当前位置: 代码迷 >> 综合 >> October cms-Backend (后端-列表)
  详细解决方案

October cms-Backend (后端-列表)

热度:38   发布时间:2023-12-06 17:38:23.0

Backend lists 后端列表

  • Introduction
  • Configuring the list behavior
    • Adding a toolbar
    • Filtering the list
  • Defining list columns
    • Column options
  • Available column types
  • Displaying the list
  • Multiple list definitions
  • Using list filters
    • Scope options
    • Available scope types
  • Extending list behavior
    • Overriding controller action
    • Overriding views
    • Extending column definitions
    • Inject CSS row class
    • Extending filter scopes
    • Extending the model query
    • Extending the records collection
    • Custom column types

Introduction 介绍

List behavior controller符号,
用于让大家方便的添加页面的record列表
该behavior提供了可排序和可搜索的列表,并在其record上带有可选链接。
该behavior提供了controller action index
这个list可以在任何地方被渲染并且可以使用多个列表定义。

列表behavior依赖 list column definitions 和 一个model class.
为了使用list behavior,你应该将其添加到controller类的$implement 属性中。
同样,应该定义$ listConfig类属性,其值应引用用于配置behavior选项的YAML文件。

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

Note: 通常,列表和[表单behavior](form)在同一控制器中一起使用。

Configuring the list behavior 配置表单behavior

$listConfig 属性中引用的配置文件以YAML格式定义。
该文件应放置在控制器的 视图目录
下面是一个典型的list behavior配置文件的示例:

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

列表配置文件中必须包含以下字段:

Field Description
title 列表标题
list 配置数组或对列表列定义文件的引用 参见 list columns.
modelClass 一个model类名,列表数据就是从这个model加载的。

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

Option Description
filter 筛选配置 参见 filtering the list.
recordUrl 将每个list record链接到另一个页面。. Eg: users/update:id. :id 是变化值. 它把表单behaviorform behavior与列表behavior连接在了一起
recordOnClick 单击record时执行的自定义JavaScript代码。
noRecordsMessage 找不到记录时显示一条消息, 能关联到本地化 localization string.
recordsPerPage 每页显示的记录数,没有页数使用0。Default: 0
showPageNumbers 分页显示页码。禁用此选项可提高使用大型表时的列表性能 Default: true
toolbar 引用工具栏小部件配置文件或带有配置的数组 (见下).
showSorting 是否显示排序 Default: true
defaultSort 未定义用户首选项时设置默认的排序列和方向 支持string或键为 columndirection的数组.
showCheckboxes 在每个记录旁边显示复选框. Default: false.
showSetup 是否显示set up按钮. Default: false.
showTree 为父子records显示一个继承树结构 Default: false.
treeExpanded 树节点是否展开. Default: false.
customViewPath 指定一个自定义视图路径以覆盖列表使用的部分内容(可选)。

Adding a toolbar 添加一个工具栏

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

toolbar:buttons: list_toolbarsearch:prompt: Find records

工具栏配置:

Option Description
buttons 使用工具栏按钮对controller partial 文件的引用 Eg: _list_toolbar.htm
search 对Search Widget配置文件或具有配置的数组的引用。

搜索配置支持以下选项:

Option Description
prompt 没有活动搜索时显示的占位符,可以本地化 localization string.
mode 定义搜索策略以包含所有单词, 任何单词或确切短语. 支持项有: all, any, exact. Default: all.
scope 指定在list model 中定义的query scope method以应用于搜索查询,第一个参数将包含搜索项。
searchOnEnter 将其设置为true将使搜索窗口小部件在开始搜索之前等待按下Enter键 (默认行为是,当有人在搜索字段中输入内容并停止一小段时间后,它就会自动开始搜索). Default: false.

上面提到的工具栏 buttons partial里也应会包含一些按钮
这个partial也会包含一个带图表的scoreboard control 记分板
例如
一个带New Post按钮的工具栏partial会有一个对应的form behavior提供的 create action

<div data-control="toolbar"><ahref="<?= Backend::url('acme/blog/posts/create') ?>"class="btn btn-primary oc-icon-plus">New Post</a>
</div>

Filtering the list

用户自定义过滤列表,请将以下配置添加到YAML文件:

filter: config_filter.yaml

The filter option should make reference to a filter configuration file path or supply an array with the configuration.
filter 选项连接到过滤配置文件路径或者一个配置数组

