Отношение Yii2 на основе значений атрибутов вместо ключей

У меня есть 2 таблицы в БД (mysql), и между ними нет классической связи через ключи или идентификаторы. Единственный способ, которым я мог бы определить отношения, — это значения атрибутов. Например. table wheel и car, и некоторые колеса будут соответствовать определенным автомобилям только из-за их размера. Можно ли это определить на уровне БД и/или в yii2, и если да, то как?

В отношениях я могу добавить onCondition(), но вы также должны определить атрибут (???):

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

Я мог бы использовать поддельный атрибут и установить его во всех записях, например, равным 1, но мне это кажется немного странным.

Я ничего не нашел в Интернете по этому поводу, или, может быть, я просто неправильно ищу, или, может быть, я пытаюсь сделать что-то, что является совершенно плохой практикой. Не могли бы вы указать мне правильное направление?


person user2511599    schedule 11.09.2019    source источник


Ответы (2)


Гипотетически можно установить пустой массив в качестве ссылки, но из соображений безопасности (я думаю) в выборке автоматически добавляется условие "0 = 1".

Я несколько раз сталкивался с вашей проблемой, и лучшим решением, которое я смог найти, было явное использование ActiveQuery (аналогично тому, что происходит для hasOne и 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, ...
    ]);

}

Таким образом вы можете получить как массив, так и ActiveQuery для добавления других условий:

var_dump($model->wheels);            // array of wheels objects
var_dump($model->getWheels());       // yii\db\ActiveQuery object
$model->getWheels()->andWhere(...);  // customize active query
person Francesco Simeoli    schedule 11.09.2019
comment
Я получил что-то новое из вашего ответа. Хорошая работа! :) - person Paul; 11.09.2019
comment
Ваше решение также является хорошей альтернативой. Рад, что был полезен :) - person Francesco Simeoli; 11.09.2019

Я не думаю, что вы могли бы достичь этого через отношения. Но есть способ обойти это ограничение.

<?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;
    }
}

Затем вы можете получить доступ к атрибуту wheels так же, как это делает отношение.

<?php

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

Имейте в виду, что этот способ не поддерживает Eager Loading

person Paul    schedule 11.09.2019