activequery count

Общие вопросы по использованию второй версии фреймворка. Если не знаете как что-то сделать и это про Yii 2, вам сюда.
Ответить
iamguruman
Сообщения: 236
Зарегистрирован: 2018.05.10, 08:26

activequery count

Сообщение iamguruman »

Код: Выделить всё

class MenuProcessing
{

    public static function ret($where = []){

        $ret = [];

        $ret [] = "<ul>Обработка ткани";

        $fabrics = new NomFabrics();

        /** @var NomFabrics $attribute */
        foreach ($fabrics->attributes as $key => $value){

            $count = 0;

            if(strpos($key, 'processing_') !== false){

                $count = NomFabrics::find();

                $count->andWhere([$key =>  1]);

                foreach ($where as $wherekey => $wherevalue){
                    $count->andFilterWhere([
                        $wherekey => $wherevalue,
                    ]);
                }

                $count->count();

                die("<pre>".print_r($count));

                if($count > 0){
                    $ret [] = "<li>".
                        Html::a($fabrics->getAttributeLabel($key),
                            ['/all', 'processing' => str_replace("processing_", "", $key)]
                        )
                        ." ({$count})</li>";
                }
            }

        }

        $ret [] = "</ul>";

        return implode('', $ret);

    }

}
вызываю меню так:

Код: Выделить всё

            <?= \app\components\MenuProcessing::ret(['use_tulle' => 1]) ?>
строю меню,
в некоторых местах мне нужно его использовать с дополнительным параметром фильтра
я придумал так, в функцию передаю дополнительное условие и делаю подсчет значений,
но мне кажется count() так не работает,
потому что возвращает мне не значение 1...2... и т.д
а вовзрает такое:

Код: Выделить всё

app\models\NomFabricsQuery Object ( [sql] => [on] => [joinWith] => [select] => [selectOption] => [distinct] => [from] => Array ( [0] => m_noms__fabrics ) [groupBy] => [join] => [having] => [union] => [withQueries] => [params] => Array ( ) [queryCacheDuration] => [queryCacheDependency] => [_events:yii\base\Component:private] => Array ( ) [_eventWildcards:yii\base\Component:private] => Array ( ) [_behaviors:yii\base\Component:private] => Array ( ) [where] => Array ( [processing_print] => 1 ) [limit] => [offset] => [orderBy] => [indexBy] => [emulateExecution] => [modelClass] => app\models\NomFabrics [with] => [asArray] => [multiple] => [primaryModel] => [link] => [via] => [inverseOf] => [viaMap:yii\db\ActiveQuery:private] => )
1
но и ... в возврате не приходит 'use_tulle' => 1, которое я пытаюсь вставить в foreach:

Код: Выделить всё

foreach ($where as $wherekey => $wherevalue){
                    $count->andFilterWhere([
                        $wherekey => $wherevalue,
                    ]);
                }
не могу понять как мне вернуть количество count() и вставить use_tulle в запрос проверки...

идея хорошая... а вот реализация... явно я неправильно делаю... не понимаю...

я так думаю что мой запрос активквери с foreach $where как-то обернуть в датапровайдер может быть...

подскажите плиз
iamguruman
Сообщения: 236
Зарегистрирован: 2018.05.10, 08:26

Re: activequery count

Сообщение iamguruman »

с use_tulle разобрался...

остлось понять как мне вернуть значение вместо

Код: Выделить всё

app\models\NomFabricsQuery Object ( [sql] => [on] => [joinWith] => [select] => [selectOption] => [distinct] => [from] => Array ( [0] => m_noms__fabrics ) [groupBy] => [join] => [having] => [union] => [withQueries] => [params] => Array ( ) [queryCacheDuration] => [queryCacheDependency] => [_events:yii\base\Component:private] => Array ( ) [_eventWildcards:yii\base\Component:private] => Array ( ) [_behaviors:yii\base\Component:private] => Array ( ) [where] => Array ( [processing_print] => 1 ) [limit] => [offset] => [orderBy] => [indexBy] => [emulateExecution] => [modelClass] => app\models\NomFabrics [with] => [asArray] => [multiple] => [primaryModel] => [link] => [via] => [inverseOf] => [viaMap:yii\db\ActiveQuery:private] => )
1
подскажите плиз
iamguruman
Сообщения: 236
Зарегистрирован: 2018.05.10, 08:26

Re: activequery count

Сообщение iamguruman »

я я активквери заменил на такой запрос:

Код: Выделить всё

                $sql = "select count(*) from fabrics where {$key} = 1 ";
                if(count($where) > 0){
                    foreach ($where as $wherekey => $wherevalue){
                        $sql .= " and $wherekey = $wherevalue ";
                    }
                }
                $count = \Yii::$app->db->createCommand($sql)->queryScalar();
результат есть, но как получить по первому варианту 1 вместо объекта?
unknownby
Сообщения: 749
Зарегистрирован: 2019.11.05, 16:34
Контактная информация:

Re: activequery count

Сообщение unknownby »

А для чего у тебя это?

Код: Выделить всё

die("<pre>".print_r($count));
Как по мне, то формирование меню у тебя слишком уж хардкодное
Почему-то уверен, что можно реализовать твою идею намного проще :)
iamguruman
Сообщения: 236
Зарегистрирован: 2018.05.10, 08:26

Re: activequery count

Сообщение iamguruman »

