October cms-Backend (后端-列表)

Backend lists 后端列表

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

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

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

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

OptionDescription
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_toolbar
    search:
        prompt: Find records

工具栏配置:

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

搜索配置支持以下选项:

OptionDescription
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">
    <a
        href="<?= 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 directory
        post/                  <=== Model configuration directory
          list_columns.yaml    <=== Model list columns config file
        Post.php               <=== model class

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

# ===================================
#  List Column Definitions
# ===================================

columns:
    name: Name
    email: Email

Column options

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

OptionDescription
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 Name
    type: text

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

full_name:
    label: Full Name
    type: text
    format: Admin:%s (active)

Number

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

age:
    label: Age
    type: number

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

price:
    label: Price
    type: number
    format: $ %.2f

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

Switch

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

enabled:
    label: Enabled
    type: switch

Date & Time

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

created_at:
    label: Date
    type: datetime

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

created_at:
    label: Date
    type: datetime
    format: l jS \of F Y h:i:s A

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

created_at:
    label: Date
    type: datetime
    ignoreTimezone: true

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

Date

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

created_at:
    label: Date
    type: date

Time

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

created_at:
    label: Date
    type: time

Time since

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

created_at:
    label: Date
    type: timesince

Time tense

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

created_at:
    label: Date
    type: timetense

Select

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

full_name:
    label: Full Name
    select: 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: Group
    relation: groups
    select: name

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

users_count:
    label: Users
    relation: users
    useRelationCount: true

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

最佳实践:

 group_name:
     label: Group
     relation: group
     select: name

不良实践:

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

Partial

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

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

Color Picker

colorpicker - displays a color from colorpicker column

color:
    label: Background
    type: 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: Category
        modelClass: Acme\Blog\Models\Category
        conditions: category_id in (:filtered)
        nameFrom: name

    status:
        label: Status
        type: group
        conditions: status in (:filtered)
        options:
            pending: Pending
            active: Active
            closed: Closed

    published:
        label: Hide published
        type: checkbox
        default: 1
        conditions: is_published <> true

    approved:
        label: Approved
        type: switch
        default: 2
        conditions:
            - is_approved <> true
            - is_approved = true

    created_at:
        label: Date
        type: date
        conditions: created_at >= ':filtered'

    published_at:
        label: Date
        type: daterange
        conditions: created_at >= ':after' AND created_at <= ':before'

Scope options

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

OptionDescription
labela name when displaying the filter scope to the user.
typedefines how this scope should be rendered (see Scope types below). Default: group.
conditionsspecifies a raw where query statement to apply to the list model query, the :filtered parameter represents the filtered value(s).
scopespecifies 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)
optionsoptions to use if filtering by multiple items, this option can specify an array or a method name in the modelClass model.
nameFromif filtering by multiple items, the attribute to display for the name, taken from all records of the modelClass model.
defaultcan either be integer(switch,checkbox,number) or array(group,date range,number range) or string(date).
permissionsthe 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.
dependsOna 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: Country
    type: group
    conditions: country_id in (:filtered)
    modelClass: October\Test\Models\Location
    options: getCountryOptions

city:
    label: City
    type: group
    conditions: city_id in (:filtered)
    modelClass: October\Test\Models\Location
    options: getCityOptions
    dependsOn: 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: Status
    type: group
    conditions: status in (:filtered)
    default:
        pending: Pending
        active: Active
    options:
        pending: Pending
        active: Active
        closed: 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 published
    type: checkbox
    default: 1
    conditions: 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: Approved
    type: switch
    default: 1
    conditions:
        - is_approved <> true
        - is_approved = true

Date

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

created_at:
    label: Date
    type: date
    minDate: '2001-01-23'
    maxDate: '2030-10-13'
    yearRange: 10
    conditions: 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: Date
    type: daterange
    minDate: '2001-01-23'
    maxDate: '2030-10-13'
    yearRange: 10
    conditions: 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 carbon
    public 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: Date
    type: daterange
    minDate: '2001-01-23'
    maxDate: '2030-10-13'
    yearRange: 10
    conditions: 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: Age
    type: number
    default: 14
    conditions: 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 Count
    type: numberrange
    default:
        0: 10
        1: 20
    conditions: 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: Username
    type: text
    conditions: username = :value
    size: 2

Extending list behavior 扩展列表行为

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

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对象上可以使用以下方法。

MethodDescription
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对象上可以使用以下方法。

MethodDescription
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 classregisterListColumnTypes 方法在后端注册。
该方法应返回一个数组,其中键是类型名,值是可调用函数。
可调用函数接收三个参数,本地$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 code
        type: uppercase
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值