Каскадные JOIN

Общие вопросы по использованию второй версии фреймворка. Если не знаете как что-то сделать и это про Yii 2, вам сюда.
Ответить
guru_nemo
Сообщения: 68
Зарегистрирован: 2017.04.10, 21:28

Каскадные JOIN

Сообщение guru_nemo »

есть таблица заказов orders в ней есть столбцы с id товаров и id пользователей. написать запрос, чтобы получив строку из таблицы заказов ещё зацепить информацию из таблиц пользователей и товаров у меня получилось.

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

$orders = Orders::find()
				->where(['date' => $this->date])
                            ->joinWith('user')
				->joinWith('teme')
                            ->asArray()
                            ->all();
 

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

public function getUser() {
        return $this->hasOne(User::className(), ['id' => 'user'])->from('user');
    }
	
public function getTeme() {
        return $this->hasOne(Teme::className(), ['id' => 'item'])->from('teme');
    }
    
но нужна ещё инфа из таблицы профилей пользователей, которая связана с таблицей пользователей. как эти таблицы объеденить в этом же запросе?
guru_nemo
Сообщения: 68
Зарегистрирован: 2017.04.10, 21:28

Re: Каскадные JOIN

Сообщение guru_nemo »

Если добавляю
->joinWith('profile')

и

public function getProfile() {
return $this->hasOne(Profile::className(), ['user_id' => 'user'])->from('profile');
}

то из профайлов приходит NULL
guru_nemo
Сообщения: 68
Зарегистрирован: 2017.04.10, 21:28

Re: Каскадные JOIN

Сообщение guru_nemo »

проблема решилась.
надо было всего лишь поменять местами строки

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

$orders = Orders::find()
				->where(['date' => $this->date])
				->joinWith('profile')
                            ->joinWith('user')
				->joinWith('teme')
                            ->asArray()
                             ->all();
Аватара пользователя
Alexum
Сообщения: 683
Зарегистрирован: 2016.09.26, 10:00

Re: Каскадные JOIN

Сообщение Alexum »

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

$orders = Orders::find()->with(['user.profile','teme')->where(['date' => $this->date])->asArray()->all();
guru_nemo
Сообщения: 68
Зарегистрирован: 2017.04.10, 21:28

Re: Каскадные JOIN

Сообщение guru_nemo »

Alexum писал(а): 2017.10.13, 21:55

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

$orders = Orders::find()->with(['user.profile','teme')->where(['date' => $this->date])->asArray()->all();
да, так тоже работает.
а есть разница в работе этих двух записей?

можно ли как-то ограничить выборку, чтобы не вся строка целиком приходила, а только определённые поля?
Аватара пользователя
Alexum
Сообщения: 683
Зарегистрирован: 2016.09.26, 10:00

Re: Каскадные JOIN

Сообщение Alexum »

1. joinWith тут не нужен, т.к. нет условий для связанных данных, следовательно нет необходимости собирать тяжёлый запрос.
2. Получаются связи Заказ->Пользователь->Профиль пользователя. В вашем же варианте получились менее логичные связи Заказ->Пользователь, Заказ->Профиль пользователя.

Ограничить выборку можно используя подзапросы, главное помнить, что в select обязательно должно быть поле с id по которому строится связь, иначе она не соберётся и данных не будет.

Н-р:

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

$orders = Orders::find()->with(['user' => function($q) {
            $q->with(['profile' => function ($q) {
          		$q->select(['user_id','user_age']); // Для этой связи достаём возраст пользователя
            }]);
        }
])->asArray()->all();
guru_nemo
Сообщения: 68
Зарегистрирован: 2017.04.10, 21:28

Re: Каскадные JOIN

Сообщение guru_nemo »

Alexum писал(а): 2017.10.13, 22:28 1. joinWith тут не нужен, т.к. нет условий для связанных данных, следовательно нет необходимости собирать тяжёлый запрос.
2. Получаются связи Заказ->Пользователь->Профиль пользователя. В вашем же варианте получились менее логичные связи Заказ->Пользователь, Заказ->Профиль пользователя.

Ограничить выборку можно используя подзапросы, главное помнить, что в select обязательно должно быть поле с id по которому строится связь, иначе она не соберётся и данных не будет.

Н-р:

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

$orders = Orders::find()->with(['user' => function($q) {
            $q->with(['profile' => function ($q) {
          		$q->select(['user_id','user_age']); // Для этой связи достаём возраст пользователя
            }]);
        }
])->asArray()->all();
а если из каждой таблице по несколько полей, как в этом случае записать?
guru_nemo
Сообщения: 68
Зарегистрирован: 2017.04.10, 21:28

Re: Каскадные JOIN

Сообщение guru_nemo »

guru_nemo писал(а): 2017.10.13, 22:17
Alexum писал(а): 2017.10.13, 21:55

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

$orders = Orders::find()->with(['user.profile','teme')->where(['date' => $this->date])->asArray()->all();
подскажите, а как записать в ->orderBy столбцы из связанных таблиц при такой записи?
с джойнами запись ->orderBy('teme.name') даёт нужный результат.
caHek2x
Сообщения: 1242
Зарегистрирован: 2016.04.12, 20:41

Re: Каскадные JOIN

Сообщение caHek2x »

with - жадная загрузка связанных данных ПОСЛЕ запроса ...
если вы хотите использовать столбец из связанной таблицы в: условии, сортировке, короче в самом запросе, то вам нужно делать joinWith ...
guru_nemo
Сообщения: 68
Зарегистрирован: 2017.04.10, 21:28

Re: Каскадные JOIN

Сообщение guru_nemo »

caHek2x писал(а): 2017.10.15, 17:41 with - жадная загрузка связанных данных ПОСЛЕ запроса ...
если вы хотите использовать столбец из связанной таблицы в: условии, сортировке, короче в самом запросе, то вам нужно делать joinWith ...
благодарю.
Ответить