Вы должны проверить WHERE imageCount.image_count IS NULL
вместо WHERE imageCount.image_count=0
, поскольку те строки, которые не имеют связанных изображений, будут отображаться как null
в image_count
и изменить условие с
$query->andFilterWhere(['imageCount.image_count' => 0]);
до
$query->andWhere(['is','imageCount.image_count',new \yii\db\Expression('null')]);`
Ваш запрос должен быть сгенерирован как
SELECT `item`.* FROM `item`
LEFT JOIN
(
SELECT `item_id`, COUNT(id) as image_count
FROM `image`
GROUP BY `item_id`
) `imageCount`
ON imageCount.item_id = id
WHERE `imageCount`.`image_count` is NULL
Обновление
Поскольку у вас все еще возникают проблемы,Я подумал, что у меня есть свободное время, чтобы найти эту проблему, и у меня возникло следующее
У вас возникли проблемы при фильтрации по элементам, имеющим 0 для изображений. У меня нет точной схемы, которую выесть, но я приведу пример ниже с похожим сценарием, где у меня есть Shoots
и связанные с ним теги в соединительной таблице ShootTag
модель
Ниже приведен пример схемы и данных
+----+------------+--------+------------+
| id | name | active | shoot_type |
+----+------------+--------+------------+
| 1 | aslam omer | 1 | modeling |
| 2 | asif | 1 | modeling |
| 3 | saleem | 1 | modeling |
| 4 | sajid | 1 | modeling |
| 5 | tasleem | 1 | modeling |
| 6 | tehseen | 1 | modeling |
| 7 | amjad | 1 | modeling |
| 8 | shaban | 1 | modeling |
| 9 | irfan | 1 | modeling |
+----+------------+--------+------------+
Ниже приведен пример схемы и данных
+----------+--------+
| shoot_id | tag_id |
+----------+--------+
| 1 | 1 |
| 1 | 2 |
| 1 | 3 |
| 1 | 4 |
| 2 | 1 |
| 2 | 2 |
| 2 | 3 |
| 3 | 1 |
| 4 | 1 |
| 4 | 4 |
+----------+--------+
Теперь, учитывая приведенные выше таблицы и данные, у меня есть поисковая модель с именем ShootsSearch
, которую я использую.g, чтобы отобразить все снимки, и я хочу показать количество тегов для каждого снимка, сохраненного в модели ShootTag
.
Я не добавляю код для GridView, так как он не имеет значения, мойПоисковая модель ShootsSearch
имеет следующий метод поиска, который работает правильно для любого подсчета по отношению к выстрелам в модели меток.
Что отличается от вашего кода тем, что я использую модель ShootsSearch
для первого запроса, а не модель Shoots
, так как вы используете Item::find();
, который должен быть ItemSearch::find();
вместо этого в качестве псевдонима, который вы используете image_count
, объявляется в модели поиска,
Затем строка new Expression('if(st.totalTags is NOT NULL,st.totalTags,0) as totalTags')
в основном запросе должна отображать нулевые значения как 0так что вы можете использовать условный выбор здесь.
Затем вам нужно проверить if ($this->totalTags == '0') {
для применения $query->andWhere(['IS', 'totalTags', new Expression('null')]);
, поскольку фактическое значение будет null
для totalTags
, гденикакие теги недоступны для любых Shoot
, а в остальной части вы будете использовать query->andFilterWhere(['=', 'totalTags', $this->totalTags]);
. Это работает правильно во всех трех сценариях, которые вы хотите видеть на изображениях ниже
Вид по умолчанию в первый раз
Поиск снимков с общим количеством тегов 4
Поиск снимков с счетчиком TotalTags 0
Вы должнызамените следующее в своем коде
public $totalTags
на public $image_count
. ShootTags
на Image
. shoot_id
на item_id
. ShootsSearch
с ItemSearch
/ self
.
Вот модель поиска, код проверен и работает.
class ShootsSearch extends Shoots
{
/**
* @var mixed
*/
public $totalTags;
/**
* {@inheritdoc}
*/
public function rules()
{
return [
[['id', 'active', 'totalTags'], 'integer'],
[['name', 'shoot_type', 'description', 'totalTags'], 'safe']
];
}
/**
* {@inheritdoc}
*/
public function scenarios()
{
// bypass scenarios() implementation in the parent class
return Model::scenarios();
}
/**
* Creates data provider instance with search query applied
*
* @param array $params
*
* @return ActiveDataProvider
*/
public function search($params)
{
$subQuery = ShootTag::find()->select(
[
new Expression('shoot_id, COUNT(shoot_id) as totalTags')
]
)->groupBy('shoot_id');
$query = ShootsSearch::find()->alias('s')
->select(
[
's.*',
new Expression('if(st.totalTags is NOT NULL,st.totalTags,0) as totalTags')
]
)->leftJoin(['st' => $subQuery], 'st.shoot_id=s.id');
// add conditions that should always apply here
$dataProvider = new ActiveDataProvider(
[
'query' => $query
]
);
$this->load($params);
if (!$this->validate()) {
// uncomment the following line if you do not want to return any records when validation fails
// $query->where('0=1');
return $dataProvider;
}
// grid filtering conditions
$query->andFilterWhere([
'id' => $this->id,
'active' => $this->active
]);
$query->andFilterWhere(['like', 'name', $this->name])
->andFilterWhere(['like', 'shoot_type', $this->shoot_type])
->andFilterWhere(['like', 'description', $this->description]);
if ($this->totalTags == '0') {
$query->andWhere(['IS', 'totalTags', new Expression('null')]);
} else {
$query->andFilterWhere(['=', 'totalTags', $this->totalTags]);
}
return $dataProvider;
}
}