New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How can I add relationships on fly in Yii2 ? #2169

Closed
johonunu opened this Issue Jan 26, 2014 · 7 comments

Comments

Projects
None yet
4 participants
@johonunu
Contributor

johonunu commented Jan 26, 2014

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 ?

@qiangxue

This comment has been minimized.

Show comment
Hide comment
@qiangxue

qiangxue Jan 26, 2014

Member

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

Member

qiangxue commented Jan 26, 2014

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

@qiangxue qiangxue closed this Jan 26, 2014

@johonunu

This comment has been minimized.

Show comment
Hide comment
@johonunu

johonunu Jan 26, 2014

Contributor

@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
Contributor

johonunu commented Jan 26, 2014

@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
@qiangxue

This comment has been minimized.

Show comment
Hide comment
@qiangxue

qiangxue Jan 26, 2014

Member

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.
Member

qiangxue commented Jan 26, 2014

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.
@johonunu

This comment has been minimized.

Show comment
Hide comment
@johonunu

johonunu Jan 26, 2014

Contributor

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

Contributor

johonunu commented Jan 26, 2014

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

@zelenin

This comment has been minimized.

Show comment
Hide comment
@zelenin

zelenin Jul 7, 2014

Contributor

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);
    }
Contributor

zelenin commented Jul 7, 2014

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);
    }
@qiangxue

This comment has been minimized.

Show comment
Hide comment
@qiangxue

qiangxue Jul 7, 2014

Member

Duplicate of #3352

Member

qiangxue commented Jul 7, 2014

Duplicate of #3352

@StagnantIce

This comment has been minimized.

Show comment
Hide comment
@StagnantIce

StagnantIce Dec 25, 2015

+1

I have modules with dependencies, and need add dinamic relations

StagnantIce commented Dec 25, 2015

+1

I have modules with dependencies, and need add dinamic relations

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment