Pagination sort link on a virtual field/entity property in CakePHP 3.0

本小妞迷上赌 提交于 2019-11-27 06:04:54

问题


I want to create a pagination sort link on a virtual field/entity property in CakePHP 3.0.

In CakePHP 2.x I used to create a 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.

Is there any way I can get this working in CakePHP 3.0?

In my situation, I have a first_name and last_name column, which are combined as full_name in a virtual entity property. I want to sort on the full_name.


回答1:


As stated in the linked docs, virtual properties cannot be used in finds. That's by design, virtual properties only live in entities, they are built in PHP after data has been retrieved from the database.

So let's forget about virtual properties for a moment, and concentrate on queries and computed columns.

Computed columns need to be specified via sortWhitelist

Just like columns of associated models, computed columns need to be specified in the sortWhitelist option in order to be useable for sorting!

Cookbook > Controllers > Components > Pagination > Control which Fields Used for Ordering

Via pagination options

You have some options here, for example you could define computed columns in the pagination options:

$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'
    ]
];

A custom finder

Another, more reusable option would be to use a custom finder:

$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

Separate custom query

It's also possible to directly pass query objects to 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);



回答2:


Set your default sort order to be the same as your virtual field:

public $paginate = [
  'order' => [
    'first_name' => 'ASC',
    'last_name' => 'ASC',
  ]
];

Then just add the following to your View to prevent the paginator from overriding the default order unless specified by the user:

if (empty($_GET['direction'])) { $this->Paginator->options(['url' => ['direction' => null, 'sort' => null]]); }


来源:https://stackoverflow.com/questions/31763413/pagination-sort-link-on-a-virtual-field-entity-property-in-cakephp-3-0

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!