tôi sẽ giả định, dựa trên câu hỏi bạn đã hỏi tại đây bạn đã thích trong các nhận xét bạn đã cung cấp toàn bộ truy vấn (không có trường nào khác mà bạn lấy ra chỉ để hiển thị mã mẫu)
do đó, nếu bạn chỉ cần các trường được chỉ định trong SELECT
, bạn có thể tối ưu hóa truy vấn của mình một chút:
trước hết, bạn đang tham gia với host_machines
chỉ để liên kết cameras
và events
, nhưng có cùng một khóa host_machines_idhost_machines
trên cả hai, vì vậy điều đó không cần thiết, bạn có thể trực tiếp:
INNER JOIN events events
ON (events.host_machines_idhost_machines =
cameras.host_machines_idhost_machines))
thứ hai, tham gia với ispy.staff
, trường được sử dụng duy nhất là idreceptionist
trong WHERE
mệnh đề, trường đó tồn tại trong events
cũng như để chúng tôi có thể bỏ nó hoàn toàn
truy vấn cuối cùng ở đây:
SELECT videos.idvideo, videos.filelocation, events.event_type, events.event_timestamp
FROM videos videos
INNER JOIN cameras cameras
ON videos.cameras_idcameras = cameras.idcameras
INNER JOIN events events
ON events.host_machines_idhost_machines =
cameras.host_machines_idhost_machines
WHERE (events.staff_idreceptionist = 182)
AND (events.event_type IN (23, 24))
AND (events.event_timestamp BETWEEN videos.start_time
AND videos.end_time)
sẽ xuất ra các bản ghi giống như bản ghi trong câu hỏi của bạn, không có bất kỳ hàng nhận dạng nào
một số video trùng lặp sẽ vẫn tồn tại do mối quan hệ từ một đến nhiều giữa cameras
và events
bây giờ về phía bạn,
bạn phải xác định một số mối quan hệ trên Video mô hình
// this is pretty straight forward, `videos`.`cameras_idcameras` links to a
// single camera (one-to-one)
public function getCamera(){
return $this->hasOne(Camera::className(), ['idcameras' => 'cameras_idcameras']);
}
// link the events table using `cameras` as a pivot table (one-to-many)
public function getEvents(){
return $this->hasMany(Event::className(), [
// host machine of event => host machine of camera (from via call)
'host_machines_idhost_machines' => 'host_machines_idhost_machines'
])->via('camera');
}
VideoController và chính chức năng tìm kiếm
public function actionIndex() {
// this will be the query used to create the ActiveDataProvider
$query =Video::find()
->joinWith(['camera', 'events'], true, 'INNER JOIN')
->where(['event_type' => [23, 24], 'staff_idreceptionist' => 182])
->andWhere('event_timestamp BETWEEN videos.start_time AND videos.end_time');
$dataProvider = new ActiveDataProvider([
'query' => $query,
]);
return $this->render('index', [
'dataProvider' => $dataProvider,
]);
}
yii sẽ coi mỗi video là một bản ghi duy nhất (dựa trên pk), điều đó có nghĩa là tất cả các video trùng lặp đều bị xóa. bạn sẽ có các video đơn lẻ, mỗi video có nhiều sự kiện nên bạn sẽ không thể sử dụng 'event_type'
và 'event_timestamp'
trong chế độ xem nhưng bạn có thể khai báo một số cửa sổ bên trong Video mô hình để hiển thị thông tin đó:
public function getEventTypes(){
return implode(', ', ArrayHelper::getColumn($this->events, 'event_type'));
}
public function getEventTimestamps(){
return implode(', ', ArrayHelper::getColumn($this->events, 'event_timestamp'));
}
và chế độ xem sử dụng:
<?= GridView::widget([
'dataProvider' => $dataProvider,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
'idvideo',
'eventTypes',
'eventTimestamps',
'filelocation',
//['class' => 'yii\grid\ActionColumn'],
],
]); ?>
chỉnh sửa :
nếu bạn muốn giữ video trùng lặp, hãy khai báo hai cột từ events
bên trong Video mô hình
public $event_type, $event_timestamp;
giữ nguyên GridView
thiết lập và thêm select
và indexBy
này cho truy vấn bên trong VideoController :
$q = Video::find()
// spcify fields
->addSelect(['videos.idvideo', 'videos.filelocation', 'events.event_type', 'events.event_timestamp'])
->joinWith(['camera', 'events'], true, 'INNER JOIN')
->where(['event_type' => [23, 24], 'staff_idreceptionist' => 182])
->andWhere('event_timestamp BETWEEN videos.start_time AND videos.end_time')
// force yii to treat each row as distinct
->indexBy(function () {
static $count;
return ($count++);
});
cập nhật
một nhân viên staff
trực tiếp liên quan đến Video
hiện hơi có vấn đề vì cách đó hơn một bảng. Có một vấn đề về nó đây
tuy nhiên, bạn thêm staff
bằng cách liên kết nó với Sự kiện mô hình,
public function getStaff() {
return $this->hasOne(Staff::className(), ['idreceptionist' => 'staff_idreceptionist']);
}
điều đó sẽ cho phép bạn truy vấn như sau:
->joinWith(['camera', 'events', 'events.staff'], true, 'INNER JOIN')
Lọc sẽ yêu cầu một số cập nhật nhỏ trên bộ điều khiển, chế độ xem và SarchModel
đây là cách triển khai tối thiểu:
class VideoSearch extends Video
{
public $eventType;
public $eventTimestamp;
public $username;
public function rules() {
return array_merge(parent::rules(), [
[['eventType', 'eventTimestamp', 'username'], 'safe']
]);
}
public function search($params) {
// add/adjust only conditions that ALWAYS apply here:
$q = parent::find()
->joinWith(['camera', 'events', 'events.staff'], true, 'INNER JOIN')
->where([
'event_type' => [23, 24],
// 'staff_idreceptionist' => 182
// im guessing this would be the username we want to filter by
])
->andWhere('event_timestamp BETWEEN videos.start_time AND videos.end_time');
$dataProvider = new ActiveDataProvider(['query' => $q]);
if (!$this->validate())
return $dataProvider;
$this->load($params);
$q->andFilterWhere([
'idvideo' => $this->idvideo,
'events.event_type' => $this->eventType,
'events.event_timestamp' => $this->eventTimestamp,
'staff.username' => $this->username,
]);
return $dataProvider;
}
}
người điều khiển:
public function actionIndex() {
$searchModel = new VideoSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
return $this->render('test', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
]);
}
và chế độ xem
use yii\grid\GridView;
use yii\helpers\ArrayHelper;
echo GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
'idvideo',
'filelocation',
[
'attribute' => 'eventType', // from VideoSearch::$eventType (this is the one you filter by)
'value' => 'eventTypes' // from Video::getEventTypes() that i suggested yesterday
// in hindsight, this could have been named better, like Video::formatEventTypes or smth
],
[
'attribute' => 'eventTimestamp',
'value' => 'eventTimestamps'
],
[
'attribute' => 'username',
'value' => function($video){
return implode(', ', ArrayHelper::map($video->events, 'idevent', 'staff.username'));
}
],
//['class' => 'yii\grid\ActionColumn'],
],
]);