Defining list columns 定义列

列表列是使用YAML文件定义的
列表行为使用列配置来创建记录表并在表单元格中显示model列
该文件放置在插件的** models 目录的子目录中。子目录名称与小写的模型类名称匹配。
文件名无关紧要
但是
columns.yaml** 和 list_columns.yaml是通用名称。
示例列表列文件位置:

plugins/acme/blog/models/                  <=== Plugin models directorypost/                  <=== Model configuration directorylist_columns.yaml    <=== Model list columns config filePost.php               <=== model class

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

# ===================================
#  List Column Definitions
# ===================================columns:name: Nameemail: Email

Column options

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

Option Description
label 向用户显示列表列时的名称。
type 定义应如何呈现此列 (see Column types below).
default 如果值为空,则指定列的默认值。
searchable 在列表搜索结果中包括此列。Default: false.
invisible 指定默认情况下是否隐藏此列。 Default: false.
sortable 指定此列是否可以排序. Default: true.
clickable 如果设置为false,则在单击列时禁用默认的单击行为。 Default: true.
select 定义用于该值的定制SQL select语句。
valueFrom 定义要用于值的model属性。
relation 定义model relation列。
useRelationCount 将定义的relation的计数作为此列的值。 Default: false
cssClass 将CSS类分配给列容器。
headCssClass 将CSS类分配给列标题容器。
width 设置列宽,可以以百分比(10%)或像素(50px)的形式指定。可能只有一列未指定宽度,它将被拉伸以占用可用空间。
align 指定列对齐方式。可能的值为 left, right and center.
permissions 当前后端用户必须具有的[permissions](用户#users和权限)才能使用该列。支持单个权限的字符串或仅需要一个权限即可授予访问权限的一组权限。

Available column types 可用的列类型

type setting可以使用多种列类型,它们控制列表列的显示方式。除了下面指定的本机列类型之外,您还可以 自定义类型.

- [Text](#column-text) - [Number](#column-number) - [Switch](#column-switch) - [Date & Time](#column-datetime) - [Date](#column-date) - [Time](#column-time) - [Time since](#column-timesince) - [Time tense](#column-timetense) - [Select](#column-select) - [Relation](#column-relation) - [Partial](#column-partial) - [Colorpicker](#column-colorpicker)

Text

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

full_name:label: Full Nametype: text

你还可以指定自定义文本格式, for example Admin:Full Name (active)

full_name:label: Full Nametype: textformat: Admin:%s (active)

Number

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

age:label: Agetype: number

你还可以指定自定义数字格式 for example currency $ 99.00

price:label: Pricetype: numberformat: $ %.2f

Note: text和number列都支持format属性,此属性遵循PHP sprintf() function. 。值必须是字符串。

Switch

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

enabled:label: Enabledtype: switch

Date & Time

datetime - 将列值显示为格式化的日期和时间.下面例子的日期为 Thu, Dec 25, 1975 2:15 PM.

created_at:label: Datetype: datetime

你还可以指定自定义日期格式 for example Thursday 25th of December 1975 02:15:16 PM:

created_at:label: Datetype: datetimeformat: l jS \of F Y h:i:s A

您可能还希望设置ignoreTimezone: true,以防止在显示的日期和数据库中存储的日期之间进行时区转换,因为默认情况下,后端时区首选项应用于显示值。

created_at:label: Datetype: datetimeignoreTimezone: true

注意: ignoreTimezone 选项也适用于其他与日期和时间相关的字段类型, 包括 date, time, timesincetimetense.

Date

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

created_at:label: Datetype: date

Time

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

created_at:label: Datetype: time

Time since

timesince - 显示从值到当前时间的人类可读时间差. Eg: 10 minutes ago

created_at:label: Datetype: timesince

Time tense

timetense - 使用当前日期的语法时态显示24小时时间和日期 Eg: Today at 12:49, Yesterday at 4:00 or 18 Sep 2015 at 14:33.

created_at:label: Datetype: timetense

Select

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

full_name:label: Full Nameselect: concat(first_name, ' ', last_name)

Relation

relation - 允许显示相关的列,您可以提供一个关系选项。 The value of this option has to be the name of the Active Record relationship on your model. In the next example the name value will be translated to the name attribute found in the related model (eg: $model->name).
此选项的值必须是model上Active Record relationship 的名称。
在下一个示例中,name值将转换为相关模型中的name属性(eg: $model->name).

group:label: Grouprelation: groupsselect: name

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

users_count:label: Usersrelation: usersuseRelationCount: true

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

最佳实践:

 group_name:label: Grouprelation: groupselect: name

不良实践:

# 这将覆写 $record->group_id 将中断从列表视图的访问关系
group_id:label: Grouprelation: groupselect: name

Partial

partial - 渲染一个 partial, path 的值能与partial view文件关联,否则将列名用作partial名称。
partial内部变量为:$value 是默认的单元格值, $record 是用于该单元格的模型,$column 是已配置的类对象Backend\Classes\ListColumn.

content:type: partialpath: ~/plugins/acme/blog/models/comments/_content_column.htm

Color Picker

colorpicker - displays a color from colorpicker column

color:label: Backgroundtype: colorpicker

Displaying the list

Usually lists are displayed in the index view file. Since lists include the toolbar, the view file will consist solely of the single listRender method call.

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

Multiple list definitions

The list behavior can support multiple lists in the same controller using named definitions. The $listConfig property can be defined as an array where the key is a definition name and the value is the configuration file.

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

Each definition can then be displayed by passing the definition name as the first argument when calling the listRender method:

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

Using list filters

Lists can be filtered by adding a filter definition to the list configuration. Similarly filters are driven by their own configuration file that contain filter scopes, each scope is an aspect by which the list can be filtered. The next example shows a typical contents of the filter definition file.

# ===================================
# Filter Scope Definitions
# ===================================scopes:category:label: CategorymodelClass: Acme\Blog\Models\Categoryconditions: category_id in (:filtered)nameFrom: namestatus:label: Statustype: groupconditions: status in (:filtered)options:pending: Pendingactive: Activeclosed: Closedpublished:label: Hide publishedtype: checkboxdefault: 1conditions: is_published <> trueapproved:label: Approvedtype: switchdefault: 2conditions:- is_approved <> true- is_approved = truecreated_at:label: Datetype: dateconditions: created_at >= ':filtered'published_at:label: Datetype: daterangeconditions: created_at >= ':after' AND created_at <= ':before'

Scope options

For each scope you can specify these options (where applicable):

Option Description
label a name when displaying the filter scope to the user.
type defines how this scope should be rendered (see Scope types below). Default: group.
conditions specifies a raw where query statement to apply to the list model query, the :filtered parameter represents the filtered value(s).
scope specifies a query scope method defined in the list model to apply to the list query. The first argument will contain the query object (as per a regular scope method) and the second argument will contain the filtered value(s)
options options to use if filtering by multiple items, this option can specify an array or a method name in the modelClass model.
nameFrom if filtering by multiple items, the attribute to display for the name, taken from all records of the modelClass model.
default can either be integer(switch,checkbox,number) or array(group,date range,number range) or string(date).
permissions the permissions that the current backend user must have in order for the filter scope to be used. Supports either a string for a single permission or an array of permissions of which only one is needed to grant access.
dependsOn a string or an array of other scope names that this scope depends on. When the other scopes are modified, this scope will update.

Filter Dependencies

Filter scopes can declare dependencies on other scopes by defining the dependsOn scope option, which provide a server-side solution for updating scopes when their dependencies are modified. When the scopes that are declared as dependencies change, the defining scope will update dynamically. This provides an opportunity to change the available options to be provided to the scope.

country:label: Countrytype: groupconditions: country_id in (:filtered)modelClass: October\Test\Models\Locationoptions: getCountryOptionscity:label: Citytype: groupconditions: city_id in (:filtered)modelClass: October\Test\Models\Locationoptions: getCityOptionsdependsOn: country

In the above example, the city scope will refresh when the country scope has changed. Any scope that defines the dependsOn property will be passed all current scope objects for the Filter widget, including their current values, as an array that is keyed by the scope names.

public function getCountryOptions()
{return Country::lists('name', 'id');
}public function getCityOptions($scopes = null)
{if (!empty($scopes['country']->value)) {return City::whereIn('country_id', array_keys($scopes['country']->value))->lists('name', 'id');} else {return City::lists('name', 'id');}
}

Note: Scope dependencies with type: group are only supported at this stage.

Available scope types

These types can be used to determine how the filter scope should be displayed.

- [Group](#filter-group) - [Checkbox](#filter-checkbox) - [Switch](#filter-switch) - [Date](#filter-date) - [Date range](#filter-daterange) - [Number](#filter-number) - [Number range](#filter-numberrange) - [Text](#filter-text)

Group

group - filters the list by a group of items, usually by a related model and requires a nameFrom or options definition. Eg: Status name as open, closed, etc.

status:label: Statustype: groupconditions: status in (:filtered)default:pending: Pendingactive: Activeoptions:pending: Pendingactive: Activeclosed: Closed

Checkbox

checkbox - used as a binary checkbox to apply a predefined condition or query to the list, either on or off. Use 0 for off and 1 for on for default value

published:label: Hide publishedtype: checkboxdefault: 1conditions: is_published <> true

Switch

switch - used as a switch to toggle between two predefined conditions or queries to the list, either indeterminate, on or off. Use 0 for off, 1 for indeterminate and 2 for on for default value

approved:label: Approvedtype: switchdefault: 1conditions:- is_approved <> true- is_approved = true

Date

date - displays a date picker for a single date to be selected.

created_at:label: Datetype: dateminDate: '2001-01-23'maxDate: '2030-10-13'yearRange: 10conditions: created_at >= ':filtered'

Date Range

daterange - displays a date picker for two dates to be selected as a date range. The conditions parameters are passed as :before and :after.

published_at:label: Datetype: daterangeminDate: '2001-01-23'maxDate: '2030-10-13'yearRange: 10conditions: created_at >= ':after' AND created_at <= ':before'

To use default value for Date and Date Range

    myController::extendListFilterScopes(function($filter){
    'Date Test' => ['label' => 'Date Test','type' => 'daterange','default' => $this->myDefaultTime(),'conditions' => "created_at >= ':after' AND created_at <= ':before'"],]);});// return value must be instance of carbonpublic function myDefaultTime(){
    return [0 => Carbon::parse('2012-02-02'),1 => Carbon::parse('2012-04-02'),];}

