CakePHP 3.0 中虚拟 field/entity 属性 的分页排序 link
Pagination sort link on a virtual field/entity property in CakePHP 3.0
我想在 CakePHP 3.0 中创建一个 pagination sort link on a virtual field/entity property。
在 CakePHP 2.x 中,我曾经创建一个 virtual field, and then create a pagination sort link on that field. However, in CakePHP 3.0, virtual fields have been replaced by virtual entity properties。
有什么方法可以使它在 CakePHP 3.0 中正常工作吗?
在我的情况下,我有一个 first_name 和 last_name 列,它们在 virtual entity property 中合并为 full_name。我想在 full_name.
上排序
如链接文档中所述,不能在查找中使用虚拟属性。这是设计使然,虚拟属性仅存在于实体中,它们是在 PHP 从数据库中检索数据后构建的。
所以让我们暂时忘掉虚拟属性,专注于查询和计算列。
需要通过sortWhitelist
指定计算列
就像关联模型的列一样,需要在 sortWhitelist
选项中指定计算列才能用于排序!
Cookbook > Controllers > Components > Pagination > Control which Fields Used for Ordering
通过分页选项
这里有一些选项,例如,您可以在分页选项中定义计算列:
$this->paginate = [
// ...
'sortWhitelist' => [
'id',
'first_name',
'last_name',
'full_name',
// ...
],
'fields' => [
'id',
'first_name',
'last_name',
'full_name' => $this->Table->query()->func()->concat([
'first_name' => 'literal',
'last_name' => 'literal'
]),
// ...
],
'order' => [
'full_name' => 'DESC'
]
];
自定义查找器
另一个更可重用的选项是使用自定义查找器:
$this->paginate = [
// ...
'sortWhitelist' => [
'id',
'first_name',
'last_name',
'full_name',
// ...
],
'finder' => 'withFullName',
'order' => [
'full_name' => 'DESC'
]
];
public function findWithFullName(\Cake\ORM\Query $query, array $options)
{
return $query->select([
'id',
'first_name',
'last_name',
'full_name' => $query->func()->concat([
'first_name' => 'literal',
'last_name' => 'literal'
]),
// ...
]);
}
- Cookbook > Controllers > Components > Pagination > Using Controller::paginate()
- Cookbook > ... ORM > Retrieving Data & Results Sets > Custom Finder Methods
单独的自定义查询
也可以直接将查询对象传递给Controller::paginate()
:
$this->paginate = [
// ...
'sortWhitelist' => [
'id',
'first_name',
'last_name',
'full_name',
// ...
],
'order' => [
'full_name' => 'DESC'
]
];
$query = $this->Table
->find()
->select(function (\Cake\ORM\Query $query) {
return [
'id',
'first_name',
'last_name',
'full_name' => $query->func()->concat([
'first_name' => 'literal',
'last_name' => 'literal'
]),
// ...
];
});
$results = $this->paginate($query);
将您的默认排序顺序设置为与您的虚拟字段相同:
public $paginate = [
'order' => [
'first_name' => 'ASC',
'last_name' => 'ASC',
]
];
然后只需将以下内容添加到您的视图中,以防止分页器覆盖默认顺序,除非用户指定:
if (empty($_GET['direction'])) { $this->Paginator->options(['url' => ['direction' => null, 'sort' => null]]); }
我想在 CakePHP 3.0 中创建一个 pagination sort link on a virtual field/entity property。
在 CakePHP 2.x 中,我曾经创建一个 virtual field, and then create a pagination sort link on that field. However, in CakePHP 3.0, virtual fields have been replaced by virtual entity properties。
有什么方法可以使它在 CakePHP 3.0 中正常工作吗?
在我的情况下,我有一个 first_name 和 last_name 列,它们在 virtual entity property 中合并为 full_name。我想在 full_name.
上排序如链接文档中所述,不能在查找中使用虚拟属性。这是设计使然,虚拟属性仅存在于实体中,它们是在 PHP 从数据库中检索数据后构建的。
所以让我们暂时忘掉虚拟属性,专注于查询和计算列。
需要通过sortWhitelist
指定计算列
就像关联模型的列一样,需要在 sortWhitelist
选项中指定计算列才能用于排序!
Cookbook > Controllers > Components > Pagination > Control which Fields Used for Ordering
通过分页选项
这里有一些选项,例如,您可以在分页选项中定义计算列:
$this->paginate = [
// ...
'sortWhitelist' => [
'id',
'first_name',
'last_name',
'full_name',
// ...
],
'fields' => [
'id',
'first_name',
'last_name',
'full_name' => $this->Table->query()->func()->concat([
'first_name' => 'literal',
'last_name' => 'literal'
]),
// ...
],
'order' => [
'full_name' => 'DESC'
]
];
自定义查找器
另一个更可重用的选项是使用自定义查找器:
$this->paginate = [
// ...
'sortWhitelist' => [
'id',
'first_name',
'last_name',
'full_name',
// ...
],
'finder' => 'withFullName',
'order' => [
'full_name' => 'DESC'
]
];
public function findWithFullName(\Cake\ORM\Query $query, array $options)
{
return $query->select([
'id',
'first_name',
'last_name',
'full_name' => $query->func()->concat([
'first_name' => 'literal',
'last_name' => 'literal'
]),
// ...
]);
}
- Cookbook > Controllers > Components > Pagination > Using Controller::paginate()
- Cookbook > ... ORM > Retrieving Data & Results Sets > Custom Finder Methods
单独的自定义查询
也可以直接将查询对象传递给Controller::paginate()
:
$this->paginate = [
// ...
'sortWhitelist' => [
'id',
'first_name',
'last_name',
'full_name',
// ...
],
'order' => [
'full_name' => 'DESC'
]
];
$query = $this->Table
->find()
->select(function (\Cake\ORM\Query $query) {
return [
'id',
'first_name',
'last_name',
'full_name' => $query->func()->concat([
'first_name' => 'literal',
'last_name' => 'literal'
]),
// ...
];
});
$results = $this->paginate($query);
将您的默认排序顺序设置为与您的虚拟字段相同:
public $paginate = [
'order' => [
'first_name' => 'ASC',
'last_name' => 'ASC',
]
];
然后只需将以下内容添加到您的视图中,以防止分页器覆盖默认顺序,除非用户指定:
if (empty($_GET['direction'])) { $this->Paginator->options(['url' => ['direction' => null, 'sort' => null]]); }