你需要查看 Laravel 中的
多态关联来实现这一点。多态关联将允许你根据字段的
类型检索不同的模型。在你的
Slug
模型中,你需要像这样做:
public function page()
{
return $this->morphTo('page', 'layout_id', 'id');
}
在您的某个服务提供者中,例如
AppServiceProvider
,您需要提供一个
Morph Map 来告诉 Laravel 将某些 ID 映射到特定的模型类。例如:
Relation::morphMap([
1 => Page::class,
// ...
6 => ArticlePage::class,
]);
现在,每当您使用
page
关系时,Laravel将检查类型并将正确的模型返回给您。
注意:我对参数等不是100%确定,也没有测试过,但您应该能够从文档中找到答案。
如果您的
layout_id
位于
Page
模型上,我唯一看到的解决方案是向您的
Page
模型添加一个方法,该方法能够根据其
layout_id
属性将现有页面转换为
ArticlePage
或其他页面类型。您应该可以尝试类似以下的内容:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Page extends Model
{
const LAYOUT_ARTICLE = 6;
protected $layoutMappings = [
self::LAYOUT_ARTICLE => ArticlePage::class
];
public function toLayoutPage()
{
$class = $this->layoutMappings[$this->layout_id];
if (class_exists($class)) {
return (new $class())
->newInstance([], true)
->setRawAttributes($this->getAttributes());
}
throw new \Exception('Invalid layout.');
}
}
这段代码会根据你的
layout_id
属性查找映射,然后创建一个新的正确类型的类,并将其属性填充为您正在创建的页面的属性。如果您查看 Laravel 的
Illuminate\Database\Eloquent::newFromBuilder()
方法,可以了解其运作方式以及我如何获得上面的代码。您应该可以像这样直接使用它:
$page = Slug::where('slug', $slug)
->first()
->page
->toLayoutPage()
那会给你一个
ArticlePage
的实例。