【问题标题】:Yii2: Multiple inverse relations to same model?Yii2:同一模型的多个反比关系?
【发布时间】:2021-04-28 02:35:00
【问题描述】:

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

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('??????');
    }

}

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

【问题讨论】:

    标签: yii2 yii2-model yii2-active-records


    【解决方案1】:

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

    • 这一切都归结为正确的命名。
    • 逆关系为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');
        }
    
    }
    

    【讨论】:

      【解决方案2】:

      我建议执行以下操作:

      创建两个新类:

      • 类 FrontWheel 扩展 Wheel {
      • 类 RearWheel 扩展 Wheel {

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

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

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

      【讨论】:

      • 有趣的想法,但行不通。轮子不能有“type”属性,因为它们必须在任一位置(后部或前部)都可以使用而无需任何修改。
      • 嗨,如果你不能使用类型,你可以在实例化方法中查询你的数据库,如果它属于一个front_wheel_id,那么你可以实例化前轮类。我知道这是一个额外的查询,我认为您的情况需要这样做。想一想:你能从没有上下文的车轮(自行车)上分辨出它是前轮还是后轮?
      • 确实,你不能而且你不应该能够。轮子就是轮子。
      • 那么你觉得在instantiate方法中查询它怎么样?
      • 这听起来像是对性能的打击,这违背了逆关系的全部目的。无论哪种方式,我都找到了一个优雅的解决方案。除非有人提出更好的建议,否则我会在几天内发布我的答案。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-07
      • 1970-01-01
      相关资源
      最近更新 更多