Yii1 search () по соотношению многие-многие возвращает только одну связанную модель - PullRequest
0 голосов
/ 07 мая 2019

У меня есть 3 таблицы: clients, traders и client_trader_relation

у клиентов может быть много трейдеров, а у трейдеров может быть много клиентов, так что это МНОЖЕСТВЕННОЕ отношение с "опорой"Таблица.Отношение определяется в модели клиентов следующим образом:

$relations = array(
        'traders' => array(self::MANY_MANY, 'traders', 'client_trader_relation(client_id, trader_id)'),
);

Теперь все работает правильно при отображении списка всех клиентов, скажем, в CGridView, но я также хочу иметь возможность искать клиентов по конкретному трейдеру(поэтому, если один из трейдеров, скажем, id 10, верните этого клиента).

Я сделал это так в функции search () модели:

public function search()
{
    $criteria=new CDbCriteria;

    $criteria->with = 'traders';
    $criteria->together = true;
    $criteria->compare('traders.id', $this->search_trader);
}

search_traderэто дополнительная переменная, добавленная в модель и правила, чтобы ее можно было использовать для поиска.Несмотря на то, что это работает, он успешно возвращает всех клиентов указанного трейдера, но результат не содержит других связанных трейдеров, кроме того, который я ищу.Я могу понять это поведение, потому что именно так работает сгенерированный SQL.

Мне любопытно, есть ли способ вернуть всех трейдеров из такого поиска без необходимости делать какие-либодополнительные запросы / функции?Если нет, то каков будет правильный способ сделать это?На данный момент я могу думать только о некоторой функции в модели, такой как getAllTraders(), которая будет вручную запрашивать все traders, связанные с текущим клиентом.Это сработало бы, я мог бы использовать эту функцию для отображения списка трейдеров, но это привело бы к дополнительному запросу и дополнительному коду.

1 Ответ

0 голосов
/ 07 мая 2019

Вы можете использовать это для отключения активной загрузки:

$this->with(['traders' => ['select' => false]]);

Но это создаст отдельный запрос для каждой строки, поэтому с 20 клиентами в GridView вы получите дополнительные 20 запросов. AFAIK нет простого и понятного способа сделать это эффективно. Самый простой обходной путь - определить дополнительную связь, которая будет использоваться для получения нефильтрованных трейдеров, использующих энергичную загрузку:

public function relations() {
    return [
        'traders' => [self::MANY_MANY, 'traders', 'client_trader_relation(client_id, trader_id)'],
        'traders2' => [self::MANY_MANY, 'traders', 'client_trader_relation(client_id, trader_id)'],
    ];
}

И затем определить with настройки для активной загрузки:

$this->with([
    'traders' => ['select' => false],
    'traders2',
]);

Затем вы можете использовать $client->traders2, чтобы получить полный список трейдеров.


Вы также можете определить это отношение ad-hoc вместо relations():

$this->getMetaData()->addRelation(
    'traders2',
    [self::MANY_MANY, 'traders', 'client_trader_relation(client_id, trader_id)']
);
...