I have three database table:
product (id, name)
product_has_adv (product,advantage,sort,important)
advantage (id, text)
In ProductModel I def
As explained by @arogachev, the viaTable
uses two separate queries, which renders any intermediate orderBy
obsolete
You could replace the viaTable
with an innerJoin
as follows, in a similar solution to @MartinM
public function getAdvantages()
{
return $this->hasMany(AdvantageModel::class, ['pha.product' => 'id'])
->innerJoin('product_has_advantage pha', 'pha.advantage = advantage.id')
->andWhere(['pha.important' => 1])
->orderBy(['pha.sort' => SORT_ASC]);
}
By adjusting the result of hasMany
, you are adjusting the query for the target class - AdvantageModel::find()
; product_has_advantage
can be joined via the advantage
identity
The second parameter of hasMany
, link, can be viewed as [ query.column => $this->attribute ]
, which you can now support via the joined product_has_advantage
and its product
identity
Note, when using viaTable
, the link parameter can be viewed as if the intermediate query is complete and we are starting from there; [ query.column => viaTable.column ]
hence ['id', 'advantage']
in your question
Using viaTable
methods with relations will cause two separate queries, but if you don't need link()
method you can use innerJoin in the following way to sort by product_has_advantage table:
public function getAdvantages()
{
$query = AdvantageModel::find();
$query->multiple = true;
$query->innerJoin('product_has_advantage','product_has_advantage.advantage = advantage.id');
$query->andWhere(['product_has_advantage.product' => $this->id, 'product_has_advantage.important' => 1]);
$query->orderBy(['product_has_advantage.sort' => SORT_DESC]);
return $query;
}
Note than $query->multiple = true
allows you to use this method as Yii2 hasMany relation.