CODESHIF - PHP http://codeshif.com/category/php/ zh-CN PHP技巧 Wed, 24 Nov 2021 14:50:20 +0800 Wed, 24 Nov 2021 14:50:20 +0800 ThinkPHP数组分页功能详解 http://codeshif.com/archives/45.html http://codeshif.com/archives/45.html Wed, 24 Nov 2021 14:50:20 +0800 admin ThinkPHP数组分页功能详解

[TOC]

原理

首先找到随便一段PHP查询代码带有paginate的,例如

$data_list = UserModel::where($map)->order('sort,role,id desc')->paginate();

Ctrl+LeftClick点进去看看:

Model.php

会发现进入到了Model.php文件:
见名思意,该文件是MVC框架的Model实现,不过注意这里:

 * @method Paginator|$this paginate() static 分页

拉到顶部可以看到如下:

/**
 * Class Model
 * @package think
 * @mixin Query
 * @method $this scope(string|array $scope) static 查询范围
 * @method $this where(mixed $field, string $op = null, mixed $condition = null) static 查询条件
 * @method $this whereRaw(string $where, array $bind = [], string $logic = 'AND') static 表达式查询
 * @method $this whereExp(string $field, string $condition, array $bind = [], string $logic = 'AND') static 字段表达式查询
 * @method $this when(mixed $condition, mixed $query, mixed $otherwise = null) static 条件查询
 * @method $this join(mixed $join, mixed $condition = null, string $type = 'INNER', array $bind = []) static JOIN查询
 * @method $this view(mixed $join, mixed $field = null, mixed $on = null, string $type = 'INNER') static 视图查询
 * @method $this with(mixed $with, callable $callback = null) static 关联预载入
 * @method $this count(string $field = '*') static Count统计查询
 * @method $this min(string $field, bool $force = true) static Min统计查询
 * @method $this max(string $field, bool $force = true) static Max统计查询
 * @method $this sum(string $field) static SUM统计查询
 * @method $this avg(string $field) static Avg统计查询
 * @method $this field(mixed $field, boolean $except = false, string $tableName = '', string $prefix = '', string $alias = '') static 指定查询字段
 * @method $this fieldRaw(string $field) static 指定查询字段
 * @method $this union(mixed $union, boolean $all = false) static UNION查询
 * @method $this limit(mixed $offset, integer $length = null) static 查询LIMIT
 * @method $this order(mixed $field, string $order = null) static 查询ORDER
 * @method $this orderRaw(string $field, array $bind = []) static 查询ORDER
 * @method $this cache(mixed $key = null , integer|\DateTime $expire = null, string $tag = null) static 设置查询缓存
 * @method mixed value(string $field, mixed $default = null) static 获取某个字段的值
 * @method array column(string $field, string $key = '') static 获取某个列的值
 * @method $this find(mixed $data = null) static 查询单个记录
 * @method $this findOrFail(mixed $data = null) 查询单个记录
 * @method Collection|$this[] select(mixed $data = null) static 查询多个记录
 * @method $this get(mixed $data = null,mixed $with = [],bool $cache = false, bool $failException = false) static 查询单个记录 支持关联预载入
 * @method $this getOrFail(mixed $data = null,mixed $with = [],bool $cache = false) static 查询单个记录 不存在则抛出异常
 * @method $this findOrEmpty(mixed $data = null) static 查询单个记录  不存在则返回空模型
 * @method Collection|$this[] all(mixed $data = null,mixed $with = [],bool $cache = false) static 查询多个记录 支持关联预载入
 * @method $this withAttr(array $name,\Closure $closure = null) static 动态定义获取器
 * @method $this withJoin(string|array $with, string $joinType = '') static
 * @method $this withCount(string|array $relation, bool $subQuery = true) static 关联统计
 * @method $this withSum(string|array $relation, string $field, bool $subQuery = true) static 关联SUM统计
 * @method $this withMax(string|array $relation, string $field, bool $subQuery = true) static 关联MAX统计
 * @method $this withMin(string|array $relation, string $field, bool $subQuery = true) static 关联Min统计
 * @method $this withAvg(string|array $relation, string $field, bool $subQuery = true) static 关联Avg统计
 * @method Paginator|$this paginate() static 分页
 */

也就是说啊,这个Model.php的方法是从Query.php这里搞过来的,那我们来看一下Query.php里面是什么

Query.php

Query.php文件主要是针对数据库链式操作的类,不过其中含有这么一个方法:

/**
     * 分页查询
     * @access public
     * @param  int|array $listRows 每页数量 数组表示配置参数
     * @param  int|bool  $simple   是否简洁模式或者总记录数
     * @param  array     $config   配置参数
     *                            page:当前页,
     *                            path:url路径,
     *                            query:url额外参数,
     *                            fragment:url锚点,
     *                            var_page:分页变量,
     *                            list_rows:每页数量
     *                            type:分页类名
     * @return $this[]|\think\Paginator
     * @throws DbException
     */
    public function paginate($listRows = null, $simple = false, $config = [])

那么这也就是说,我们之前的代码:

$data_list = UserModel::where($map)->order('sort,role,id desc')->paginate();

其方法->paginate();是调用的Query.php中的paginate方法。

DIY实现分页

解释

如果我们想自己查询数据库,例如使用->select();方法:

$data_list = UserModel::where($map)->order('sort,role,id desc')->select();

没错,得到的$data_list是数组类型,数组类型并不返回Model本身的实例,则无法继续像这样调用paginate方法了:

$data_list = UserModel::where($map)->order('sort,role,id desc')->select();
$data_list->paginate();    //    这里是错误的,因为数组没有paginate方法可调用

怎么办?虽然无法调用了,但是我们可以自己创造实例去呀?
但是我们需要先了解paginate方法的类在哪对吧?

