后端列表

简介

列表行为是一个控制器修饰符,用于轻松地将记录列表添加到页面。 该行为提供可排序和可搜索的列表,其列表中包含可选链接。 该行为提供了控制器操作index,但是列表可以在任何地方呈现,并且可以使用多个列表定义。

列表行为取决于列表列定义模型类。 为了使用列表行为,您应该将它添加到控制器类的$implement属性中。 此外,应定义$listConfig类属性,其值应引用用于配置行为选项的YAML文件。

  1. namespace Acme\Blog\Controllers;
  2. class Categories extends \Backend\Classes\Controller
  3. {
  4. public $implement = ['Backend.Behaviors.ListController'];
  5. public $listConfig = 'list_config.yaml';
  6. }

注意:通常,列表和表单行为在同一个控制器中一起使用。

配置列表行为

$listConfig属性中引用的配置文件以YAML格式定义。 该文件应放入控制器的views目录。 以下是典型列表行为配置文件的示例:

  1. # ===================================
  2. # List Behavior Config
  3. # ===================================
  4. title: Blog Posts
  5. list: ~/plugins/acme/blog/models/post/columns.yaml
  6. modelClass: Acme\Blog\Models\Post
  7. recordUrl: acme/blog/posts/update/:id

列表配置文件中需要以下字段:

字段 描述
title 此列表的标题。
list 配置数组或对列列定义文件的引用,请参阅列表列
modelClass 模型类名称,列表数据从此模型加载。

下面列出的配置选项是可选的。

选项 描述
filter 过滤器配置,请参阅过滤列表
recordUrl 将每个列表记录链接到另一个页面。例如:users/update:id:id部分被记录标识符替换。这允许您链接列表行为和表单行为
recordOnClick 单击记录时要执行的自定义JavaScript代码。
noRecordsMessage 当没有找到记录时显示的消息,可以参考本地化字符串
recordsPerPage 每页显示的记录,没有页面使用0。默认值:0
showPageNumbers 显示带分页的页码。在处理大型表时,禁用此选项可提高列表性能。默认值:true
toolbar 引用Toolbar Widget配置文件或带配置的数组(参见下文)。
showSorting 显示每列的排序链接。默认值:true
defaultSort 在未定义用户首选项时设置默认排序列和方向。支持字符串或带有“column”和“direction”键的数组。
showCheckboxes 显示每条记录旁边的复选框。默认值:false。
showSetup 显示列表列设置按钮。默认值:false。
showTree 显示父/子记录的树层次结构。默认值:false。
treeExpanded 如果默认情况下应该扩展树节点。默认值:false。
customViewPath 指定自定义视图路径以覆盖列表使用的部分,可选。

添加工具栏

要在列表中包含工具栏,请将以下配置添加到列表配置YAML文件中:

  1. toolbar:
  2. buttons: list_toolbar
  3. search:
  4. prompt: Find records

工具栏配置允许:

选项 描述
buttons 使用工具栏按钮引用控制器部分文件。 例如:_list_toolbar.htm
search 引用Search Widget配置文件或带配置的数组。

搜索配置支持以下选项:

选项 描述
prompt 当没有活动搜索时显示的占位符,可以参考本地化字符串
mode 将搜索策略定义为包含所有单词,任何单词或精确短语。 支持的选项:all,any,exact。 默认值:全部。
scope 指定在列表模型中定义的查询范围方法以应用于搜索查询,第一个参数将包含搜索项。
searchOnEnter 将此设置为true将使搜索小部件在开始搜索之前等待按下Enter键(默认行为是,在有人在搜索字段中输入内容然后暂停一小段时间后,它会自动开始搜索)。 默认值:false。

上面提到的工具栏按钮部分应该包含带有一些按钮的工具栏控件定义。 部分还可以包含带有图表的记分板控件。 使用New Post按钮引用由form behavior提供的create操作的工具栏部分示例:

  1. <div data-control="toolbar">
  2. <a
  3. href="<?= Backend::url('acme/blog/posts/create') ?>"
  4. class="btn btn-primary oc-icon-plus">New Post</a>
  5. </div>

过滤列表

要按用户定义的输入过滤列表,请将以下列表配置添加到YAML文件:

  1. filter: config_filter.yaml

filter选项应引用filter configuration file路径或提供带有配置的数组。

定义列表列

