Yii2: How can I add relationships on fly in Yii2 ?

Created on 26 Jan 2014  路  7Comments  路  Source: yiisoft/yii2

Is it possible to add relations on fly in Yii2 ?
I used to add dynamically relations in my UploadBehavior, but because relations are set using getter function I am not quite sure how to do this. This is what I used to do to add relations on fly in Yii 1 (in behavior) :

$owner->metaData->addRelation($this->relation, array($owner::HAS_ONE, 'Upload', 'foreign_key','order'=>$this->relation.'.order ASC', 'condition' => "{$this->relation}.model=\"" . strtolower(get_class($owner)) . "\" AND {$this->relation}.relation=\"{$this->relation}\""));

How can I add relationships on fly in Yii2 ?

Most helpful comment

+1

I have modules with dependencies, and need add dinamic relations

All 7 comments

You only need to define the getter in your behavior class. You don't need to do anything else.

@qiangxue the problem is, that I don't know the name of the getter function at runtime. For example, I have a model "Logo" in which I added behavior like this:

public function behaviors()
    {
        return [
            'image' => [
                'class' => 'ajkulacms\behaviors\UploadBehavior',
                'relation' => 'image',
                'multiple' => false,
                'mimetypes'=>array('image/gif','image/png','image/jpeg'),
            ],
        ];
    }

UploadBehavior is supposed to make relation hasOne or hasMany to upload table. Attribute 'relation' is the name of the relation I would like to use. So in this example, model "Logo" should have relation hasOne to upload table created dynamically(using behavior) and I could access it like:

$logo->image

I see. So your relation name is dynamic based on the configuration, right?

You need to do some trick with your behavior to support such "dynamic method".

  • override Behavior::hasMethod() to return true for getRelationName.
  • override Behavior::__call() to implement getRelationName.

@qiangxue Thanks a lot. I hope I will make it work now ;)

I had same problem. My solution:

    public function hasMethod($name)
    {
        $attribute = strtolower(preg_replace('/^get(.*)/isU', '', $name));
        if (isset($this->attributes[$attribute])) {
            return true;
        }
        return parent::hasMethod($name);
    }

    public function __call($name, $params)
    {
        $attribute = strtolower(preg_replace('/^get(.*)/isU', '', $name));
        if (isset($this->attributes[$attribute])) {
            return $this->getFiles($attribute);
        }
        return parent::__call($name, $params);
    }

    public function canGetProperty($name, $checkVars = true)
    {
        if (isset($this->attributes[$name])) {
            return true;
        }
        return parent::canGetProperty($name, $checkVars);
    }

    public function __get($name)
    {
        if (isset($this->attributes[$name])) {
            return $this->getFiles($name);
        }
        return parent::__get($name);
    }

+1

I have modules with dependencies, and need add dinamic relations

Was this page helpful?
0 / 5 - 0 ratings