You may also wish to set ignoreTimezone: true to prevent a timezone conversion between the date that is displayed and the date stored in the database, since by default the backend timezone preference is applied to the display value.

published_at:label: Datetype: daterangeminDate: '2001-01-23'maxDate: '2030-10-13'yearRange: 10conditions: created_at >= ':after' AND created_at <= ':before'ignoreTimezone: true

Note: the ignoreTimezone option also applies to the date filter type as well.

Number

number - displays input for a single number to be entered.

age:label: Agetype: numberdefault: 14conditions: age >= ':filtered'

Number Range

numberrange - displays inputs for two numbers to be entered as a number range. The conditions parameters are passed as :min and :max. You may leave either the minimum value blank to search everything up to the maximum value, and vice versa, you may leave the maximum value blank to search everything at least the minimum value.

visitors:label: Visitor Counttype: numberrangedefault:0: 101: 20conditions: visitors >= ':min' and visitors <= ':max'

Text

text - display text input for a string to be entered. You can specify a size attribute that will be injected in the input size attribute (default: 10).

username:label: Usernametype: textconditions: username = :valuesize: 2

Extending list behavior 扩展列表行为

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

  • Overriding controller action
  • Overriding views
  • Extending column definitions
  • Inject CSS row class
  • Extending filter scopes
  • Extending the model query
  • Custom column types

