active-record
active-record copied to clipboard
Idea: avoid double declare link and type of relation if used via()
#14238
What about AR function?
yii\db\BaseActiveRecord
/**
* Get a relation from the another class relation definition
* @param ActiveRecord|array|callable|string $target the model class who have relation
* @param string $relationName relation name in target (case sensitive, without 'get')
* @return ActiveQuery
*/
public function hasRelation($target, $relationName){
$target instanceof ActiveRecord || $target = Yii::createObject($target);
/** @var ActiveQuery $relationQuery */
$relationQuery = $target->getRelation($relationName);
$relationQuery->primaryModel = $this;
return $relationQuery;
}
class Order extends ActiveRecord
{
public function getItems(){
return $this->hasRelation(OrderItem::className(), 'item')->via('orderItems');
}
public function getOrderItems()
{
return $this->hasMany(OrderItem::className(), ['order_id' => 'id']);
}
}
It's avoid double declare link and type of relation (multiple)
can you elaborate on your usecase and why it is necessary compared to BaseActiveRecord::createRelationQuery()
now I propose
public function viaRelation($target, $relationName, $via){
$target instanceof ActiveRecord || $target = Yii::createObject($target);
/** @var ActiveQuery $relationQuery */
$relationQuery = $target->getRelation($relationName);
$relationQuery->primaryModel = $this;
return $relationQuery->via($via);
}
vs
protected function createRelationQuery($class, $link, $multiple)
{
/* @var $class ActiveRecordInterface */
/* @var $query ActiveQuery */
$query = $class::find();
$query->primaryModel = $this;
$query->link = $link;
$query->multiple = $multiple;
return $query;
}
:
multiple and link get from parent declaration of exist relation.
It's avoid double declare link and type of relation (multiple)
i.e. model3, who use relation of model2 as via to model1 not necessary know about details of relation definition into model2
model3 is so pure :angel:
From docs https://github.com/yiisoft/yii2/tree/master/docs/guide
class Order extends ActiveRecord
{
public function getOrderItems()
{
return $this->hasMany(OrderItem::className(), ['order_id' => 'id']);
}
public function getItems()
{
return $this->hasMany(Item::className(), ['id' => 'item_id'])
->via('orderItems');
}
}
If model OrderItem have relation item representation of getItem()
class OrderItem extends ActiveRecord
{
public function getItem()
{
return $this->hasOne(Item::className(), ['id' => 'item_id']);
}
}
model Order can use it like that:
class Order extends ActiveRecord
{
public function getOrderItems()
{
return $this->hasMany(OrderItem::className(), ['order_id' => 'id']);
}
public function getItems()
{
return $this->viaRelation(Item::className(), 'item', 'orderItems');
}
}
So... in this notation via relation is main... may be move it to first argument? Contr: function via() in end of chain
And this can be used for simple-definition chain of relation