Loveorigami писал(а): ↑2017.08.23, 13:01
Во вторых - а зачем Вы делаете select?
В гриде понимаются записи вида `country.name`,
если данные достали, как User::find()->joinWith('country');
Только что смоделировал ситуацию в три файла.
Данные:
u_id name c_id
111 user name 123
c_id name
123 Country name
Если данные доставать без Select
И в GridView использовать c.name, то в дебагере видим:
SELECT COUNT(*) FROM `u` LEFT JOIN `c` ON `u`.`c_id` = `c`.`c_id`
SELECT `u`.* FROM `u` LEFT JOIN `c` ON `u`.`c_id` = `c`.`c_id` LIMIT 20
SELECT * FROM `c` WHERE `c_id`=123
Если же использовать Select
Код: Выделить всё
$query = U::find()->select(['u.*', 'c_name' => 'c.name'])->joinWith('c');
указать в модеи U свойство c_name и не использовать геттер, то ... барабанная дробь .....
COUNT(*) FROM `u` LEFT JOIN `c` ON `u`.`c_id` = `c`.`c_id`
SELECT `u`.*, `c`.`name` AS `c_name` FROM `u` LEFT JOIN `c` ON `u`.`c_id` = `c`.`c_id` LIMIT 20
SELECT * FROM `c` WHERE `c_id`=123
Результата удалось добиться моим первоначальным способом, но без использования геттера для c_name, а лишь объявив public $c_name в классе U. Способ не самый изящный, т.к. заполняться значением это поле будет только при выборке в классе SearchU, в остальных случаях оно будет пустым, и из-за того, что оно public, getter уже не использовать.
Код: Выделить всё
$query = U::find()->select(['u.*', 'c_name' => 'c.name'])->leftJoin('c', 'c.c_id = u.c_id');
Для частного случая сойдет, но всё равно не особо красиво.
И в итоге я нашел, как мне кажется, идеальный вариант.
Класс U:
Код: Выделить всё
private $c_name;
....
public function getC()
{
return $this->hasOne(C::className(), ['c_id' => 'c_id']);
}
function getC_name()
{
return is_null($this->c_name) ? ($this->c ? $this->c->name : null) : $this->c_name;
}
function setC_name($c_name)
{
$this->c_name = $c_name;
}
В этом случае при выборке с джойном из базы, срабатывает сеттер, заполняя
приватную переменную c_name. Когда GridView выгребает данные - срабатывает getter, который возвращает название страны, если оно было заполнено ранее. В противном случае, для совместимости - выгребает данные через связь.
Лишний запрос может быть в том случае, если нет связанной модели (тогда c_name будет = null) и getter пойдет по связи, но это можно обойти добавив флаг признака выборки данных например:
U:
Код: Выделить всё
public $dataEquired = false;
...
function getC_name()
{
return $this->dataEquired ? $this->c_name : ($this->c ? $this->c->name : null);
}
SearchU:
Код: Выделить всё
$query = U::find()->select(['u.*', 'c_name' => 'c.name', 'dataEquired' => new \yii\db\Expression(1)])->leftJoin('c', 'c.c_id = u.c_id');