列列是使用YAML文件定义的。 列配置使用列配置来创建记录表并在表格单元格中显示模型列。 该文件放在插件的models目录的子目录中。 子目录名称与以小写字母书写的模型类名称匹配。 文件名无关紧要,但columns.yamllist_columns.yaml是常用名称。 示例列表列文件位置:

  1. plugins/
  2. acme/
  3. blog/
  4. models/ <=== Plugin models directory
  5. post/ <=== Model configuration directory
  6. list_columns.yaml <=== Model list columns config file
  7. Post.php <=== model class

下一个示例显示了列列定义文件的典型内容。

  1. # ===================================
  2. # List Column Definitions
  3. # ===================================
  4. columns:
  5. name: Name
  6. email: Email

列选项

对于每列,可以指定这些选项(如果适用):

选项 描述
label 向用户显示列表列时的名称。
type 定义如何呈现此列(请参阅下面的列类型)。
default 如果value为空,则指定列的默认值。
searchable 在列表搜索结果中包含此列。默认值:false。
invisible 指定默认情况下是否隐藏此列。默认值:false。
sortable 指定是否可以对此列进行排序。默认值:true。
clickable 如果设置为false,则在单击列时禁用默认单击行为。默认值:true。
select 定义用于该值的自定义SQL select语句。
valueFrom 定义要用于值的模型属性。
relation 定义模型关系列。
useRelationCount 使用定义的relation的计数作为此列的值。默认值:false
cssClass 将CSS类分配给列容器。
width 设置列宽,可以百分比(10%)或像素(50px)指定。可以有一个没有指定宽度的列,它将被拉伸以占用可用空间。
align 列对齐。可能的值是“left”,“right”和“center”。

可用的列类型

有许多列类型可用于类型设置,它们控制列表列的显示方式。 除了下面指定的本机列类型之外,您还可以定义自定义列类型

Text

text - 显示一个左对齐的文本列

  1. full_name:
  2. label: Full Name
  3. type: text

Number

number - 显示一个数字列,右对齐

  1. age:
  2. label: Age
  3. type: number

Switch

switch - 显示布尔列的开启或关闭状态。

  1. enabled:
  2. label: Enabled
  3. type: switch

Date & Time

datetime - 将列值显示为格式化的日期和时间。 下一个示例将日期显示为Thu,1975年12月25日下午2:15

  1. created_at:
  2. label: Date
  3. type: datetime
  4. # Display datetime exactly as it is stored, ignores October's and the backend user's specified timezones.
  5. ignoreTimezone: true

您还可以指定自定义日期格式,例如1975年12月25日星期四02:15:16 PM:

  1. created_at:
  2. label: Date
  3. type: datetime
  4. format: l jS \of F Y h:i:s A

Date

date - 将列值显示为日期格式M j,Y

  1. created_at:
  2. label: Date
  3. type: date
  4. # Display datetime exactly as it is stored, ignores October's and the backend user's specified timezones.
  5. ignoreTimezone: true

Time

time - 将列值显示为时间格式g:i A

  1. created_at:
  2. label: Date
  3. type: time
  4. # Display datetime exactly as it is stored, ignores October's and the backend user's specified timezones.
  5. ignoreTimezone: true

Time since

timesince - 显示从值到当前时间的人类可读时间差。 例如:10分钟前

  1. created_at:
  2. label: Date
  3. type: timesince
  4. # Display datetime exactly as it is stored, ignores October's and the backend user's specified timezones.
  5. ignoreTimezone: true

Time tense

timetense - 使用当前日期的语法时态显示24小时时间和日期。 例如:今天12:49昨天4:002015年9月18日14:33

  1. created_at:
  2. label: Date
  3. type: timetense
  4. # Display datetime exactly as it is stored, ignores October's and the backend user's specified timezones.
  5. ignoreTimezone: true

Select

select - 允许使用自定义select语句创建列。 任何有效的SQL SELECT语句都适用于此处。

  1. full_name:
  2. label: Full Name
  3. select: concat(first_name, ' ', last_name)

Relation

relation - 允许显示相关列,可以提供关系选项。 此选项的值必须是模型上Active Record relationship的名称。 在下一个示例中,name值将转换为相关模型中的name属性(例如:$model-> name)。

  1. group:
  2. label: Group
  3. relation: groups
  4. select: name

要显示显示相关记录数的列,请使用useRelationCount选项。

  1. users_count:
  2. label: Users
  3. relation: users
  4. useRelationCount: true

