如何将 Laravel 的多态系统应用于似乎被逆转的事物
Posted
技术标签:
【中文标题】如何将 Laravel 的多态系统应用于似乎被逆转的事物【英文标题】:How can I apply Laravel's polymorph-system to what seems to be reversed 【发布时间】:2021-11-01 19:11:17 【问题描述】:背景
在我们的 Laravel 系统中,我们有一个 Post,例如VideoPost 或 TextPost(类型存储在 type
-attribute 中)。每个帖子(无论是什么类型)都依赖于翻译,因此我们让每个帖子都有一个 PostTranslation,其中包含与 VideoPostTranslation 或 TextPostTranslation 的一对多关系。
这意味着我要访问 Post 的翻译内容,首先必须获取 Post,然后检查类型,并获取相关的 PostTranslations 和它的任何子类型(例如 VideoPostTranslation)。
我们现在已经意识到这是次优的,我们希望就如何实现这一点获得一些帮助。
目标
我们想将我们的数据库转换成这样的:
[Post]
int: id
str: type // one of [video, text]
[VideoPostTranslation]
int: id
int: post_id
str: language_code
str: video_specific_data
[TextPostTranslation]
int: id
int: parent_id
str: language_code
str: text_specific_data
在这个结构中,没有冗余数据,希望 Laravel 可以帮助我们查询这个。
最好是我们希望能够编写如下内容:
$posts = Post::with('translations')->get();
foreach($posts as $post)
switch($post->type)
case 'video':
// handle $post->translations[]->video_specific_data
case 'text':
// handle $post->translations[]->text_specific_data
我们已经看到 Laravel 有一个很好的类之间的变形系统,但它通常要求包含类型数据的系统也是处理变形的系统。在他们的一对多示例中,他们使用可评论系统,其中评论可以通过commentable
-relation 引用帖子和视频,但我不确定这在我们的案例中如何工作。
例如,这将不起作用:
class Post extends Model
public function translations()
return $this->morphTo();
class VideoPostTranslation extends Model
public function post()
return $this->morphMany(Post::class, 'translations');
class TextPostTranslation extends Model
public function post()
return $this->morphMany(Post::class, 'translations');
我们需要“实施”哪些改变?我们是否需要添加一个名为 PageTranslation 的中间多对多表来处理这种关系?或者是否可以让 Laravel 使用建议的数据库结构?
【问题讨论】:
【参考方案1】:在我看来,你们的关系很好,应该会奏效。 您能否进一步解释一下它是如何不起作用的以及您遇到了什么错误。此外,提供的foreach
循环中的switch
语句可能不是必需的。而不是
foreach($posts as $post) switch($post->type) case 'video': // handle $post->translations[]->video_specific_data case 'text': // handle $post->translations[]->text_specific_data
您可以通过关系名称直接访问其翻译后的模型。传递语言键以检索特定语言的翻译。
foreach($posts as $post)
$post->translations()->where('language_code', $langKey)->first()->content;
如果video_post_translations
和text_post_translations
有其独特的字段,例如video_post_translations
有一个video
,而在text_post_translations
表中,这个video
字段不存在(这很可能),可以使用switch case
。
如果仍然使用switch case
,请考虑将video_post_translations
和text_post_translations
表分组,这肯定会简化问题,因为posts.type
已经区分了所需的字段。根据您的需要,这种方法可能不适合。
【讨论】:
我已经使用建议的数据库结构和模型代码进行了测试,但它目前不起作用。我知道要让它按照 Laravel 的意图工作,我们需要多态关系以另一种方式进行,例如这意味着一篇帖子需要通过指定type
和id
来引用一个VideoPageVersion。我意识到它可以通过数据透视表来解决,所以我想我们只需要尝试一下。以上是关于如何将 Laravel 的多态系统应用于似乎被逆转的事物的主要内容,如果未能解决你的问题,请参考以下文章