Overriding controller action 覆写controller action

覆写controller中的 index action方法,然后选择调用List behavior index 父方法。

public function index()
{//// Do any custom code here//// Call the ListController behavior index() method$this->asExtension('ListController')->index();
}

Overriding views 覆写views

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

<?php if ($toolbar): ?><?= $toolbar->render() ?>
<?php endif ?><?php if ($filter): ?><?= $filter->render() ?>
<?php endif ?><div class="row row-flush"><div class="col-sm-3">[Insert sidebar here]</div><div class="col-sm-9 list-with-sidebar"><?= $list->render() ?></div>
</div>

behavior调用包含许多你可以覆盖的视图的 Lists widget
如 list configuration options 列表配置选项. 中所述,可以通过指定customViewPath选项来实现。
This is possible by specifying a customViewPath option as described in the list configuration options. 小部件将首先在此路径中查找视图,然后退回到默认位置。

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

Note:最好使用子目录(例如list)以避免冲突。

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

<?php foreach ($columns as $key => $column): ?>
<?= $this->getColumnValue($record, $column) ?>
<?php endforeach ?>

Extending column definitions 扩展列定义

你可以通过在控制器类上调用extendListColumns静态方法来从外部扩展另一个控制器的列
此方法可以使用两个参数
$list 代表Lists窗口小部件对象

