Mougrim
(Rinat)
March 31, 2010, 1:50pm
1
Выполняю поиск в модели Object
$aConditions['join'] = 'LEFT JOIN block_values dt_published ON dt_published.object_id = t.id';
$aConditions['condition'] = 'dt_published.block_id = 3 AND dt_published.val_date > "2010-01-01"';
Потом вывожу на экран id полученного объекта, получаю id записи из таблицы block_values.
Нашел следующее решение:
$aConditions['select'] = 't.*';
Но так писать каждый раз не есть хорошо.
Подскажите, это баг ActiveRecord-а или можно еще как-то решить эту проблему более изящно?
vamp
(Vamphouse)
March 31, 2010, 2:34pm
2
Выполняю поиск в модели Object
$aConditions['join'] = 'LEFT JOIN block_values dt_published ON dt_published.object_id = t.id';
$aConditions['condition'] = 'dt_published.block_id = 3 AND dt_published.val_date > "2010-01-01"';
Потом вывожу на экран id полученного объекта, получаю id записи из таблицы block_values.
Нашел следующее решение:
$aConditions['select'] = 't.*';
Но так писать каждый раз не есть хорошо.
Подскажите, это баг ActiveRecord-а или можно еще как-то решить эту проблему более изящно?
по дефолту для таблицы (к которой применяется критерия и find/findAll()) алиас = "t" если в критерии не указано иное
Mougrim
(Rinat)
April 1, 2010, 9:01am
3
Не понял, какое отношение это имеет к вопросу.
vamp
(Vamphouse)
April 1, 2010, 10:29am
4
непосредственное, так как по-моему:
[list=1]
[*]либо запрос выполняется не у модели Object
[*]либо для block_values некорректно указан alias=>‘t’
[/list]
покажите полностью запрос (если есть - используемые скопы), а не только условия
Mougrim
(Rinat)
April 2, 2010, 6:42am
5
vamp:
непосредственное, так как по-моему:
[list=1]
[*]либо запрос выполняется не у модели Object
[*]либо для block_values некорректно указан alias=>‘t’
[/list]
покажите полностью запрос (если есть - используемые скопы), а не только условия
Алиас t используется для модели Object, т.е. для таблицы objects. Для таблицы block_values указан алиас dt_published, как это видно из параметра JOIN.
Поиск происходит так:
$oObject = Object::model()->findAll($aConditions);
Вот запрос, который при этом генерирует CActiveRecord:
SELECT * FROM objects
t
LEFT JOIN block_values dt_published ON dt_published.object_id = t.id WHERE dt_published.block_id = 3 AND dt_published.val_date > "2010-01-01"
Далее:
echo $oObject->id;
Выводит на экран id записи из таблицы block_values, а не objects.
vamp
(Vamphouse)
April 2, 2010, 7:35am
6
Mougrim:
Алиас t используется для модели Object, т.е. для таблицы objects. Для таблицы block_values указан алиас dt_published, как это видно из параметра JOIN.
Поиск происходит так:
$oObject = Object::model()->findAll($aConditions);
Вот запрос, который при этом генерирует CActiveRecord:
SELECT * FROM objects
t
LEFT JOIN block_values dt_published ON dt_published.object_id = t.id WHERE dt_published.block_id = 3 AND dt_published.val_date > "2010-01-01"
Далее:
echo $oObject->id;
Выводит на экран id записи из таблицы block_values, а не objects.
по логике работы AR он не генерирует алиасы для филдов выбираемых таблиц, если не добавлено ни одного отношения…
т.е. в вашем случае я сделал бы один из пунктов:
[list=1]
[*]relation blockValues (HAS_MANY) в object
[*]добавил
public function defaultScope(){
return array(
'select'=>$this->getTableAlias().'.*',
);
}
либо добавил бы в scopes и в запросе использовал
[/list]
вам выбирать
Mougrim
(Rinat)
April 2, 2010, 8:24am
7
Т.е. это все таки баг. По идее при использовании join, AR должна использовать алиас.
Первый способ на прокатывает, т.к. может понадобиться несколько раз вызывать blockValues, и при этом использовать их под разными алиасами.
Спасибо за помощь.
vamp
(Vamphouse)
April 2, 2010, 8:40am
8
почему же!?
это первое:
with(array(
'blockValues'=>array(
'alias' => 'myCustomAlias',
'condition' => 'x=1',
)
))
но вы правы, несколько раз не получится использовать (дополнительные withЫ будут мержится, рекурсивно с учетом имени отношения [по патчу, который еще не применен issue и patch, на текущий момент последующий вызов with() мержится используя CMap::mergeArray()] - если вы только руками не будете мержить их… т.е. $model->getDbCriteria()->mergeWith(…,$useAnd=false)), но это избавит от необходимости указывания select=‘t.*’ (+если не секрет, в каком случае вы связываете несколько раз blockValues - опишите задачу, просто интересно)
а второе… что при использовании join - вы сами определяете необходимый набор полей для выборки, если бы это было не так, тогда были бы жалобы: “куда исчезают филды, которые у меня выбираются?”, т.к. у CActiveRecord есть возможность биндить результаты поиска на публично-доступные для записи проперти модели (а не аттрибуты, которые имеет таблица модели)
Mougrim
(Rinat)
April 2, 2010, 11:31am
9
vamp:
почему же!?
это первое:
with(array(
'blockValues'=>array(
'alias' => 'myCustomAlias',
'condition' => 'x=1',
)
))
но вы правы, несколько раз не получится использовать (дополнительные withЫ будут мержится, рекурсивно с учетом имени отношения [по патчу, который еще не применен issue и patch, на текущий момент последующий вызов with() мержится используя CMap::mergeArray()] - если вы только руками не будете мержить их… т.е. $model->getDbCriteria()->mergeWith(…,$useAnd=false)), но это избавит от необходимости указывания select=‘t.*’ (+если не секрет, в каком случае вы связываете несколько раз blockValues - опишите задачу, просто интересно)
а второе… что при использовании join - вы сами определяете необходимый набор полей для выборки, если бы это было не так, тогда были бы жалобы: “куда исчезают филды, которые у меня выбираются?”, т.к. у CActiveRecord есть возможность биндить результаты поиска на публично-доступные для записи проперти модели (а не аттрибуты, которые имеет таблица модели)
Задача не простая, здесь ее описать будет не просто)
Идя взята отсюда - http://misha.design.ru/hobby/progr/engine4.html
Но уже притерпела много изменений.
А насчет join, AR должна корректно определять, какой id к какой записи относится, т.е. учитывать такой случай, когда у таблиц есть поля с одинаковым именем.