2015-10-26 2 views
1

Имея некоторые проблемы с активной записью Yii2.Yii 2 Активная запись hasMany с LeftJoin

Я хотел бы установить отношение hasMany, которое включает левое соединение, однако при этом запись заполняется только одним объектом отношения.

Вот текущий код - копирование вставляемого исполняемого запроса из Yii debug в navicat определенно возвращает несколько результатов.

public function getx() 
{ 

    return $this->hasMany(x::className(),['x' => 'x']) 
     ->viaTable('a', ['arId' => 'arId'], function ($query){ 


      $query->leftJoin('a b', 'a.type = b.type AND a.val < b.val') 
       ->andWhere('a.foo IN (0,1,2,3)') 
       ->andWhere('a.bar IN ((0,1,2,3)') 
       ->andWhere('a.moo IN ((0,1,2,3)') 
       ->andWhere('b.val IS NULL'); 
     } 
     ); 

} 

Следующий код, однако, работает нормально (заданы разные запросы).

return $this->hasMany(x::className(),['x' => 'x']) 
     ->viaTable('a', ['arId' => 'arId'], function ($query){ 

      $query->andWhere(['and', ['foo' => [0,1,2,3]], 
        ['bar' => [0,1,2,3]], 
        ['moo' => [0,1,2,3]], 
       ] 
       ); 
      } 
     ); 

Он вызывается в контроллере со следующим:

$rs = ar::find(1)->with('x')->all(); 

Этот вопрос явно объединение - может кто-нибудь просветить меня, почему это так?

+0

вы можете использовать отладчик и создать контрольную точку, чтобы увидеть 'SQL' команду,' leftJoin' является создание ??? –

+0

Да, в отладчике yii он показывает полный запрос и вставляет его в navicat, дает мне желаемые результаты, т.е. возвращает несколько строк. – Zac

+0

, честно говоря, я не знаю, как этот 'leftjoin' работает, поскольку вы пропускаете 2 названия таблиц a и b без разделителя или чего-то еще. Дайте мне немного времени и позвольте мне попробовать демо в моем проекте и вернемся к вам. –

ответ

-1

Итак, вот ответ!

Если есть присоединиться к вам нужно указать indexBy() в другой мудрой следующий код:

db\ActiveQuery ln 224

if (!empty($this->join) && $this->indexBy === null) { 
     $models = $this->removeDuplicatedModels($models); 
    } 

отправит вас в функцию removeDuplicatedModels().

Эта функция проверяет первичный ключ от параметра modelclass, а затем удаляет любые дубликаты. Однако таблица соединений ожидает нескольких первичных элементов (от родительской активной записи), поскольку это отношение hasMany(). Таким образом, вам необходимо переопределить эту проверку, установив параметр indexBy на нужный первичный ключ.

Ниже код будет работы:

public function getx() 
{ 

    return $this->hasMany(x::className(),['xId' => 'xId']) 
     ->viaTable('a', ['arId' => 'arId'], function ($query){ 
      $query->leftJoin('a b', 'a.type = b.type AND a.val < b.val') 
       ->andWhere('a.foo IN (0,1,2,3)') 
       ->andWhere('a.bar IN ((0,1,2,3)') 
       ->andWhere('a.moo IN ((0,1,2,3)') 
       ->andWhere('b.val IS NULL') 
       ->indexBy('xId') 
     } 
     ); 

} 
Смежные вопросы