ActiveDataProvider + multiple select + having

Предварительное обсуждение найденных ошибок перед отправкой их авторам фреймворка, а также внесение новых предложений.
Ответить
Demon_id
Сообщения: 421
Зарегистрирован: 2011.10.29, 00:13

ActiveDataProvider + multiple select + having

Сообщение Demon_id »

Решил помочь человеку в этой теме viewtopic.php?f=19&t=22567 , и уткнулся в ту же проблему.
На мой взгляд это баг. Заключается он в следующем:
Если собрать запрос так, чтобы в его селекте оказались несуществующие в таблице поля, потом сделать по одному из них HAVING, то получим эксепшн, примерно такой:

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

SQLSTATE[42S22]: Column not found: 1054 Unknown column 'age' in 'having clause'
The SQL being executed was: SELECT COUNT(*) FROM `user` HAVING age=1

Error Info: Array
(
    [0] => 42S22
    [1] => 1054
    [2] => Unknown column 'age' in 'having clause'
Пример сборки датапровайдера:

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

public function search($params)
{
    $query = User::find();
    $dataProvider = new ActiveDataProvider([
        'query' => $query,
    ]);
    $this->load($params);

    if (!$this->validate()) {
        // uncomment the following line if you do not want to any records when validation fails
        // $query->where('0=1');
        return $dataProvider;
    }

    $query->addSelect(
        [
            '*',
            'age'=>new \yii\db\Expression('NOW()')    // возьмём простое sql выражение для примера
        ]);

    $query->andHaving('age=1');        // в хевин тоже поставим простое сравнение не несущее смысла в реальном мире

    return $dataProvider;
}
А проблема у нас в следующем. В коде класса yii\data\ActiveDataProvider есть метод, который считает кол-во всех строк в провайдере. Вот он:

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

protected function prepareTotalCount()
{
    if (!$this->query instanceof QueryInterface) {
        throw new InvalidConfigException('The "query" property must be an instance of a class that implements the QueryInterface e.g. yii\db\Query or its subclasses.');
    }
    $query = clone $this->query;
    return (int) $query->limit(-1)->offset(-1)->orderBy([])->count('*', $this->db);
}
Таким образом, count выбрасывает из select всё кроме *. но совершенно не заботится о том, что делать с having при этом.

zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: ActiveDataProvider + multiple select + having

Сообщение zelenin »

для сложных случаев надо самостоятельно считать тотал и setTotalCount()

Demon_id
Сообщения: 421
Зарегистрирован: 2011.10.29, 00:13

Re: ActiveDataProvider + multiple select + having

Сообщение Demon_id »

да, если провайдеру самому посчитать $dataProvider->totalCount = ...; то проблема решается. но это как минимум не очевидно.

zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: ActiveDataProvider + multiple select + having

Сообщение zelenin »

Demon_id писал(а):да, если провайдеру самому посчитать $dataProvider->totalCount = ...; то проблема решается. но это как минимум не очевидно.
а как вы очевидность вычисляете?)

Demon_id
Сообщения: 421
Зарегистрирован: 2011.10.29, 00:13

Re: ActiveDataProvider + multiple select + having

Сообщение Demon_id »

zelenin писал(а):
Demon_id писал(а):да, если провайдеру самому посчитать $dataProvider->totalCount = ...; то проблема решается. но это как минимум не очевидно.
а как вы очевидность вычисляете?)
очевидное написано в доках и/или мануале. или продиктовано внешними правилами, например правилами языка php. а тут случай - пока не соберёшь пример, да не полезешь в код фреймворка смотреть что к чему, не разберёшься.

zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: ActiveDataProvider + multiple select + having

Сообщение zelenin »

Demon_id писал(а):
zelenin писал(а):
Demon_id писал(а):да, если провайдеру самому посчитать $dataProvider->totalCount = ...; то проблема решается. но это как минимум не очевидно.
а как вы очевидность вычисляете?)
очевидное написано в доках и/или мануале. или продиктовано внешними правилами, например правилами языка php. а тут случай - пока не соберёшь пример, да не полезешь в код фреймворка смотреть что к чему, не разберёшься.
все в доках не описано. все, кто разбираются в yii выше среднего, понимают, что в доках описаны только базовые вещи, концепт, назовем это так.

Demon_id
Сообщения: 421
Зарегистрирован: 2011.10.29, 00:13

Re: ActiveDataProvider + multiple select + having

Сообщение Demon_id »

zelenin писал(а): все в доках не описано. все, кто разбираются в yii выше среднего, понимают, что в доках описаны только базовые вещи, концепт, назовем это так.
Ну я за 20 минут понял что к чему. Человек вон 5 дней сидит без результата. Разве это хорошо?

zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: ActiveDataProvider + multiple select + having

Сообщение zelenin »

Demon_id писал(а): Ну я за 20 минут понял что к чему.
это ок
Demon_id писал(а):Человек вон 5 дней сидит без результата. Разве это хорошо?
это никак. просто уровень разработчика дотягивает до того, чтобы впендюрить в запрос дополниельное поле, но недотягивает до решения возникшей из-за этого проблемы.

Если зайти любой класс, мы увидим кучу публичных полей и методов, которые соотвественно можно как-то использовать.
Для понимания как все это использовать, есть два вида документации:
1. Базовая, концептуальная, мануал
2. Документация по апи (она же комментарии в коде, из которых собственно она и генерится). Там как раз описаны моменты касательно этих totalCount.

Ответить