【问题标题】:Laravel polymorphic relation in NovaNova中的Laravel多态关系
【发布时间】:2019-02-02 03:44:57
【问题描述】:

我当前的博客之类的应用程序有一个Page,它可能有许多不同结构的Paragraphs(文本、图像、文件下载、注册表单……)。在尝试将其转换为具有关系的 Eloquent 模型时,我认为这是一种简单的方法:

pages

  • 身份证
  • 标题,...

paragraphs:

  • 身份证
  • page_id
  • paragraphable_id
  • paragraphable_type

paragraph_texts

  • 身份证
  • 文字

paragraph_images:

  • 身份证
  • 图像路径

paragraph_downloads:

  • 身份证
  • 文件路径

还有模特:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Page extends Model
{

    public function paragraphs() {
        return $this->hasMany(Paragraph::class);
    }
}

?>

段落模型:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Paragraph extends Model
{
    public $table = 'paragraphs';
    public $timestamps = [];

    public function page() {
        return $this->belongsTo(Page::class);
    }

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

文本类型模型作为示例:

<?php

namespace App\Models\ParagraphTypes;


use Illuminate\Database\Eloquent\Model;

class Text extends Model
{
    protected $table = 'paragraph_texts';

    public function paragraph() {
        return $this->morphOne(Paragraph::class, 'paragraphable');
    }

}

我现在想在 nova 中查看页面并通过可选类型创建一个新段落。我根据雄辩的关系(页面的 HasMany 字段,段落的 MorphTo 和 Text 类型的 TextArea)创建了资源类(用于页面、段落和每个段落类型)。当我看到一个页面的详细信息并想添加一个新段落时,我可以看到添加段落的表单,并且可以在下拉列表中选择段落类型,但只能看到已经存在的条目,而不是新的条目。我永远不想添加这样的现有段落类型。

所以问题:

  • 将结构转化为eloquent是否正确,有什么改进吗?
  • laravel nova 如何“通过”段落模型为页面创建新的段落类型?我觉得必须添加一个自定义字段才能这样做,这可能会要求首先创建类型......

【问题讨论】:

    标签: laravel eloquent laravel-nova


    【解决方案1】:

    关于你的第一个问题:你应该使用documentation中的关系:

    class Page extends Model
    {
        public function texts() {
            return $this->morphedByMany(Text::class, 'paragraphable', 'paragraphs');
        }
    }
    
    class Text extends Model
    {
        public function pages() {
            return $this->morphToMany(Page::class, 'paragraphable', 'paragraphs');
        }
    }
    

    您可以使用访问器获取多种段落类型:

    class Page extends Model
    {
        public function getParagraphsAttribute() {
            return $this->texts->toBase()->merge($this->files)->merge([...]);
        }
    }
    
    $paragraphs = $page->paragraphs;
    

    【讨论】:

    • 在处理文档中的多对多“标签”关系时,这可能是一种解决方案。但是我在这里想要的是与“段落”的单一关系,每个段落都可以是某种类型。遵循您的示例将导致页面模型中的每个 Paragraphtype 都有一个 morphedByMany 关系。
    • 我看不出你们的关系与文档中的关系有何不同。
    • 好吧,当它只保留一个段落类型(如文本)时,就不行了。但我想有一个定义多个类型的单一关系“段落”和一个定义段落在页面上列出的顺序的列“sort_order”。例如,如果我有 5 种段落类型(文本、文件、图像、幻灯片、测验),我可以定义与页面模型的 5 个关系,但没有要访问的单个关系“段落”并且会失去排序。
    • 没有(本机)关系可以返回多个段落类型。此类情况的默认解决方案是访问器。我更新了我的答案。
    • 感谢 Jonas,这似乎是访问段落类型的解决方案。但是通过合并单个关系,在 laravel 和 nova 中似乎没有内置的解决方案。
    猜你喜欢
    • 1970-01-01
    • 2019-02-19
    • 2021-05-20
    • 2019-06-18
    • 1970-01-01
    • 2020-04-17
    • 2019-05-04
    • 2019-01-22
    相关资源
    最近更新 更多