:-) ну это я его отлаживал... хочу через активквери получить каунт а не через запрос...
как в активквери получить значение count()?..

Код: Выделить всё

            if(strpos($key, 'processing_') !== false){

                $count = NomFabrics::find();

                $count->andWhere([$key =>  1]);

                foreach ($where as $wherekey => $wherevalue){
                    $count->andFilterWhere([
                        $wherekey => $wherevalue,
                    ]);
                }

                $count->count();

                die("<pre>".print_r($count));
результат такой:

Код: Выделить всё

app\models\NomFabricsQuery Object ( [sql] => [on] => [joinWith] => [select] => [selectOption] => [distinct] => [from] => Array ( [0] => m_noms__fabrics ) [groupBy] => [join] => [having] => [union] => [withQueries] => [params] => Array ( ) [queryCacheDuration] => [queryCacheDependency] => [_events:yii\base\Component:private] => Array ( ) [_eventWildcards:yii\base\Component:private] => Array ( ) [_behaviors:yii\base\Component:private] => Array ( ) [where] => Array ( [processing_print] => 1 ) [limit] => [offset] => [orderBy] => [indexBy] => [emulateExecution] => [modelClass] => app\models\NomFabrics [with] => [asArray] => [multiple] => [primaryModel] => [link] => [via] => [inverseOf] => [viaMap:yii\db\ActiveQuery:private] => )
1
а мне бы просто получить значение count()

подкажите плиз :P
unknownby
Сообщения: 749
Зарегистрирован: 2019.11.05, 16:34
Контактная информация:

Re: activequery count

Сообщение unknownby »

Конструкция должна вывести всё, что есть количество. Если не выводит, то проблема где-то в другом.
Может переписан метод find внутри модели или еще что.

Код: Выделить всё

$count = NomFabrics::find()->count();
var_dump($count);
Для начала нужно отдебажить данную конструкцию, если выдает правильно, прибавляем остальное.

И для чего вообще второй foreach? Если передается уже массив "ключ - значение". Должно так сработать.

Код: Выделить всё

$count->andFilterWhere([$where]);
esamokhov
Сообщения: 2
Зарегистрирован: 2020.05.26, 14:47

Re: activequery count

Сообщение esamokhov »

А подскажите, пожалуйста, ActiveQuery count() каждый раз делает запрос к БД при вызове?

Скажем есть такой код:

Код: Выделить всё

 public function getArchivesRelationCount()
 {
     return $this->getArchivesRelation()->count();
 }
Правильно ли я понимаю, что при каждом вызове $model->getArchivesRelationCount(), будет производится обращение к БД.

Есть ли смысл делать как-то так:

Код: Выделить всё

 public function getArchivesRelationCount()
 {
    return $this->isRelationPopulated('archivesRelation') ? count($this->archivesRelation) : $this->getArchivesRelation()->count();
 }
Я имею ввиду проверять если данные уже загружены, то просто брать кол-во элементов в массиве, иначе вызывать обращение к БД.

Или же count() сам по себе как-то кэширует данные?

Заранее спасибо.
Последний раз редактировалось esamokhov 2020.05.26, 14:55, всего редактировалось 2 раза.
skynin
Сообщения: 400
Зарегистрирован: 2017.12.12, 10:09

Re: activequery count

Сообщение skynin »

esamokhov писал(а): 2020.05.26, 14:53 Правильно ли я понимаю, что при каждом вызове $model->getArchivesRelationCount(), будет производится обращение к БД.
Да.

Но закеширует сам результат, поэтому:

Код: Выделить всё

 public function getArchivesRelationCount()
 {
    return count($this->archivesRelation);
 }
Первый вызов getArchivesRelationCount() или обращение к атрибуту аrchivesRelationCount приведет к
к проверке archivesRelation
если пусто, к вызову
$this->getArchivesRelation() и сохранению в archivesRelation

если запрос в getArchivesRelation() сделан с помощью hasOne/hasMany

хотя, вроде и всегда сохранится...

Вобщем - сделайте тестовую страничку, где просто эти вызовы, и посмотрите в дебаг панели
а магию посмотрите в __get у классов моделей фреймворка

Полностью вручную кешировать так:

Код: Выделить всё

 public function getArchivesRelationCount()
 {
 static $cacheCount;
 if (empty($cacheCount)) {
 $cacheCount = $this->getArchivesRelation()->count();
 }
    return $cacheCount;
 }
но, помните, что это кеширование на класс, и если будут наследники, могут быть сюрпризы - "надо чтобы вызвался $this->getArchivesRelation()->count()", а он не вызывается.

Еще кеширование:
$this->getArchivesRelation()->cache(1)->count();
на 1 секунду. Но, это уже будет кеширование и для разных запросов, что может быть плохо.

для кеширования на сеанс, когда магии Yii2 недостаточно, я у себя везде использую доработку
$this->getArchivesRelation()->memCache()->count();

но ее нужно делать у своего наследника от \yii\db\Connection, и сделать свою реализацию yii\caching\Cache для этого
Не желайте странного, и не будет у вас головной боли чтобы достичь этого странного.
Тем более что окажется что оно вам и не нужно было, странное это.
esamokhov
Сообщения: 2
Зарегистрирован: 2020.05.26, 14:47

Re: activequery count

Сообщение esamokhov »

Спасибо за подробный ответ.
Ответить