注意:使用列上的relation选项会将selected列中的值加载到此列指定的属性中。 建议您将显示关系数据的列命名为名称,而不与现有模型属性冲突,如以下示例所示:

最佳实践:

  1. group_name:
  2. label: Group
  3. relation: group
  4. select: name

糟糕的做法:

  1. # 这将覆盖$record-> group_id的值,这将破坏从列表视图访问关系
  2. group_id:
  3. label: Group
  4. relation: group
  5. select: name

Partial

partial - 渲染partial,path值可以引用partial视图文件,否则列名称用作partial名称。 在partial内部,这些变量是可用的:$value是默认单元格值,$record是用于单元格的模型,$column是配置的类对象Backend::Classes::ListColumn

  1. content:
  2. type: partial
  3. path: ~/plugins/acme/blog/models/comments/_content_column.htm

Color Picker

colorpicker - 显示colorpicker列的颜色

  1. color:
  2. label: Background
  3. type: colorpicker

显示列表

通常列表显示在索引view文件中。 由于列表包含工具栏,因此视图文件将仅包含单个listRender方法调用。

  1. <?= $this->listRender() ?>

多个列表定义

列表行为可以使用命名定义在同一控制器中支持多个列表。 $listConfig属性可以定义为一个数组,其中键是定义名称,值是配置文件。

  1. public $listConfig = [
  2. 'templates' => 'config_templates_list.yaml',
  3. 'layouts' => 'config_layouts_list.yaml'
  4. ];

然后,通过在调用listRender方法时将定义名称作为第一个参数传递,可以显示每个定义:

  1. <?= $this->listRender('templates') ?>

使用列表过滤器

可以通过添加过滤器定义过滤列表配置来过滤列表。 类似地,过滤器由它们自己的包含过滤器范围的配置文件驱动,每个范围是可以过滤列表的方面。 下一个示例显示了过滤器定义文件的典型内容。

  1. # ===================================
  2. # Filter Scope Definitions
  3. # ===================================
  4. scopes:
  5. category:
  6. label: Category
  7. modelClass: Acme\Blog\Models\Category
  8. conditions: category_id in (:filtered)
  9. nameFrom: name
  10. status:
  11. label: Status
  12. type: group
  13. conditions: status in (:filtered)
  14. options:
  15. pending: Pending
  16. active: Active
  17. closed: Closed
  18. published:
  19. label: Hide published
  20. type: checkbox
  21. default: 1
  22. conditions: is_published <> true
  23. approved:
  24. label: Approved
  25. type: switch
  26. default: 2
  27. conditions:
  28. - is_approved <> true
  29. - is_approved = true
  30. created_at:
  31. label: Date
  32. type: date
  33. conditions: created_at >= ':filtered'
  34. published_at:
  35. label: Date
  36. type: daterange
  37. conditions: created_at >= ':after' AND created_at <= ':before'

范围选项

对于每个范围,您可以指定这些选项(如果适用):

选项 描述
label 向用户显示过滤器范围时的名称。
type 定义如何呈现此范围(请参阅下面的范围类型)。 默认值:组。
conditions 指定要应用于列表模型查询的raw where查询语句,:filtered参数表示已过滤的值。
scope 指定在列表模型中定义的查询范围方法以应用于列表查询,第一个参数将包含过滤的值。
options 如果通过多个项过滤使用的选项,此选项可以在modelClass模型中指定数组或方法名称。
nameFrom 如果按多个项过滤,则显示名称的属性,取自modelClass模型的所有记录。
default 可以是整数(开关,复选框,数字)或数组(组,日期范围,数字范围)或字符串(日期)。

可用范围类型

这些类型可用于确定如何显示过滤器范围。

Group

group - 通过一组项过滤列表,通常是通过相关模型,并且需要nameFromoptions定义。 例如:状态名称为打开,关闭等。

  1. status:
  2. label: Status
  3. type: group
  4. conditions: status in (:filtered)
  5. default:
  6. pending: Pending
  7. active: Active
  8. options:
  9. pending: Pending
  10. active: Active
  11. closed: Closed

Checkbox

checkbox - 用作二进制复选框,以将预定义条件或查询应用于列表,可以打开也可以关闭。 使用0表示关闭,使用1表示打开默认值

  1. published:
  2. label: Hide published
  3. type: checkbox
  4. default: 1
  5. conditions: is_published <> true

Switch

