В руководстве приведен нерабочий пример для реляц запроса

Предварительное обсуждение найденных ошибок перед отправкой их авторам фреймворка, а также внесение новых предложений.
Ответить
aleksp
Сообщения: 12
Зарегистрирован: 2011.07.26, 12:38

В руководстве приведен нерабочий пример для реляц запроса

Сообщение aleksp »

Точнее частично нерабочий, а именно:

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

$posts=Post::model()->with('comments:recently:approved')->findAll();
// или, начиная с версии 1.1.7
$posts=Post::model()->with(array(
    'comments'=>array(
        'scopes'=>array('recently','approved')
    ),
))->findAll();
// или, начиная с версии 1.1.7
$posts=Post::model()->findAll(array(
    'with'=>array(
        'comments'=>array(
            'scopes'=>array('recently','approved')
        ),
    ),
));
В данном случае не будет корректно отработано условие recently для связанной модели comments!
Если смотреть профилирование, то параметр LIMIT категорически отказывается добавляться.
aleksp
Сообщения: 12
Зарегистрирован: 2011.07.26, 12:38

Re: В руководстве приведен нерабочий пример для реляц запрос

Сообщение aleksp »

В моем же случае есть таблица tbl_users с пользователями, есть таблица tbl_users_log с логом действий пользователей. Задача выбрать 0,25 пользователей с последними N действиями, но выбираются все действия.

Соответствующие модели

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

class Users extends CActiveRecord
{
    public static function model($className=__CLASS__)
    {
        return parent::model($className);
    }

    public function tableName()
    {
        return 'tbl_users';
    }

    public function relations()
    {
        return array(
            'logs' => array(self::HAS_MANY, 'UsersLog', 'user_id'),
        );
    }
}


class UsersLog extends ActiveRecord
{
    public static function model($className = __CLASS__)
    {
        return parent::model($className);
    }

    public function tableName()
    {
        return 'tbl_users_log';
    }

    public function recently($limit = 10)
    {
        $this->getDbCriteria()->mergeWith(array(
            'order' => '`timestamp` DESC',
            'limit' => $limit,
        ));

        return $this;
    }
}
Собсно сам запрос:

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

        $users = Users::model()->with(array(
            'logs' => array(
                'scopes' => 'recently',
            ),
        ))->findAll(array(
               'offset' => 0,
               'limit' => 25
        ));
 
Последний раз редактировалось aleksp 2012.04.11, 16:35, всего редактировалось 1 раз.
aleksp
Сообщения: 12
Зарегистрирован: 2011.07.26, 12:38

Re: В руководстве приведен нерабочий пример для реляц запрос

Сообщение aleksp »

Итоговые запросы.

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

2012/04/11 07:55:16 [trace] [system.db.CDbCommand] Querying SQL: SELECT `t`.`id` AS `t0_c0`, `t`.`username` AS `t0_c1`, `t`.`email` AS `t0_c2`, `t`.`password` AS `t0_c3`, `t`.`first_name` AS `t0_c4`, `t`.`last_name` AS `t0_c5`, `t`.`gender` AS `t0_c6`, `t`.`birthday` AS `t0_c7`, `t`.`country` AS `t0_c8`, `t`.`role` AS `t0_c9`, `t`.`joined` AS `t0_c10`, `t`.`active_till` AS `t0_c11`, `t`.`last_visit` AS `t0_c12`, `t`.`join_ip` AS `t0_c13`, `t`.`note` AS `t0_c14`, `t`.`status` AS `t0_c15`, `t`.`state` AS `t0_c16`, `t`.`site_id` AS `t0_c17` FROM `tbl_users` `t`  ORDER BY id ASC LIMIT 25

2012/04/11 07:55:16 [trace] [system.db.CDbCommand] Querying SQL: SELECT `t`.`id` AS `t0_c0`, `logs`.`id` AS `t1_c0`, `logs`.`user_id` AS `t1_c1`, `logs`.`timestamp` AS `t1_c2`, `logs`.`user_ip` AS `t1_c3`, `logs`.`action` AS `t1_c4`, `logs`.`details` AS `t1_c5` FROM `tbl_users` `t` LEFT OUTER JOIN `tbl_users_log` `logs` ON (`logs`.`user_id`=`t`.`id`)  WHERE (`t`.`id` IN ('1', '11', '15', '16', '18', '22', '25', '27', '37', '40', '44', '45', '46', '47', '48', '49', '55', '57', '58', '59', '60', '66', '67', '69', '70')) ORDER BY `timestamp`
 
aleksp
Сообщения: 12
Зарегистрирован: 2011.07.26, 12:38

Re: В руководстве приведен нерабочий пример для реляц запрос

Сообщение aleksp »

Для большей наглядности модифицируем немного код.

В class Users, отношение logs изменим так

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

'logs' => array(self::HAS_MANY, 'UsersLog', 'user_id', 'scopes' => 'recently')
 
А теперь сравним два варианта запроса.
Первый с жадной загрузкой, тот самый, что был приведен ранее, и который должен сформировать единый запрос к базе:

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

        $users = Users::model()->with('logs')->findAll(array(
               'offset' => 0,
               'limit' => 25
        ));
 
В итоге получаем все действия пользователей! Т.е. 'scopes' => 'recently' не срабатывает.

Второй с отложенной загрузкой:

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

        $users = Users::model()->findAll(array(
               'offset' => 0,
               'limit' => 25
        ));

        foreach ($users as $id => $user)
        {
            $result['models'][$id] = $user->attributes;
            if (is_array($user->logs))
            {
                $result['models'][$id]['logs'] = array();
                foreach ($user->logs as $log) $result['models'][$id]['logs'][] = $log->attributes;
            }
        }
 
В итоге получаем что и хотели: для каждого пользователя имеем требуемое кол-во последних действий.
Ответить