Paginator.php

根据查询,弄到了paginate的方法原类对象是Paginator,所在位置thinkphp/library/think/Paginator.php

它是一个abstract抽象类,抽象类是不能实例化的。

abstract class Paginator implements ArrayAccess, Countable, IteratorAggregate, JsonSerializable

不过我们可以提前看看它所提供的方法:

public function __construct($items, $listRows, $currentPage = null, $total = null, $simple = false, $options = [])
public static function make($items, $listRows, $currentPage = null, $total = null, $simple = false, $options = [])

这两个方法,一个是用于构造对象用的构造函数__construct,另外一个是静态方法make,看参数应该知道,这就是我们想要找的类。

Bootstrap.php

再来看看Bootstrap,这个类继承自Paginator抽象类,也就是Paginator抽象类的实现类,

class Bootstrap extends Paginator

所在位置:thinkphp/library/think/paginator/driver/Bootstrap.php

在Query.php中是这么实例化它的:

$config = Container::get('config')->pull('paginate');

/** @var Paginator $class */
$class = false !== strpos($config['type'], '\\') ? $config['type'] : '\\think\\paginator\\driver\\' . ucwords($config['type']);

return $class::make($results, $listRows, $page, $total, $simple, $config);

$config['type']来自于thinkphp/convention.php配置文件的:

//分页配置
'paginate'   => [
    'type'      => 'bootstrap',
    'var_page'  => 'page',
    'list_rows' => 15,
],

所以,我们接下来可以自己去创造实例去了。

自己创造实例

根据以上知识,我们只需要自行实例化Bootstrap类,并将查询的数组数据注入至Bootstrap实例,最后将Bootstrap实例交给ThinkPHP来处理就好了,非常简单。

$data_list = UserModel::where($map)->order('sort,role,id desc')->select();
$config = Container::get('config')->pull('paginate');
/*

$listRows 每页数量 数组表示配置参数
$simple   是否简洁模式或者总记录数
$config 配置参数
    page:当前页,
    path:url路径,
    query:url额外参数,
    fragment:url锚点,
    var_page:分页变量,
    list_rows:每页数量
    type:分页类名
*/

// 原型:
// public static function make($items, $listRows, $currentPage = null, $total = null, $simple = false, $options = [])

$data_list = Bootstrap::make($data_list,$config['list_rows'],1,15,false,$config);

此时,$data_list就拥有了原数组就有了Bootstrap实例的外衣,交给ThinkPHP去处理时,就可以分页了。

]]>
0 http://codeshif.com/archives/45.html#comments http://codeshif.com/feed/category/php/
EvaThumber截取图片失败,尺寸过大解决办法 http://codeshif.com/archives/27.html http://codeshif.com/archives/27.html Thu, 27 Dec 2018 21:37:00 +0800 admin EvaThumber截取图片失败,尺寸过大解决办法

找到/src/EvaThumber/Thumber.php文件,第509

加入以下代码:

//  防止尺寸过大,图片并没有裁切的尺寸大造成失败
if($crop > $imageWidth || $gravity > $imageHeight){
    $min1 = min($crop,$gravity);
    $min2 = min($imageWidth, $imageHeight);

    if($min1 <= $min2){
        $crop = $gravity = $min1;
    }else{
        $crop = $gravity = $min2;
    }
}

然后就好了,
如果给与的截取宽高大于图片的宽高,就取给与的最小值进行判断,
如果最小值小于图片宽高,就用这个最小值作为基准进行截取图片。

如果最小值大于图片宽高,就用图片的宽高最小值最为基准,进行裁切图片。

]]>
0 http://codeshif.com/archives/27.html#comments http://codeshif.com/feed/category/php/
PHPStorm LiveTemplate如何设置$变量符号 http://codeshif.com/archives/18.html http://codeshif.com/archives/18.html Sat, 03 Nov 2018 10:23:00 +0800 admin 我们知道PHPStorm有个神技功能是Live Template
当然了,操作方法非常简单,只是选中代码 -> 点击顶部菜单Tools -> 再点击Save as Live Template
就可以很简单的把代码保存成代码模板了,但是这不是重点,
重点是当你设置一些代码之后发现代码变量中的$符合和你的代码模板中的$重叠了!

那怎么办呢?
比如我要实现一键获取$_GET[]的参数,例如如下:
$username = $_GET['username']

在代码模板里面要这么设置:

$$$NAME$ = $_GET['$NAME$'];
$END$

注意看最前面有3个$$$$$$NAME$是啥意思呢?
$$其实是PHPStorm里面的转义字符,将$$转义成为了$,呵呵!

那么$NAME$当然是个变量啦,因为后面也用到一样的了,所以就可以设置成变量了,
$END$是内置变量,它代表键盘光标最后停留的位置。

]]>
0 http://codeshif.com/archives/18.html#comments http://codeshif.com/feed/category/php/
Atom Beautify插件无法格式化PHP代码及问题处理办法 http://codeshif.com/archives/13.html http://codeshif.com/archives/13.html Sat, 27 Oct 2018 01:49:00 +0800 admin Atom Beautify需要一个php-cs-fixer的插件,
安装该插件的方法,可以参照php-cs-fixer的安装方式安装,
也可以使用brew install php-cs-fixer的方式安装。

但是安装完毕使用的时候也许会有个错误?
比如,我安装完成后对代码进行ctrl+alt+b就发现代码并没有格式化……

为什么啊?原来是我的PHP代码出现了问题,所以在安装php-cs-fixer之前,还是先安装个linter-php吧,
AtomInstall搜索php就可以找到该选项了,安装就可以发现自己带代码有没有错误了。

]]>
0 http://codeshif.com/archives/13.html#comments http://codeshif.com/feed/category/php/