switch - 用作切换器在两个预定义条件或查询列表之间切换,不确定,打开或关闭。 使用0表示关闭,1表示不确定,2表示默认值

  1. approved:
  2. label: Approved
  3. type: switch
  4. default: 1
  5. conditions:
  6. - is_approved <> true
  7. - is_approved = true

Date

date - 显示要选择的单个日期的日期选择器。

  1. created_at:
  2. label: Date
  3. type: date
  4. minDate: '2001-01-23'
  5. maxDate: '2030-10-13'
  6. yearRange: 10
  7. conditions: created_at >= ':filtered'

Date Range

daterange - 显示要选择作为日期范围的两个日期的日期选择器。 条件参数以:before:after传递。

  1. published_at:
  2. label: Date
  3. type: daterange
  4. minDate: '2001-01-23'
  5. maxDate: '2030-10-13'
  6. yearRange: 10
  7. conditions: created_at >= ':after' AND created_at <= ':before'

使用日期和日期范围的默认值

  1. myController::extendListFilterScopes(function($filter) {
  2. 'Date Test' => [
  3. 'label' => 'Date Test',
  4. 'type' => 'daterange',
  5. 'default' => $this->myDefaultTime(),
  6. 'conditions' => "created_at >= ':after' AND created_at <= ':before'"
  7. ],
  8. ]);
  9. });
  10. //return value must be instance of carbon
  11. public function myDefaultTime() {
  12. return [
  13. 0 => Carbon::parse('2012-02-02'),
  14. 1 => Carbon::parse('2012-04-02'),
  15. ];
  16. }

Number

number - 显示要输入的单个数字的输入。

  1. age:
  2. label: Age
  3. type: number
  4. default: 14
  5. conditions: age >= ':filtered'

Number Range

numberrange - 显示要输入的两个数字的输入作为数字范围。 条件参数以:min:max传递。

  1. visitors:
  2. label: Visitor Count
  3. type: numberrange
  4. default:
  5. 0:10
  6. 1:20
  7. conditions: vistors >= ':min' and visitors <= ':max'

Text

text - 显示要输入的字符串的文本输入。 您可以指定将在输入大小属性中注入的size属性(默认值:10)。

  1. username:
  2. label: Username
  3. type: text
  4. conditions: username = :value
  5. size: 2

扩展列表行为

有时您可能希望修改默认列表行为,有几种方法可以执行此操作。

覆盖控制器方法

您可以将自己的逻辑用于控制器中的index操作方法,然后可选地调用List behaviorindex父方法。

  1. public function index()
  2. {
  3. //
  4. //Do any custom code here
  5. //
  6. //Call the ListController behavior index() method
  7. $this->asExtension('ListController')->index();
  8. }

覆盖视图

ListController行为有一个主容器视图,您可以通过在控制器目录中创建名为_list_container.htm的特殊文件来覆盖它。 以下示例将向列表添加侧栏:

  1. <?php if ($toolbar): ?>
  2. <?= $toolbar->render() ?>
  3. <?php endif ?>
  4. <?php if ($filter): ?>
  5. <?= $filter->render() ?>
  6. <?php endif ?>
  7. <div class="row row-flush">
  8. <div class="col-sm-3">
  9. [Insert sidebar here]
  10. </div>
  11. <div class="col-sm-9 list-with-sidebar">
  12. <?= $list->render() ?>
  13. </div>
  14. </div>

该行为将调用Lists小部件,该小部件还包含您可以覆盖的众多视图。 这可以通过指定列出配置选项中描述的customViewPath选项来实现。 窗口小部件将首先在此路径中查找视图,然后回退到默认位置。

  1. # Custom view path
  2. customViewPath: $/acme/blog/controllers/reviews/list

注意: 最好使用子目录,例如list,以避免冲突。

例如,要修改列表正文行标记,请在控制器目录中创建名为list/_list_body_row.htm的文件。

  1. <tr>
  2. <?php foreach ($columns as $key => $column): ?>
  3. <td><?= $this->getColumnValue($record, $column) ?></td>
  4. <?php endforeach ?>
  5. </tr>

扩展列定义

您可以通过在控制器类上调用extendListColumns静态方法从外部扩展另一个控制器的列。 此方法可以采用两个参数,$list表示Lists小部件对象,$model表示列表使用的模型。 以此控制器为例:

  1. class Categories extends \Backend\Classes\Controller
  2. {
  3. public $implement = ['Backend.Behaviors.ListController'];
  4. public $listConfig = 'list_config.yaml';
  5. }

