Laravel Nova 模型关联
除了我们之前讨论过的那些字段,Nova 还支持 Laravel 模型的关联关系。只要给资源添加一个关联关系,你就能体会到 Nova 的强大之处,因为你可以在资源详情页快速的查看并搜索该资源的关联模型:
一对一
这个 HasOne
对应一个 hasOne
Eloquent 关系。例如,让我们假设一个 User
模型 hasOne
Address
模型。我们可以将这种关系添加到我们的
User
Nova 资源中,如下所示:
use Laravel\Nova\Fields\HasOne;
HasOne::make('Address')
就像其他类型的字段一样,关系字段将自动地 “snake case” 字段的显示名称,来确定底层关系的方法或属性。然而,你可以将它作为第二个参数传递给这个字段的 make
方法,来明确地指定关系方法的名称。如下所示:
HasOne::make('Dirección', 'address')
一对多
HasMany
字段对应 Eloquent 中的 hasMany
关系。假设一个 User
模型 hasMany
Post
模型,那么我们可以给 Nova 的 User
资源添加如下关系:
use Laravel\Nova\Fields\HasMany;
HasMany::make('Posts')
一对多(逆向)
BelongsTo
字段对应 Eloquent 中的 belongsTo
关系。假设一个 Post
模型 belongsTo
一个 User
模型,那么我们可以给
Nova 的 Post
资源添加如下关系:
use Laravel\Nova\Fields\BelongsTo;
BelongsTo::make('User')
标题属性
当创建或编辑包含 BelongsTo
字段的资源时,下拉框或搜索框里会显示该资源的「标题」。假如 User
资源的标题是 name
属性,那么 BelongsTo
选择菜单里显示的就是他的
name
:
如果要自定义资源的「titile」,可以在资源类里定义一个 title
属性:
public static $title = 'name';
此外,你也可以覆盖资源的 title
方法:
/**
* 获取资源显示的值。
*
* @return string
*/
public function title()
{
return $this->name;
}
多对多
BelongsToMany
字段对应于模型的 belongsToMany
关联。例如,我们假定有一个 User
模型 belongsToMany
Role
模型。我们就可以像这样将它添加到 User
Nova
资源中:
use Laravel\Nova\Fields\BelongsToMany;
BelongsToMany::make('Roles')
主字段
如果你的 belongsToMany
关联中间表还存着其他的关联字段,你也可以将它附到 BelongsToMany
Nova 关联字段上。一旦这些字段被附到该关联,那他们将会在关联资源列表中展示.
例如,我们假定我们的 User
模型 belongsToMany
Role
模型。在 role_user
中间表,让我们想象一下 notes
字段包含一些关联关系中简单的文本 我们可以使用 fields
方法把这个字段附加到
BelongsToMany
字段上:
BelongsToMany::make('Roles')
->fields(function () {
return [
Text::make('Notes'),
];
});
当然,这也可以在定义相反关联时使用。所以,如果我们在 User
资源中定义了一个 BelongsToMany
字段,我们也可以在 Role
资源中定义反向关联:
BelongsToMany::make('Users')
->fields(function () {
return [
Text::make('Notes'),
];
});
在两处分别定义这样的关联可能会让我们的代码重复,Nova 允许你通过传入一个可调用的对象给 fields
方法:
BelongsToMany::make('Users')->fields(new RoleUserFields)
上面的例子中,RoleUserFields
类可以只有一个 __invoke
方法,并返回一个包含附加字段的数组:
<?php
namespace App\Nova;
use Laravel\Nova\Fields\Text;
class RoleUserFields
{
/**
* 获取关联模型的附加字段
*
* @return array
*/
public function __invoke()
{
return [
Text::make('Notes'),
];
}
}
主操作
通常,Nova actions 是基于资源操作的。 然而,你也可以把 actions 绑定到 belongsToMany
字段 然后他们就可以在 pivot / 中间表记录上操作了。为了实现它,你可以在字段定义时使用 actions
链式方法:
BelongsToMany::make('Roles')
->actions(function () {
return [
new Actions\MarkAsActive,
];
});
一旦 action 被绑定到这个字段,你就可以从父级资源屏幕上的关系索引中选择这个 action 并且执行它。
标题属性
当 BelongsToMany
字段出现在资源创建和更新操作时,一个下拉选择菜单或搜索框会显示当前资源的 “title” 。例如: Role
资源可以使用 name
属性作为其标题。然后,当资源显示在 BelongsToMany
选择菜单时,这个属性也会显示。
为了自定义这个资源的 “title” ,你可以在类内定义一个 title
成员属性:
public static $title = 'name';
另外,你可以复写资源的 title
方法:
/**
* 获取资源需要被显示的值
* @return string
*/
public function title()
{
return $this->name;
}
远层一对多
MorphMany
字段响应 morphMany
Eloquent 关联。例如:我们假设
Post
与 Comment
模型存在一对多的多态关联。我们可以为 Post
Nova 资源添加关联,如下:
use Laravel\Nova\Fields\MorphMany;
MorphMany::make('Comments')
多态关联
MorphTo
字段对应于 morphTo
Eloquent 关系。 例如,让我们假设一个 Comment
模型与 Post
和 Video
模型都有多态关系。
我们可以将这种关系添加到我们的 Comment
Nova 资源中,如下所示:
use Laravel\Nova\Post;
use Laravel\Nova\Video;
use Laravel\Nova\Fields\MorphTo;
MorphTo::make('Commentable')->types([
Post::class,
Video::class,
])
正如上面的示例中所看到的,types
方法用于指示 MorphTo
字段可以与哪些类型的资源相关联。 Nova 将使用此信息在创建和更新显示 MorphTo
字段的类型选择菜单:
多态标题属性
当在资源创建 / 更新显示
MorphTo
字段时,将自动显示可用资源的 [标题属性](#title-attributes)。
多对多的多态关联
MorphToMany
字段对应于 morphToMany
Eloquent 关系。例如,让我们假设一个 Post
模型与 Tag
模型有多对多多态关系。 我们可以将这种关系添加到我们的 Post
Nova 资源中,如下所示:
use Laravel\Nova\Fields\MorphToMany;
MorphToMany::make('Tags')
中间表字段
如果您的 morphToMany
关系与存储在多对多关系的中间表中的其他 “pivot” 字段进行交互,则您也可以将其附加到 MorphToMany
Nova 关系中。将这些字段附加到关系字段后,它们将显示在相关的资源索引上。
例如,在 taggables
中间表上,假设有一个 notes
字段,其中包含一些关于关系的简单文本注释。我们可以使用 fields
方法将此透视字段附加到 MorphToMany
字段:
MorphToMany::make('Tags')
->fields(function () {
return [
Text::make('Notes'),
];
});
当然,我们很可能也会在关系的反方向定义这个字段。 所以,如果我们在 Post
资源上定义 MorphToMany
字段,我们将在 Tag
资源中定义它的反向关联:
MorphToMany::make('Posts')
->fields(function () {
return [
Text::make('Notes'),
];
});
由于在关系的两端定义字段会导致一些代码重复,nova 允许您将可调用对象传递给 “fields” 方法:
MorphToMany::make('Users')->fields(new TaggableFields)
在这个例子中,’taggablefields’类是一个返回数组的核心字段的简单、可调用的类,
<?php
namespace App\Nova;
use Laravel\Nova\Fields\Text;
class TaggableFields
{
/**
* Get the pivot fields for the relationship.
*
* @return array
*/
public function __invoke()
{
return [
Text::make('Notes'),
];
}
}
标题属性
当 MorphToMany
字段显示在资源创建 / 更新页面上时,下拉选择菜单或搜索菜单将显示资源的 “标题”。例如,Tag
资源可以使用 name
属性作为它的标题。然后,当资源在 MorphToMany
选择菜单中显示时,该属性将显示:
您可以在资源类上定义一个 title 属性,自定义资源的 title 属性值:
public static $title = 'name';
或者你可以重写资源的 title
方法:
/**
* 获取资源类显示的标题。
*
* @return string
*/
public function title()
{
return $this->name;
}
关联搜索
在我们使用 BelongsTo、BelongsToMany、MorphTo、MorphToMany 来建立两个模型的关联关系时,Nova 会默认显示一个简单的下拉选择栏。但是,当我们两个关联模型有很多数据,这样在创建模型时就成一场灾难。例如,你创建用户的年龄,它有着 1、2、3、4 …… 到 200 岁的下拉菜单选项。
您可以将这两个模型的关系标记为 searchable
,此时不会显示下拉菜单选项,而是显示为一个可输入的、漂亮的搜索栏。
要将关系模型中的下拉菜单变为 “搜索栏”,请在关联模型的位置,添加方法 searchable()
:
BelongsTo::make('User')->searchable()
更多建议: