【问题标题】:Laravel 5 Polymorphic RelationshipLaravel 5 多态关系
【发布时间】:2016-05-26 00:23:06
【问题描述】:

对此尚不完全清楚,因为这将是我第一次修补这个问题。我的表结构如下:

questions
- id
- type_id

multiple_choice_options
- id
- question_id

drag_and_drop_options
- id
- question_id

questions 表上的type_id 字段确定要从哪个选项表加载。所以基本上我想在Question 模型上建立如下关系:

class Question extends Model {
    public function options() {
        // not sure what to return here?
    }
}

对于期权模型,这是否是正确的逆定义?

class MultipleChoiceOption extends Model {
    public function question() {
        return $this->belongsTo(Question::class);
    }
}

class DragAndDropOptions extends Model {
    public function question() {
        return $this->belongsTo(Question::class);
    }
}

如何设置它以处理多态关系?

【问题讨论】:

    标签: laravel eloquent polymorphic-associations


    【解决方案1】:

    您可以简单地在options() 关系中构建一个开关:

    class Question extends Model {
        public function options() {
            if ($type_id === 'multiple') {
                return $this->hasMany(MultipleChoiceOption::class);
            } else {
                return $this->hasMany(DragAndDropOptions::class);
            }
        }
    }
    

    尽管使用这些神奇的关系要小心,但您需要在应用中进行额外的类型检查和仔细的编码。

    【讨论】:

    • 老实说,我希望能够避免使用开关,因为大约有 10 种不同的问题类型。关于应用程序,我本来打算使用一个开关来为每种问题类型包含不同的刀片。
    • 最终使用了这个解决方案,除了一个开关
    【解决方案2】:

    查看Laravel Docs on Polymorphism,您可以通过稍微不同的数据结构来利用一些功能:

    questions
    - id
    - optionable_id
    - optionable_type
    
    multiple_choice_options
    - id
    
    drag_and_drop_options
    - id
    

    型号:

    class Question extends Model {
        public function optionable() {
            return $this->morphTo();
        }
    }
    
    class MultipleChoiceOption extends Model {
        public function question() {
            return $this->morphMany('App\Question', 'optionable');
        }
    }
    
    class DragAndDropOptions extends Model {
        public function question() {
            return $this->morphMany('App\Question', 'optionable');
        }
    }
    

    注意,optionable_type 列将包含所属模型的类名。


    附带说明,您的数据结构关系逻辑对我来说似乎有点奇怪,但仍然可以满足您正在尝试做的事情。我可能有模型QuestionOptionQuestionType,这样选项就独立于问题和问题类型。这将使您能够更改问题类型而无需更改选项。

    【讨论】:

    • 对不起,但我遇到的问题是一个问题有很多选择,而不是相反。选项不会跨问题重复使用
    【解决方案3】:

    考虑你想要达到的目标:

    a)一个选项只能属于一个问题,

    b)一个问题可以有很多选项,

    我认为更简洁的解决方案可能涉及调整您的数据库设计,

    questions
     - id
     - body
     - question_type_id
    
    question_type
     - id
     - name
    
    options
     - id
     - name
     - question_id
    
    
    
    class question extends Model {
        public function options() {
          $this->hasMany('App\option','question_id')
        }
     }
    
    class option extends Model {
      public function question() {
        return $this->belongsTo('App\question');
      }
    }
    

    然后您的 question_type 表将包含 muiltiple_choice、拖放等。因此您无需使用“if”语句或“switch”,这会使您的代码更清晰。您也无需在添加新问题类型时编辑代码。

    【讨论】:

      猜你喜欢
      • 2017-02-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-20
      • 1970-01-01
      • 2015-04-16
      • 2015-04-25
      • 1970-01-01
      相关资源
      最近更新 更多