$model 代表列表使用的模型
以这个控制器为例:

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

使用extendListColumns方法,您可以在此控制器呈现的任何列表中添加额外的列。最好检查 $model 的类型正确。例子:

    Categories::extendListColumns(function($list, $model){if (!$model instanceof MyModel) {return;}$list->addColumns(['my_column' => ['label' => 'My Column']]);});

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

class Categories extends \Backend\Classes\Controller
{[...]public function listExtendColumns($list){$list->addColumns([...]);}
}

$ list对象上可以使用以下方法。

Method Description
addColumns 将新列添加到列表
removeColumn 从列表中删除一列

每种方法都采用类似于 list column configuration.的列数组。

Inject CSS row class 注入CSS行类

您可以通过在控制器类上添加listInjectRowClass方法来注入定制的CSS行类。该方法可以接受两个参数,
$record代表单个模型record,

$definition包含List小部件定义的名称。
你可以返回任何包含行类的字符串值。这些类将添加到行的HTML标记中。

class Lessons extends \Backend\Classes\Controller
{[...]public function listInjectRowClass($lesson, $definition){// 总结过去的课程if ($lesson->lesson_date->lt(Carbon::today())) {return 'strike';}}
}

特殊的CSS类nolink可用于强制行不可单击,即使为List小部件定义了recordUrlrecordOnClick选项也是如此。
在事件中返回此class类将使records不可单击-例如,对于软删除的行或信息行:

    public function listInjectRowClass($record, $value){if ($record->trashed()) {return 'nolink';}}

Extending filter scopes 扩展过滤范围

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

    Categories::extendListFilterScopes(function($filter) {// 将自定义CSS类添加到Filter小部件本身$filter->cssClasses = array_merge($filter->cssClasses, ['my', 'array', 'of', 'classes']);$filter->addScopes(['my_scope' => ['label' => 'My Filter Scope']]);});

提供的作用域数组类似于list filters configuration列表过滤器配置.。

您还可以在内部将过滤器作用域扩展到controller类,只需覆盖listFilterExtendScopes方法即可。

class Categories extends \Backend\Classes\Controller
{[...]public function listFilterExtendScopes($filter){$filter->addScopes([...]);}
}

在$filter对象上可以使用以下方法。

Method Description
addScopes 向过滤器小部件添加新范围
removeScope 从过滤器小部件中删除范围

Extending the model query 扩展模型查询

列表 database model 的查找查询可以通过覆盖控制器类内的listExtendQuery方法来扩展
通过将 withTrashed 范围应用于查询,此示例将确保将软删除的记录包括在列表数据中:

public function listExtendQuery($query)
{$query->withTrashed();
}

list filter model查询也可以通过重写listFilterExtendQuery方法来扩展:

public function listFilterExtendQuery($query, $scope)
{if ($scope->scopeName == 'status') {$query->where('status', '<>', 'all');}
}

Extending the records collection 扩展记录收集

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

public function listExtendRecords($records)
{return $records->sort(function ($a, $b) {return $a->computedVal() > $b->computedVal();});
}

Custom column types 自定义列类型

Custom list column types can be registered in the back-end with the registerListColumnTypes method of the Plugin registration class. The method should return an array where the key is the type name and the value is a callable function. The callable function receives three arguments, the native $value, the $column definition object and the model $record object.
自定义列表列类型可以使用 Plugin registration class的registerListColumnTypes 方法在后端注册。
该方法应返回一个数组,其中键是类型名,值是可调用函数。
可调用函数接收三个参数,本地$value$column定义对象和模型$record 对象。

public function registerListColumnTypes()
{return [// 一个本地方法, i.e $this->evalUppercaseListColumn()'uppercase' => [$this, 'evalUppercaseListColumn'],// 使用内联闭包'loveit' => function($value) { return 'I love '. $value; }];
}public function evalUppercaseListColumn($value, $column, $record)
{return strtoupper($value);
}

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

# ===================================
#  List Column Definitions
# ===================================columns:secret_code:label: Secret codetype: uppercase
  相关解决方案