【问题标题】:Laravel - Polymorphic relationships for model typesLaravel - 模型类型的多态关系
【发布时间】:2019-10-18 20:05:05
【问题描述】:

我是 Laravel 的新手,作为我的第一个项目,我正在尝试制作一个调查 API。

我正在努力为答案类型创建模型和控制器,在查看了我的问题后,我发现了多态关系,这在一定程度上满足了我的需求。 Adam Watham 制作了一个关于模型和模型类型的精彩视频,但没有谈到创建它。

视频链接:https://adamwathan.me/2015/09/03/pushing-polymorphism-to-the-database/

型号

我为答案和答案类型创建了一个模型,并且必须在 Answers 上添加一个属性类型,因为我必须事先知道它是什么类型。我选择在类型模型上添加 morphTo 是因为我不想在我的答案中添加一个或多个 Types(text,number)

class NumberAnswer extends Model
{
    protected $fillable = [
        'number'
    ];

    public function numberable()
    {
        $this->morphTo();
    }
}

class TextAnswer extends Model
{
    protected $fillable = [
        'text'
    ];

    public function textable()
    {
        $this->morphTo();
    }
}

class Answer extends Model
{
    protected $fillable = [
        'user_id',
        'question_id',
        'type'
    ];

    public function numbers()
    {
        $this->morphMany('App\Models\File', 'numberable');
    }

    public function texts()
    {
        $this->morphMany('App\Models\Text', 'textable');
    }
}

我遇到的问题是如何存储它们,我目前的工作方式以及我在哪里找到了一些提示:

Polymorphic controller solution that I found

服务提供者

public function boot()
{
    Relation::morphMap([
        'answer' => 'App\Models\Answer'
    ]);
}

应答控制器

class AnswerController extends Controller
{
    private $answer;


    public function __construct(AnswerRepository $answerRepo)
    {
        $this->answer = $answerRepo;
    }

    public function store(Request $request, int $tenantId)
    {
       $requestAnswer = $request->validate([
         'user_id' => [
            'required',
            'numeric',
            Rule::exists('users','id'),
        ],
        'question_id' => [
            'required',
            'numeric',
            Rule::exists('questions','id'),
        ],
        'type' => [
            'required',
            'in:text,number'
        ]
       ]);

       $text = $request->validate([
           'text' => 'required_if:type,text|string',
       ]);
       $number = $request->validate([
           'number' => 'required_if:type,number|string',
       ]);

       $answer = $this->answer->create($requestAnswer);

       if($requestAnswer['type'] === 'text'){
          $answer->texts()->create(['text' => $text]);
       }
       if($requestAnswer['type'] === 'number'){
          $answer->numbers()->create(['number' => $number]);
       }

       return response()->json($answer);
    }

}

问题

我对我应该做什么有点迷茫,因为在我学习的过程中,我想知道是否还有其他我看不到的方法。有更好的方法来实现这一点吗?

【问题讨论】:

    标签: laravel postgresql model-view-controller polymorphism


    【解决方案1】:

    一旦你设置了多态关系,它就像一个正常的关系。因此,您使用的是多对多的变形,它与所有方法的常规多对多的工作方式相同。

    最后,您可能需要考虑将答案存储为 JSON 列类型。在您的特定用例中,它似乎更合适。

    【讨论】:

    • 我想制作更多类型的答案,比如我想在系统的另一部分使用的文件。感谢您的回答,现在我明白了,当我不需要在其他地方使用相同的模型以及 JSON 列类型时,我不需要做多态关系,我不喜欢处理的想法之后用它。
    【解决方案2】:

    我可能说话不合时宜,并不是来自 Laravel 背景。来自 RDBMS 背景,多态关系是一个危险信号。这并不意味着它们总是一个糟糕的设计(这太容易了),但它们本质上是有问题的。主要是因为您可以通过声明方式获得许多关系完整性控制,并且在 RDBMS 中“免费”地被丢弃了。再说一次,多态关系往往出现在关系模型不合适的情况下。 (一种关系。)我不时使用这种关系,但很少……而且事先有很多想法。我猜 Laravel 中包含了混杂的关系,所以 Laravel 可能已经以某种方式为你克服了很多问题。 (如前所述,我没有任何线索。)如果 Postgres 只是 Laravel 的一种持久性机制,也许没那么重要。

    你并没有问到多态关系本身,所以我就这样说吧。但如果你对这个主题感兴趣,Bill Karwin 在 SQL Anitpatterns 中关于该主题的一章相当不错。

    【讨论】:

      猜你喜欢
      • 2020-10-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-23
      • 2020-04-25
      • 2015-05-29
      • 1970-01-01
      • 2017-07-07
      相关资源
      最近更新 更多