该 Backend\Behaviors\RelationController 类是一个控制器行为,用于轻松管理页面上的复杂 模型 关系。
关联行为取决于下方指定的关联类型。为了使用关联行为,你应该将 Backend\Behaviors\RelationController 定义添加到控制器类的 $implement 字段中。此外,$relationConfig 类属性应该被定义,并且其值应该引用用于配置行为属性的 YAML 文件。
namespace Acme\Projects\Controllers;
class Projects extends Controller
{
public $implement = [
\Backend\Behaviors\FormController::class,
\Backend\Behaviors\RelationController::class
];
public $formConfig = 'config_form.yaml';
public $relationConfig = 'config_relation.yaml';
}通常关系控制器会与表单控制器结合使用。
:::
配置文件中引用的$relationConfig属性以 YAML 格式定义。该文件应放置到控制器的视图目录。所需的配置取决于目标模型与相关模型之间的关系类型。
关系配置文件中的第一层字段定义了目标模型中的关系名称。例如。
class Invoice extends Model
{
public $hasMany = [
'items' => \Acme\Pay\Models\InvoiceItem::class,
];
}一个 Invoice 模型,如果它具有一个名为 items 的关系,那么它应该使用相同的关系名称来定义第一级字段。
# config_relation.yaml
items:
label: Invoice Line Item
view:
list: $/acme/pay/models/invoiceitem/columns.yaml
toolbarButtons: create|delete
recordsPerPage: 10
manage:
form: $/acme/pay/models/invoiceitem/fields.yaml以下属性接着用于每个关系名称的定义。
| Property | Description |
|---|---|
| label | a label for the relation, in the singular tense, required. |
| view | configuration specific to the view container, see below. |
| manage | configuration specific to the management popup, see below. |
| pivot | a reference to form field definition file, used for relations with pivot table data. |
| emptyMessage | a message to display when the relationship is empty, optional. |
| readOnly | disables the ability to add, update, delete or create relations. Default: false |
| deferredBinding | defers all binding actions using a session key when it is available. default: false |
| popupSize | change the size of the management popups used, either: giant, huge, large, small, tiny or adaptive. Default: huge |
| valueFrom | defines a custom model attribute to use for the source value. Default comes from the definition name. |
这些配置值可以为 view 或 manage 属性指定,在适用于列表、表单或两者兼有的渲染类型时。
| Property | Type | Description |
|---|---|---|
| form | Form | a reference to form field definition file, see backend form fields. |
| list | List | a reference to list column definition file, see backend list columns. |
| showFlash | Both | enables the display of flash messages after a successful action. Default: true |
| showSearch | List | display an input for searching the records. Default: false |
| showSorting | List | displays the sorting link on each column. Default: true |
| showSetup | List | displays a setup button to configure the list columns and records per page. Default: false |
| defaultSort | List | sets a default sorting column and direction when user preference is not defined. Supports a string or an array with keys column and direction. The direction can be asc for ascending (default) or desc for descending order. |
| recordsPerPage | List | maximum rows to display for each page. |
| noRecordsMessage | List | a message to display when no records are found, can refer to a localization string. |
| conditions | List | specifies a raw where query statement to apply to the list model query. |
| scope | List | specifies a model query scope method defined in the related form model to apply to the list query always. The model that this relationship will be attached to (i.e. the parent model) is passed to this scope method as the second parameter ($query is the first). |
| searchMode | List | defines the search strategy to either contain all words, any word or exact phrase. Supported options: all, any, exact. Default: all. |
| searchScope | List | specifies a model query scope method defined in the related form model to apply to the search query, the first argument will contain the search term. |
| filter | List | a reference to a filter scopes definition file, see backend list filters. |
| customPageName | List | specify a custom variable name to use in the page URL for paginated records. Set to false to disable storing the page number in the URL. |
这些配置值只能指定给 view 属性。
| Property | Type | Description | |
|---|---|---|---|
| showCheckboxes | List | displays checkboxes next to each record. | |
| recordUrl | List | link each list record to another page. Eg: users/update/:id. The :id part is replaced with the record identifier. | |
| customViewPath | List | specify a custom view path to override partials used by the list. | |
| recordOnClick | List | custom JavaScript code to execute when clicking on a record. | |
| toolbarPartial | Both | a reference to a controller partial file with the toolbar buttons. Eg: _relation_toolbar.php. This property overrides the toolbarButtons property. | |
| toolbarButtons | Both | the set of buttons to display. This can be formatted as an array or a pipe separated string, or set to false to show no buttons. Available options are: create, update, delete, add, remove, link, & unlink. Example: `add | remove`. |
| structure | List | options to enable sorting records for the list. |
这些配置值只能为 manage 属性指定。
| Property | Type | Description |
|---|---|---|
| title | Both | a popup title, can refer to a localization string. |
| context | Form | context of the form being displayed. Can be a string or an array with keys: create, update. |
指定 customMessages 属性以覆盖关系控制器使用的默认消息。这些值可以是纯文本,或者可以引用一个 本地化字符串。
customMessages:
buttonCreate: Make Thing
buttonDelete: Destroy Thing您还可以在正在显示的关联字段的上下文中修改消息。以下内容将仅覆盖 items 关系的 createButton 消息。
items:
customMessages:
buttonCreate: New Item!以下消息可作为自定义消息进行覆盖。
::: details 查看可用消息列表
| Message | Default Message |
|---|---|
| buttonCreate | Create :name |
| buttonCreateForm | Create |
| buttonCancelForm | Cancel |
| buttonCloseForm | Close |
| buttonUpdate | Update :name |
| buttonUpdateForm | Update |
| buttonAdd | Add :name |
| buttonAddMany | Add Selected |
| buttonAddForm | Add |
| buttonLink | Link :name |
| buttonDelete | Delete |
| buttonDeleteMany | Delete Selected |
| buttonRemove | Remove |
| buttonRemoveMany | Remove Selected |
| buttonUnlink | Unlink |
| buttonUnlinkMany | Unlink Selected |
| confirmDelete | Are you sure? |
| confirmUnlink | Are you sure? |
| titlePreviewForm | Preview :name |
| titleCreateForm | Create :name |
| titleUpdateForm | Update :name |
| titleLinkForm | Link a New :name |
| titleAddForm | Add a New :name |
| titlePivotForm | Related :name Data |
| flashCreate | :name Created |
| flashUpdate | :name Updated |
| flashDelete | :name Deleted |
| flashAdd | :name Added |
| flashLink | :name Linked |
| flashRemove | :name Removed |
| flashUnlink | :name Unlinked |
| ::: |
关系控制器支持嵌套关系,换句话说,通过关系管理关系。嵌套关系使用标准的字段嵌套语法。例如,countries[cities] 关系定义使得 cities 关系可以通过 countries 关系进行管理。
countries:
label: Country
form: $/acme/location/models/country/fields.yaml
list: $/acme/location/models/country/columns.yaml
countries[cities]:
label: City
form: $/acme/location/models/city/fields.yaml
list: $/acme/location/models/city/columns.yaml嵌套关系定义旨在与 关系表单部件 无缝协作,将
useController属性设置为true。
关系管理器如何显示取决于目标模型中的关系定义。关系类型也将决定配置要求,这些将以粗体显示。以下关系类型可用:
view.list).manage.form)。manage.list)。manage.form)。例如,如果一个 博客文章 有许多 评论,目标模型被设置为该博客文章,并显示一个评论列表,使用 list 定义中的列。点击评论会打开一个弹出表单,其中包含在 form 中定义的字段,用于更新评论。评论也可以用同样的方式创建。下面是关系行为配置文件的一个示例。
# config_relation.yaml
comments:
label: Comment
manage:
form: $/acme/blog/models/comment/fields.yaml
list: $/acme/blog/models/comment/columns.yaml
view:
list: $/acme/blog/models/comment/columns.yaml
toolbarButtons: create|deleteview.list)。manage.list)。manage.form)。例如,如果一个 用户 属于多个 角色,目标模型被设置为用户,并显示一个角色列表,使用来自 list 定义的列。现有角色可以从用户处添加和移除。下面是关系行为配置文件的示例。
# config_relation.yaml
roles:
label: Role
view:
list: $/acme/user/models/role/columns.yaml
toolbarButtons: add|remove
manage:
list: $/acme/user/models/role/columns.yaml
form: $/acme/user/models/role/fields.yamlview.list)。pivot.form)。manage.list),然后是一个数据录入表单(pivot.form)。沿用 多对多 关联中的示例,如果一个角色还带有一个有效期,点击一个角色将打开一个弹窗表单,其中包含在 pivot 中定义的字段,用于更新有效期。下面是关系行为配置文件的示例。
# config_relation.yaml
roles:
label: Role
view:
list: $/acme/user/models/role/columns.yaml
manage:
list: $/acme/user/models/role/columns.yaml
pivot:
form: $/acme/user/models/role/fields.yaml透视数据在通过 pivot 关系定义表单字段和列表列时可用, 请参见下面的示例.
# config_relation.yaml
teams:
label: Team
view:
list:
columns:
name:
label: Name
pivot[team_color]:
label: Team color
manage:
list:
columns:
name:
label: Name
pivot:
form:
fields:
pivot[team_color]:
label: Team colorview.form) 的形式显示。manage.form)。manage.form).manage.list).例如,如果一个 电话 属于一个 人员 关系管理器将显示一个包含在 form 中定义的字段的表单。点击“链接”按钮将显示一个用于与该电话关联的人员列表。点击“取消链接”按钮将解除该电话与该人员的关联。
# config_relation.yaml
person:
label: Person
view:
form: $/acme/user/models/person/fields.yaml
toolbarButtons: link|unlink
manage:
form: $/acme/user/models/person/fields.yaml
list: $/acme/user/models/person/columns.yamlview.form)。manage.form)。manage.form)。manage.list).例如,如果一个Person拥有一部Phone,关系管理器将显示一个表单,其中包含为该Phone在form中定义的字段。当点击“更新”按钮时,会弹出一个窗口,其中的字段现在可编辑。如果该Person已经拥有一部Phone,这些字段将被更新,否则,将为他们创建一个新的Phone。
# config_relation.yaml
phone:
label: Phone
view:
form: $/acme/user/models/phone/fields.yaml
toolbarButtons: update|delete
manage:
form: $/acme/user/models/phone/fields.yaml
list: $/acme/user/models/phone/columns.yaml在任何页面上管理关系之前,必须首先在控制器中通过调用 initRelation 方法初始化目标模型。
$post = Post::where('id', 7)->first();
$this->initRelation($post);表单控制器 将自动在其创建、更新和预览操作上初始化模型。
关系管理器即可通过调用 relationRender 方法,针对指定的关联定义进行显示。例如,如果您想在 预览 页面上显示关系管理器,preview.htm 视图的内容可能如下所示。
<?= $this->formRenderPreview() ?>
<?= $this->relationRender('comments') ?>您可以指示关系管理器以只读模式渲染,方法是将该属性作为第二个参数传递。
<?= $this->relationRender('comments', ['readOnly' => true]) ?>有时您可能希望修改默认关系行为,并且有几种方法可以实现这一点。
提供了一个操纵关系配置的机会。以下示例可用于根据您模型的一个属性来注入不同的 columns.yaml 文件。
public function relationExtendConfig($config, $field, $model)
{
// Make sure the model and field matches those you want to manipulate
if (!$model instanceof MyModel || $field !== 'myField') {
return;
}
// Show a different list for business customers
if ($model->mode == 'b2b') {
$config->view['list'] = '$/author/plugin_name/models/mymodel/b2b_columns.yaml';
}
}提供了操作视图小部件的机会。例如,你可能希望根据模型的某个属性来切换 showCheckboxes。
public function relationExtendViewWidget($widget, $field, $model)
{
// Make sure the model and field matches those you want to manipulate
if (!$model instanceof MyModel || $field !== 'myField') {
return;
}
if ($model->constant) {
$widget->showCheckboxes = false;
}
}由于在该运行时周期的此阶段小部件尚未完成初始化,你无法调用 $widget->removeColumn()。如 列表控制器文档 中所述,addColumns() 方法将按预期工作,但要移除列,我们需要在 relationExtendViewWidget() 方法中监听 'list.extendColumns' 事件。以下示例展示了如何移除列。
public function relationExtendViewWidget($widget, $field, $model)
{
// Make sure the model and field matches those you want to manipulate
if (!$model instanceof MyModel || $field !== 'myField') {
return;
}
// This will work
$widget->bindEvent('list.extendColumns', function () use ($widget) {
$widget->removeColumn('my_column');
});
}提供了一个操作你的关联的管理小部件的机会。
public function relationExtendManageWidget($widget, $field, $model)
{
// Make sure the field is the expected one
if ($field !== 'myField') {
return;
}
// Manipulate widget as needed
}提供了一个操纵您的关系的枢轴部件的机会。
public function relationExtendPivotWidget($widget, $field, $model)
{
// Make sure the field is the expected one
if ($field !== 'myField') {
return;
}
// Manipulate widget as needed
}有两个筛选器部件可以使用以下方法进行扩展, 一个用于 RelationController 的查看模式, 另一个用于其管理模式。
public function relationExtendViewFilterWidget($widget, $field, $model)
{
// Extends the view filter widget
}
public function relationExtendManageFilterWidget($widget, $field, $model)
{
// Extends the manage filter widget
}关于如何在筛选器小部件中通过编程方式添加或删除作用域的示例可在列表控制器文档的扩展筛选器作用域部分中找到。
视图组件通常会在管理组件进行更改时刷新,您可以在此过程发生时注入额外的容器。返回一个包含要发送到浏览器的额外值的数组,例如:
public function relationExtendRefreshResults($field)
{
// Make sure the field is the expected one
if ($field !== 'myField') {
return;
}
return ['#myCounter' => 'Total records: 6'];
}