Php 如何为分页器排序顺序使用函数表达式?
在对数据库中的ip地址进行排序时,我使用MySQL提供的INET_ATON函数 现在,当我试图在CakePHP3中实现这一点时(我是新手),我失败了 以下是我得到的:Php 如何为分页器排序顺序使用函数表达式?,php,mysql,cakephp,pagination,cakephp-3.0,Php,Mysql,Cakephp,Pagination,Cakephp 3.0,在对数据库中的ip地址进行排序时,我使用MySQL提供的INET_ATON函数 现在,当我试图在CakePHP3中实现这一点时(我是新手),我失败了 以下是我得到的: class Ip extends Entity { /** * Fields that can be mass assigned using newEntity() or patchEntity(). * * Note that when '*' is set to true, this a
class Ip extends Entity
{
/**
* Fields that can be mass assigned using newEntity() or patchEntity().
*
* Note that when '*' is set to true, this allows all unspecified fields to
* be mass assigned. For security purposes, it is advised to set '*' to false
* (or remove it), and explicitly make individual fields accessible as needed.
*
* @var array
*/
protected $_accessible = [
'*' => true,
'id' => false,
];
protected $_virtual = ['ip_address'];
protected function _getIpAddress()
{
$vc = (new FunctionsBuilder())->inet_aton(['ip' => 'literal']);
return $vc;
}
}
这是我的控制器方法
<?php
namespace App\Controller;
use App\Controller\AppController;
use Cake\ORM\TableRegistry;
use Cake\Validation\Validator;
use Cake\Database\FunctionsBuilder;
/**
* Ips Controller
*
* @property \App\Model\Table\IpsTable $Ips
*/
class IpsController extends AppController
{
/**
* Index method
*
* @return void
*/
public function index()
{
$this->paginate = [
'contain' => ['Users'],
'order' => [(new FunctionsBuilder())->inet_aton(['ip' => 'literal'])]
];
$this->set('ips', $this->paginate($this->Ips));
$this->set('_serialize', ['ips']);
}
改用附加列
就我个人而言,我会将IP的整数表示另外存储在一个单独的列中,并使用该列进行排序。由于DBMS可以使用索引,这不仅可以为您提供更好的性能,还可以避免处理函数表达式所需的额外逻辑,并让您像往常一样使用分页组件
在视图中,只需使用新列的名称,并手动定义要为排序链接显示的名称,如
<?= $this->Paginator->sort('ip_int', 'IP') ?>
或者使用自定义查询,如
$query = $this->Ips->find();
$query->orderAsc($query->func()->inet_aton(['ip' => 'literal']));
$this->set('ips', $this->paginate($query));
您必须使用一点自定义逻辑才能使其与视图一起工作,因为分页辅助程序设计为仅处理列名(字符串)
具有视图辅助对象的动态排序
现在,如果还想使用分页视图帮助器,则必须创建一些逻辑来计算帮助器生成的排序列和方向,并手动配置选项/查询,类似于上面的示例
下面是一个基本示例,使用Query::orderAsc()
和Query::orderDesc()
方法可以在使用函数表达式时定义方向(表达式不能通过Query::order()
与其他值组合)
这应该主要是自我解释,首先检查分页器助手生成的排序
键是否已传递,如果未传递,或者是,并且是您的IP列,请针对可能设置的方向
键应用自定义顺序。如果sort
不是您的IP列,只需忽略它,分页器将拾取值并像往常一样计算和使用它们
类似地,您可以在手动创建orderClauseeExpression
实例时设置方向,但我个人可能会坚持使用自定义查询和函数生成器
再干一点?
如果您想让它更具可重用性,您可能需要研究自定义/扩展分页器组件、自定义查找器和行为
实体是数据容器
最后但并非最不重要的一点是,您的实体与所有这些无关,它只是一个数据容器,所以抛开虚拟财产,它们无论如何都不能用于查找
另见
您想对数据进行排序吗?杰普,我想对ip地址进行排序,使1.1.1.18不会出现在1.1.1.2之前。您可以添加控制器/索引方法吗?还要添加您现在的输出以及您希望看到的实际内容?您希望将ip视为描述顺序吗?还是作为ip模式?非常好的解释!我抛弃了虚拟财产,选择了查看助手的方法!尽管使用整数表示的额外列可能是最简单的方法。
$query = $this->Ips->find();
$query->orderAsc($query->func()->inet_aton(['ip' => 'literal']));
$this->set('ips', $this->paginate($query));
$query = $this->Ips->find();
$sort = $this->request->query('sort');
if ($sort === null || $sort === 'ip') {
$method = 'orderAsc';
if ($this->request->query('direction') === 'desc') {
$method = 'orderDesc';
}
$query->{$method}($query->func()->inet_aton(['ip' => 'literal']));
}
$this->set('articles', $this->paginate($query));