Yii2:与同一模型的多个逆关系?

Yii2: Multiple inverse relations to same model?

如何处理指向同一活动记录的多个反向关系? 例如:

class Bicycle extends ActiveRecord {

    public function getFrontWheel() {
        return $this
            ->hasOne(Wheel::class, ['id' => 'front_wheel_id'])
            ->inverseOf('bicycles');
    }

    public function getRearWheel() {
        return $this
            ->hasOne(Wheel::class, ['id' => 'rear_wheel_id'])
            ->inverseOf('bicycles');
    }

}

class Wheel extends ActiveRecord {

    public function getBicycles() {
        return $this
            ->hasMany(Bicycle::class, ['???' => 'id'])
            ->inverseOf('??????');
    }

}

我可以在这里做什么?我非常需要逆关系。

我建议执行以下操作:

创建两个新的 classes:

  • class FrontWheel 延伸车轮 {
  • class 后轮伸出车轮 {

在新的 classes 中,您可以轻松设置关系。

如何实例化正确class? ActiveRecord instantiate() 中有一个方法,您可以在其中编写需要创建轮 class 的逻辑。

class Wheel extends ActiveRecord {
...

  public static function instantiate ( $row ) {
      if($row['type'] === 'RearWheel') {
           return new RealWheel();
      }
      ...

  }

完整代码:

class Bicycle extends ActiveRecord
{

    public function getFrontWheel()
    {
        return $this
            ->hasOne(Wheel::class, ['id' => 'front_wheel_id'])
            ->inverseOf('bicycles');
    }

    public function getRearWheel()
    {
        return $this
            ->hasOne(Wheel::class, ['id' => 'rear_wheel_id'])
            ->inverseOf('bicycles');
    }

}

abstract class Wheel extends ActiveRecord
{

    public static function instantiate($row)
    {
        if ($row['type'] === 'RearWheel') {
            return new RealWheel();
        }
        if ($row['type'] === 'FrontWheel') {
            return new FrontWheel();
        }
        
        throw new InvalidConfigException();
    }

    abstract public function getBicycles();
}

class RealWheel extends Wheel
{

    public function getBicycles()
    {
        return $this
            ->hasMany(Bicycle::class, ['rear_wheel_id' => 'id'])
            ->inverseOf('rearWheel');
    }

}

class FrontWheel extends Wheel
{

    public function getBicycles()
    {
        return $this
            ->hasMany(Bicycle::class, ['front_wheel_id' => 'id'])
            ->inverseOf('frontWheel');
    }

}

这是我自己的解决方案。 要点:

  • 这一切都归结为正确的命名。
  • 逆关系是bijective!换句话说,每一个关系在另一端总是必须有自己唯一的镜像关系。
class Bicycle extends ActiveRecord {

    public function getFrontWheel() {
        return $this
            ->hasOne(Wheel::class, ['id' => 'front_wheel_id'])
            ->inverseOf('frontWheelBicycles');
    }

    public function getRearWheel() {
        return $this
            ->hasOne(Wheel::class, ['id' => 'rear_wheel_id'])
            ->inverseOf('rearWheelBicycles');
    }

}
class Wheel extends ActiveRecord {

    public function getFrontWheelBicycles() {
        return $this
            ->hasMany(Bicycle::class, ['front_wheel_id' => 'id'])
            ->inverseOf('frontWheel');
    }

    public function getRearWheelBicycles() {
        return $this
            ->hasMany(Bicycle::class, ['rear_wheel_id' => 'id'])
            ->inverseOf('rearWheel');
    }

}