active-record icon indicating copy to clipboard operation
active-record copied to clipboard

Idea: avoid double declare link and type of relation if used via()

Open bscheshirwork opened this issue 8 years ago • 6 comments

#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)

bscheshirwork avatar Jun 02 '17 12:06 bscheshirwork

can you elaborate on your usecase and why it is necessary compared to BaseActiveRecord::createRelationQuery()

dynasource avatar Jul 31 '17 09:07 dynasource

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.

bscheshirwork avatar Jul 31 '17 09:07 bscheshirwork

It's avoid double declare link and type of relation (multiple)

bscheshirwork avatar Jul 31 '17 09:07 bscheshirwork

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:

bscheshirwork avatar Jul 31 '17 10:07 bscheshirwork

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

bscheshirwork avatar Jul 31 '17 10:07 bscheshirwork

And this can be used for simple-definition chain of relation

bscheshirwork avatar Jul 31 '17 14:07 bscheshirwork