使用extendListColumns方法,您可以将额外的列添加到此控制器呈现的任何列表中。 检查$model的类型是否正确是个好主意。 这是一个例子:

  1. Categories::extendListColumns(function($list, $model) {
  2. if (!$model instanceof MyModel)
  3. return;
  4. $list->addColumns([
  5. 'my_column' => [
  6. 'label' => 'My Column'
  7. ]
  8. ]);
  9. });

您还可以通过覆盖控制器类中的listExtendColumns方法在内部扩展列表列。

  1. class Categories extends \Backend\Classes\Controller
  2. {
  3. [...]
  4. public function listExtendColumns($list)
  5. {
  6. $list->addColumns([...]);
  7. }
  8. }

$list对象提供以下方法。

方法 描述
addColumns 将新列添加到列表中
removeColumn 从列表中删除列

每个方法都采用类似于列列配置的列数组。

注入CSS行 class

您可以通过在控制器类上添加listInjectRowClass方法来注入自定义css行类。 此方法可以采用两个参数,$record表示单个模型记录,$definition包含List窗口小部件定义的名称。 您可以返回包含行类的任何字符串值。 这些类将添加到行的HTML标记中。

  1. class Lessons extends \Backend\Classes\Controller
  2. {
  3. [...]
  4. public function listInjectRowClass($lesson, $definition)
  5. {
  6. //Strike through past lessons
  7. if ($lesson->lesson_date->lt(Carbon::today())) {
  8. return 'strike';
  9. }
  10. }
  11. }

扩展过滤范围

您可以通过在控制器类上调用extendListFilterScopes静态方法,从外部扩展另一个控制器的过滤器作用域。 此方法可以使用参数$filter来表示Filter小部件对象。 以此控制器为例:

  1. Categories::extendListFilterScopes(function($filter) {
  2. $filter->addScopes([
  3. 'my_scope' => [
  4. 'label' => 'My Filter Scope'
  5. ]
  6. ]);
  7. });

提供的作用域数组类似于列出过滤器配置

您还可以在内部将过滤器范围扩展到控制器类,只需覆盖listFilterExtendScopes方法。

  1. class Categories extends \Backend\Classes\Controller
  2. {
  3. [...]
  4. public function listFilterExtendScopes($filter)
  5. {
  6. $filter->addScopes([...]);
  7. }
  8. }

$filter对象提供了以下方法。

方法 描述
addScopes 添加新范围以过滤小部件
removeScope 从过滤器小部件中删除范围

扩展模型查询

可以通过覆盖控制器类中的listExtendQuery方法来扩展列表数据库模型的查询查询。 此示例将通过将withTrashed作用域应用于查询来确保列表数据中包含软删除的记录:

  1. public function listExtendQuery($query)
  2. {
  3. $query->withTrashed();
  4. }

列表过滤器模型查询也可以通过覆盖listFilterExtendQuery方法进行扩展:

  1. public function listFilterExtendQuery($query, $scope)
  2. {
  3. if ($scope->scopeName == 'status') {
  4. $query->where('status', '<>', 'all');
  5. }
  6. }

扩展记录集

可以通过覆盖控制器类中的listExtendRecords方法来扩展列表使用的记录集合。 此示例使用记录集合上的sort方法更改记录的排序顺序。

  1. public function listExtendRecords($records)
  2. {
  3. return $records->sort(function ($a, $b) {
  4. return $a->computedVal() > $b->computedVal();
  5. });
  6. }

自定义列类型

自定义列表列类型可以使用插件注册类的“registerListColumnTypes”方法在后端注册。 该方法应返回一个数组,其中键是类型名称,值是可调用函数。 可调用函数接收三个参数,原生$value$column定义对象和模型$record对象。

  1. public function registerListColumnTypes()
  2. {
  3. return [
  4. //A local method, i.e $this->evalUppercaseListColumn()
  5. 'uppercase' => [$this, 'evalUppercaseListColumn'],
  6. //Using an inline closure
  7. 'loveit' => function($value) { return 'I love '. $value; }
  8. ];
  9. }
  10. public function evalUppercaseListColumn($value, $column, $record)
  11. {
  12. return strtoupper($value);
  13. }

使用自定义列表列类型就像使用type选项按名称调用它一样简单。

  1. # ===================================
  2. # List Column Definitions
  3. # ===================================
  4. columns:
  5. secret_code:
  6. label: Secret code
  7. type: uppercase