1

I have 2 tables in the db (mysql), and between the 2 there is no classic relationship through keys or ids. The only way I could define relationship would be through attribute values. E.g. table wheel and car and certain wheels would match certain cars because of the size only. Can it be defined on DB level, and/or in yii2, and if yes, how?

In the relations I can add an onCondition(), but you have to define an attribute (???), too:

public function getWheels() {
    return $this->hasMany(\app\models\Wheel::className(), ['???' => '???'])->onCondition(['<', 'wheelsize', $this->wheelsize]);
}

I could use a fake attribute and set it in all records like to 1, but it seems a little bit odd for me.

I find nothing on the web regarding this or maybe I'm just searching the wrong way, or maybe I'm trying something that's totally bad practice. Can you please point me to the right direction?

user2511599
  • 796
  • 1
  • 13
  • 38

2 Answers2

2

Hypothetically you can set an empty array as a link, but for security reasons (I think) the condition "0 = 1" is automatically added in the select.

I faced your own problem several times and the best solution I could find was to use ActiveQuery explicitly (similar to what happens for hasOne and hasMany):

public function getWheels() {
    return new ActiveQuery(\app\models\Wheel::className(), [
        'where' => 'my condition' // <--- inserte here your condition as string or array
        'multiple' => true        // true=hasMany, false=hasOne
        // you can also add other configuration params (select, on condition, order by, ...
    ]);

}

This way you can get both the array and the ActiveQuery to add other conditions:

var_dump($model->wheels);            // array of wheels objects
var_dump($model->getWheels());       // yii\db\ActiveQuery object
$model->getWheels()->andWhere(...);  // customize active query
1

I don't think that you could achieve this through relation. But there is a way to work around the limitation.

<?php

namespace app\models;

class Car extend \yii\db\ActiveRecord
{
    /**
     * @var \app\models\Wheel
     */
    private $_wheels;

    /**
     * @return \app\models\Wheel[]
     */
    public function getWheels()
    {
        if (!$this->_wheels) {
            $this->_wheels = Wheel::find()
                ->where(['<', 'wheelsize', $this->wheelsize])
                //->andWhere()  customize your where here
                ->all();
        }

        return $this->_wheels;
    }
}

Then you could access the wheels attribute just as relation does.

<?php

$car = Car::find(1);
$car->wheels;

Beware that this way does not support Eager Loading

Paul
  • 1,630
  • 1
  • 16
  • 23