Dynamic Creating Of Ar Relations

Hello.

I need to create AR relations in runtime (in model init). How I can do this?

What’s your use case?

EAV. I have order model and many order properties in another table. I want to create has-one relation for each property to get with/joinWith functionality and to access properties via getter.

For example, I have order property with symbolic code ‘address’. I can make relation like this:


public function getAddress()

{

    return $this->hasOne(OrderProp::className(), ['order_id' => 'id'])->onCondition(['code' => 'address']);

}

But I need to create all relations in runtime for each property (from cached array of property codes).

In general you could override __call() and __get() to return relation object when dynamic relations are accessed.

This approach however is a bit hacky as it is not easy to implement for all possible cases.

We might need to improve extendability of AR for these cases.

Can you redesign your app a bit and try using a parameterized relation like this?




public function getProp($code = 'address')

{

    return $this->hasOne(OrderProp::className(), ['order_id' => 'id'])

        ->onCondition(['code' => $code]);

}

And wherever you need to access you call it accordingly like this:




$data1 = $model->getProp('address');

$data2 = $model->getProp('prop2');



Kartik V, it is not a solution of my problem, I think. Getter is not a big deal, main trouble is in using joinWith. How can I call this method with parameterized relation?

CeBe, do I need to create an issue on Github? I will try to override __call() and if it won’t help, I’ll write relation getters for all props in model class (as temp solution before you release new functional).

P.S. __call() hack is not working: "has no relation" exception when trying to use joinWith.