Tp5·paginate分页分析

关于tp5的paginate方法,我查找了一些文档,没有去讲它的原理是什么样的,我们来分析一下这个方法会做什么

1.控制器中添加入口

首先,我们会在我们的控制器中添加入口,如下 :

public function index(){

        $result = model("News")->order(['id'=>'asc'])->paginate();
        
        $this->assign('list',$result);
        
        return $this->fetch() ; 
    }

它做了什么呢?
它查找news这个库中id正序数据,这个paginate()方法,其实类似于select()方法,执行完之后,它都会执行查询操作,然后返回数据。

2.在html中渲染数据

查询完之后,我们把数据 assign到了模板中,我们看一下我们模板中的使用。

{volist name='list' id='vo'}
      <tr class="text-c">
        <td><input type="checkbox" value="" name=""></td>
        <td>{$vo.id}</td>
        <td class="text-l"><u style="cursor:pointer" class="text-primary"  title="查看">{$vo.title}</u></td>
        <td>{$vo.catid}</td>
        <td><img width="60" height="60" class="picture-thumb" src="{$vo.image}"></td>
        <td>{$vo.update_time}</td>
        <td>{$vo.is_position}</td>
        <!-- 略-->
      {/volist}

我们通过{volist}标签,把数据渲染到界面上,其实这步和paginate关系不太大,这个只是一个步骤。

3.添加分页的标签(重点)

下面就该我们添加分页的标签了

{volist name='list' id='vo'}
      <!-- 略-->
      {/volist}
      </tbody>
    </table>
    <div id="laypage"></div>
  </div>
  
</div>
{:pagination($list)}

核代码:{:pagination($list)}
这是一个分页实现的核心实现,它是一个php的方法,我们把它写在了通用的方法common.php中,我们来看一下。

function pagination($obj){
    if(!$obj){
        return '' ; 
    }
    $params = request()->param();
    return '<div class="imooc-app">'.$obj->appends($params)->render().'</div>';
}

执行了这段代码,会发生什么呢?这段代码会生成一段如下的代码,我们来看看。

<div class="imooc-app">
    <ul class="pagination">
        <li><a href="/admin/news/index.html?page=3">«</a></li> 
        <li><a href="/admin/news/index.html?page=1">1</a></li>
        <li><a href="/admin/news/index.html?page=2">2</a></li>
        <li><a href="/admin/news/index.html?page=3">3</a></li>
        <li class="active"><span>4</span></li><li><a href="/admin/news/index.html?page=5">5</a></li>
        <li><a href="/admin/news/index.html?page=6">6</a></li>
        <li><a href="/admin/news/index.html?page=7">7</a></li> 
        <li><a href="/admin/news/index.html?page=5">»</a></li>
    </ul>
</div>

这样我们就不难分析出来了。
<div class="imooc-app"></div>这段是我们在pagination()方法里拼的,所以render()方法会生成<ul><li>…</li></ui>这一段代码。
我们来看看这段代码生成的url:/admin/news/index.html?page=3
清楚地看到,这个都是带参数的。
这就是为什么appends方法需要request()->param()方法了,它是会把请求里的参数传过来,生成这个参数的。

流程是这样的:
首先我们第一次请求php的paginate();方法,
$result = model(“News”)->order([‘id’=>’asc’])->paginate();
因为是第一次请求paginate()方法,所以并没有page参数,于是page就会默认为0页。
获取到$result,注意result的结构

{"total":31,"per_page":5,"current_page":1,"last_page":7,"data":[]}

它带了分页数据,总条数,每页的条数,当前多少页,最后一页。
这个$result会被分配到模板中
模板中会调用我们common.php中的方法,根据这个结果json,判断一共多少页,于是生成多少个<li>并且在url中添加了page=N

但是注意上面有一个疑惑点:
明明通过php的paginate();方法,查出来的数据是一个object,但是在前端界面中就可以直接使用循环数据,what?我们做了如下的打印。

        {:dump(json_encode($list))}
        {:dump(json_encode($vo))}

打印出来确实是直接给我们转化好了。我们来看一下

//list数据,看到是带data的一个object
{"total":31,"per_page":5,"current_page":1,"last_page":7,"data":[{"id":1,"title":"u6d4bu8bd5u6587u7ae0","small_title":...
//vo数据,已经帮我们解析成了对象,并没有因为list是一个object而出现问题,所以在这个{volist}标签内部肯定给我们做了处理
{"id":1,"title":"u6d4bu8bd5u6587u7ae0","small_title":"aaaa","catid":0,"image":"/uploads/20200321/b53c3d8180c149b2b8fe7bda2e89e2e7.png"...

同样的,我们看一个volist的代码,确实做了处理
没有具体的去细读,但是浏览一下,也能看到它对数组和非数组的处理了。

public function tagVolist($tag, $content)
    {
        $name   = $tag['name'];
        $id     = $tag['id'];
        $empty  = isset($tag['empty']) ? $tag['empty'] : '';
        $key    = !empty($tag['key']) ? $tag['key'] : 'i';
        $mod    = isset($tag['mod']) ? $tag['mod'] : '2';
        $offset = !empty($tag['offset']) && is_numeric($tag['offset']) ? intval($tag['offset']) : 0;
        $length = !empty($tag['length']) && is_numeric($tag['length']) ? intval($tag['length']) : 'null';
        // 允许使用函数设定数据集 <volist name=":fun('arg')" id="vo">{$vo.name}</volist>
        $parseStr = '<?php ';
        $flag     = substr($name, 0, 1);
        if (':' == $flag) {
            $name = $this->autoBuildVar($name);
            $parseStr .= '$_result=' . $name . ';';
            $name = '$_result';
        } else {
            $name = $this->autoBuildVar($name);
        }

        $parseStr .= 'if(is_array(' . $name . ') || ' . $name . ' instanceof thinkCollection || ' . $name . ' instanceof thinkPaginator): $' . $key . ' = 0;';
        // 设置了输出数组长度
        if (0 != $offset || 'null' != $length) {
            $parseStr .= '$__LIST__ = is_array(' . $name . ') ? array_slice(' . $name . ',' . $offset . ',' . $length . ', true) : ' . $name . '->slice(' . $offset . ',' . $length . ', true); ';
        } else {
            $parseStr .= ' $__LIST__ = ' . $name . ';';
        }
        $parseStr .= 'if( count($__LIST__)==0 ) : echo "' . $empty . '" ;';
        $parseStr .= 'else: ';
        $parseStr .= 'foreach($__LIST__ as $key=>$' . $id . '): ';
        $parseStr .= '$mod = ($' . $key . ' % ' . $mod . ' );';
        $parseStr .= '++$' . $key . ';?>';
        $parseStr .= $content;
        $parseStr .= '<?php endforeach; endif; else: echo "' . $empty . '" ;endif; ?>';

        if (!empty($parseStr)) {
            return $parseStr;
        }
        return;
    }

暂无评论

相关推荐

TP5标签之for循环

我们使用的场景是根据用户级别显示星,几级就显示几星,代码如下其实$vo.svalue是一个整数,代表几星 <td>{$vo.s …

tp5中使用Command计划任务

有时候我们定时执行任务的需求,也可能是为了性能,也有可能是需求,不管如何,我们如何在TP5中配合计划任务完成这一功 …

tp5标签们

一、比较标签如: {比较标签 name="变量" value="值"} 内容 {/比较标签} {eq name="name&quo …

微信扫一扫,分享到朋友圈

Tp5·paginate分页分析