Laravel (nova) 继承映射
Laravel (nova) inheritance mapping
我目前正在构建 laravel nova 应用程序。
我希望能够通过 inheritance mapping.
实现类似于 Doctrine 可以做的事情
让我们假设以下示例:
use Illuminate\Database\Eloquent\Model;
class Event extends Model {
protected $attributes = [
'name' => null,
'starts_at' => null,
'ends_at' => null,
];
}
class EventTypeA extends Event {
// has extra fields specific to EventTypeA
}
class EventTypeB extends Event {
// has extra fields specific to EventTypeB
}
现在我希望能够:
- 获取所有
EventTypeA
的
- 获取所有
EventTypeB
的
- 获取所有事件,只关心共享信息。
当然,对于上面的列表,过滤、投影等所有 Eloquent 好处都应该适用。
据我所知laravel可能能够正确处理EventTypeA
和EventTypeB
但是Event
会必须需要从两个表中获取数据,这实际上是不可能的。
我知道 eloquent 的变形功能,但是根据我的理解,这会导致 Event
核心数据和后代特定属性的单独 nova 视图。这在用户体验方面是不可接受的。
我考虑过为 Event
使用一个接口,然后 EventTypeA
和 EventTypeB
将实现该接口。但是,我认为这将需要大量体力劳动才能让 Eloquent 对事件做一些有意义的事情。
这听起来像是一个常见的问题,但是我无法在 laravel 中找到任何关于如何正确执行此操作的资源(尤其是 nova 可以应对它)。
Laravel 不提供为不同的 table 创建子 类 基础模型的解决方案。反过来也是完全可能的:
class Event extends Model
{
protected $table = 'events';
}
class EventA extends Event
{
protected static function boot()
{
parent::boot();
static::addGlobalScope(function (Builder $query) {
$query->where('events.type', '=', 'a');
});
}
}
class EventB extends Event
{
protected static function boot()
{
parent::boot();
static::addGlobalScope(function (Builder $query) {
$query->where('events.type', '=', 'b');
});
}
}
我通过为枢轴使用中间模型 table 并将一些属性代理给子模型解决了类似的问题。
那么你的关系就是 BelongsTo
和 HasMany
。
就用户体验而言,您可以通过有条件地检查资源属性来自定义 Nova 中的字段。尽管我建议仅在详细信息和表单视图上执行此操作,因为索引 table 将在返回具有不同列的行时关闭。
public function fields(Request $request)
{
return array_filter([
ID::make()->sortable(),
value(function () {
if ($this->type === 'a') {
return Boolean::make('A specific field')->hideFromIndex();
}
}),
value(function () {
if ($this->type === 'b') {
return Boolean::make('B specific field')->hideFromIndex();
}
}),
]);
}
我最近才知道 kirschbaum-development/nova-inline-relationship
这个包允许你将关系内联到 nova 资源中,因此将允许这样的结构:
class Event extends Model
{
public function eventable()
{
return $this->morphTo();
}
}
class Workshop extends Model
{
public function event()
{
return $this->morphOne(Event::class, 'eventable');
}
}
class StageTalk extends Model
{
public function event()
{
return $this->morphOne(Event::class, 'eventable');
}
}
然后在nova资源中
class Workshop extends Resource
{
public function fields(Request $request)
{
return [
MorphOne::make('Event')->inline(),
];
}
}
我目前正在构建 laravel nova 应用程序。 我希望能够通过 inheritance mapping.
实现类似于 Doctrine 可以做的事情让我们假设以下示例:
use Illuminate\Database\Eloquent\Model;
class Event extends Model {
protected $attributes = [
'name' => null,
'starts_at' => null,
'ends_at' => null,
];
}
class EventTypeA extends Event {
// has extra fields specific to EventTypeA
}
class EventTypeB extends Event {
// has extra fields specific to EventTypeB
}
现在我希望能够:
- 获取所有
EventTypeA
的 - 获取所有
EventTypeB
的 - 获取所有事件,只关心共享信息。
当然,对于上面的列表,过滤、投影等所有 Eloquent 好处都应该适用。
据我所知laravel可能能够正确处理EventTypeA
和EventTypeB
但是Event
会必须需要从两个表中获取数据,这实际上是不可能的。
我知道 eloquent 的变形功能,但是根据我的理解,这会导致 Event
核心数据和后代特定属性的单独 nova 视图。这在用户体验方面是不可接受的。
我考虑过为 Event
使用一个接口,然后 EventTypeA
和 EventTypeB
将实现该接口。但是,我认为这将需要大量体力劳动才能让 Eloquent 对事件做一些有意义的事情。
这听起来像是一个常见的问题,但是我无法在 laravel 中找到任何关于如何正确执行此操作的资源(尤其是 nova 可以应对它)。
Laravel 不提供为不同的 table 创建子 类 基础模型的解决方案。反过来也是完全可能的:
class Event extends Model
{
protected $table = 'events';
}
class EventA extends Event
{
protected static function boot()
{
parent::boot();
static::addGlobalScope(function (Builder $query) {
$query->where('events.type', '=', 'a');
});
}
}
class EventB extends Event
{
protected static function boot()
{
parent::boot();
static::addGlobalScope(function (Builder $query) {
$query->where('events.type', '=', 'b');
});
}
}
我通过为枢轴使用中间模型 table 并将一些属性代理给子模型解决了类似的问题。
那么你的关系就是 BelongsTo
和 HasMany
。
就用户体验而言,您可以通过有条件地检查资源属性来自定义 Nova 中的字段。尽管我建议仅在详细信息和表单视图上执行此操作,因为索引 table 将在返回具有不同列的行时关闭。
public function fields(Request $request)
{
return array_filter([
ID::make()->sortable(),
value(function () {
if ($this->type === 'a') {
return Boolean::make('A specific field')->hideFromIndex();
}
}),
value(function () {
if ($this->type === 'b') {
return Boolean::make('B specific field')->hideFromIndex();
}
}),
]);
}
我最近才知道 kirschbaum-development/nova-inline-relationship
这个包允许你将关系内联到 nova 资源中,因此将允许这样的结构:
class Event extends Model
{
public function eventable()
{
return $this->morphTo();
}
}
class Workshop extends Model
{
public function event()
{
return $this->morphOne(Event::class, 'eventable');
}
}
class StageTalk extends Model
{
public function event()
{
return $this->morphOne(Event::class, 'eventable');
}
}
然后在nova资源中
class Workshop extends Resource
{
public function fields(Request $request)
{
return [
MorphOne::make('Event')->inline(),
];
}
}