接口數(shù)據(jù)使用ThinkPHP5的自定義分頁

tp程序自帶了分頁的功能逆趋,用起來很是方便哮伟,特別是默認(rèn)情況下直接連樣式都寫好了正蛙。非常的省心统阿。但這只是對于數(shù)據(jù)庫操作而言逗柴。如果我們想要對請求的接口數(shù)據(jù)進(jìn)行分頁灾锯,那么該如何使用paginate方法呢爆哑?

修改說明

增加了注釋呻待,參考附錄代碼砰盐。
此代碼的使用場景:在php中curl請求帶分頁的接口中使用
解決html顯示異常肿仑,模板中使用raw方法

知其然

我們首先來查看tp數(shù)據(jù)的分頁流程是怎么樣的谈撒。先寫一個(gè)數(shù)據(jù)庫分頁的代碼

 $page = Db::name("null")
            ->paginate();
        $page->render();

使用ctrl+鼠標(biāo)左鍵腥泥,進(jìn)入paginate方法中。

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

        $page = $page < 1 ? 1 : $page;

        $config['path'] = isset($config['path']) ? $config['path'] : call_user_func([$class, 'getCurrentPath']);

        if (!isset($total) && !$simple) {
            $options = $this->getOptions();

            unset($this->options['order'], $this->options['limit'], $this->options['page'], $this->options['field']);

            $bind    = $this->bind;
            $total   = $this->count();
            $results = $this->options($options)->bind($bind)->page($page, $listRows)->select();
        } elseif ($simple) {
            $results = $this->limit(($page - 1) * $listRows, $listRows + 1)->select();
            $total   = null;
        } else {
            $results = $this->page($page, $listRows)->select();
        }
        return $class::make($results, $listRows, $page, $total, $simple, $config);

這里只粘貼了重要代碼啃匿。我們看最后一句蛔外,$class 的實(shí)例化在上面代碼塊的第一行,這個(gè)類就是分頁驅(qū)動類溯乒。調(diào)用了make方法夹厌。我們再跟蹤進(jìn)make方法進(jìn)行查看

    public static function make($items, $listRows, $currentPage = null, $total = null, $simple = false, $options = [])
    {
        return new static($items, $listRows, $currentPage, $total, $simple, $options);
    }

我們可以看一下參數(shù)名,currentPage裆悄,當(dāng)前頁矛纹,totoal總共。這里應(yīng)該就是我們要找的分頁方法了灯帮。

   /** @var bool 是否為簡潔模式 */
    protected $simple = false;

    /** @var Collection 數(shù)據(jù)集 */
    protected $items;

    /** @var integer 當(dāng)前頁 */
    protected $currentPage;

    /** @var  integer 最后一頁 */
    protected $lastPage;

    /** @var integer|null 數(shù)據(jù)總數(shù) */
    protected $total;

    /** @var  integer 每頁的數(shù)量 */
    protected $listRows;

    /** @var bool 是否有下一頁 */
    protected $hasMore;

    /** @var array 一些配置 */
    protected $options = [
        'var_page' => 'page',
        'path'     => '/',
        'query'    => [],
        'fragment' => '',
    ];

擼起袖子干

我們接下來可以試著寫個(gè)demo調(diào)用一下看看崖技。
make 方法需要傳入的參數(shù)都已經(jīng)在paginate類里聲明過了。都是漢語注釋钟哥。

$result = $this->api();
        $total = count($result);
        $page = Paginator::make(null, 10, 0, $total, false, []);
        $this->assign("data", $result);
        $this->assign("page", $page);

我們這里值先嘗試進(jìn)行傳遞迎献,出錯之后再進(jìn)行修改。訪問這個(gè)方法腻贰。發(fā)現(xiàn)系統(tǒng)報(bào)錯了

Cannot instantiate abstract class think\Paginator

paginator 是一個(gè)抽象類吁恍,無法實(shí)例化,那這個(gè)時(shí)候我們需要找到他的實(shí)現(xiàn)類是哪一個(gè)播演。得益于intellij方便的index功能冀瓦,我們只需要ctrl+鼠標(biāo)左鍵點(diǎn)擊Pageinator這個(gè)類的名字,我們會發(fā)現(xiàn)長長的列表中有一個(gè)驚喜

 class Bootstrap extends Paginator

我們實(shí)例化Bootstrap試一下写烤。代碼如下

  public function page()
    {
        //模擬接口請求
        $result = $this->api();
        $total = count($result);
        $page = Bootstrap::make(null, 10, 0, $total, false, []);
        $this->assign("data", $result);
        $this->assign("page", $page);
        return $this->fetch();
    }


    private function api()
    {
        return ["最后的生還者", "神秘海域", "塞爾達(dá)傳說", "獵天使魔女", "光環(huán)", "極品飛車", "使命召喚", "最后的守護(hù)者", "戰(zhàn)神", "鬼泣", "仁王",
            "超級馬里奧", "地平線-零之曙光", "怪物獵人", "DOOM", "無冬", "風(fēng)之旅人"];
    }
分頁顯示

這時(shí)候我們發(fā)現(xiàn)翼闽,我們的分頁已經(jīng)顯示出來了,只不過效果很難看洲炊。tp分頁渲染使用的是bootstrap感局,從上面類的名字我們也能夠看的出來尼啡。我們引入bootstrap試試

引入css樣式

引入css樣式之后,我們發(fā)現(xiàn)分頁效果已經(jīng)炫酷了很多了询微。

查詢參數(shù)及url路徑

如果是在搜索中用到分頁崖瞭,那么分頁之后的url帶有搜索關(guān)鍵字就更好了,不然點(diǎn)機(jī)第二頁撑毛,不知到搜索的是什么了就很尷尬书聚。我們看一下make的最后一個(gè)參數(shù) option,選項(xiàng)

    /** @var array 一些配置 */
    protected $options = [
        'var_page' => 'page',
        'path'     => '/',
        'query'    => [],
        'fragment' => '',
    ];

這里是一個(gè)數(shù)組藻雌,里面有一個(gè)query字段雌续,也是一個(gè)數(shù)組,那么我們嘗試著使用一下這個(gè)字段看看效果如何蹦疑。修改make方法的參數(shù)

options 參數(shù)中有一個(gè)字段時(shí)path西雀,上面可以看到默認(rèn)值為 / 也就是根目錄,如果我們傳入了這個(gè)值歉摧,就可以設(shè)置分頁后的url了

 $page = Bootstrap::make(null,
            10,
            0,
            $total, 
            false,
          ["query" => ["key" => "game"], 'path' => '/index/index/page']);

我們傳入了query和path這個(gè)字段,看看效果吧


鏈接中帶有關(guān)鍵字和路徑

這個(gè)時(shí)候url里不僅包含了頁碼腔呜,還包含了關(guān)鍵字和路徑叁温,PHP端就能方便的知道下一個(gè)頁面該展示什么了。

make第一個(gè)參數(shù)核畴,數(shù)據(jù)集也是很有用的東西膝但,可以實(shí)現(xiàn)數(shù)據(jù)和分頁通過一個(gè)paginator傳遞到前端頁面,類似于數(shù)據(jù)庫請求那樣谤草。我們講上面的代碼簡單改動跟束,就可以實(shí)現(xiàn)

 public function page()
    {
        //模擬接口請求
        $result = $this->api();
        $total = count($result);
        $page = Bootstrap::make($result,
            10,
            0,
            $total,
            false,
            ["query"=>["key"=>"game"]]);
        //$this->assign("data", $result);
        $this->assign("page", $page);
        return $this->fetch();
    }

這樣的話我們還可以少進(jìn)行一次assign操作。

下面是上面演示用到的代碼

附上后端代碼

<?php

namespace app\index\controller;

use think\Controller;
use think\paginator\driver\Bootstrap;

class Index extends Controller
{

    /**
     * 這套代碼不對數(shù)據(jù)進(jìn)行分頁處理丑孩,只是一個(gè)將已經(jīng)分頁后的數(shù)據(jù)冀宴,套用tp的分頁方法,可以少一個(gè)自己寫分頁
     * 使用是有場景限制的温学,建議是在php請求帶分頁的接口略贮,然后返回?cái)?shù)據(jù)給html時(shí)候使用
     * 直接請求數(shù)據(jù)庫時(shí)tp自帶分頁
     * 前端直接請求接口時(shí)前端可以自行分頁
     * @return mixed
     */
    public function page()
    {
        $page = input('page');
        //模擬接口請求
        //從接口種獲取$page頁的數(shù)據(jù)
        $result = $this->api($page);
        //從接口中獲取總數(shù)據(jù),這里應(yīng)該是個(gè)固定值仗岖,因?yàn)椴樵儣l件不變的話逃延,總數(shù)據(jù)一搬不會變。
        //方便演示直接寫死了轧拄,正常應(yīng)該是從接口中獲取
        $total = 18;
        //進(jìn)行分頁揽祥,這里第二個(gè)參數(shù)是每頁數(shù)據(jù),應(yīng)該和接口中的每頁數(shù)據(jù)相同
        //最后一個(gè)參數(shù)中的path檩电,如果不指定就會從根目錄開始
        $page = Bootstrap::make($result,
            10,
            $page,
            $total,
            false,
            ["query" => ["key" => "game"], 'path' => '/index/index/page']);
        //上面第一個(gè)參數(shù)已經(jīng)帶了數(shù)據(jù)拄丰,所以這個(gè)assign可以取消
        //$this->assign("data", $result);
        $this->assign("page", $page);
        return $this->fetch();
    }

    /**
     * @param $page int 頁碼
     * @return mixed
     * 這里是數(shù)據(jù)模擬府树,正常情況下這里可能是curl訪問數(shù)據(jù)接口。
     * 數(shù)據(jù)分頁獲取在數(shù)據(jù)接口請求數(shù)據(jù)庫時(shí)候操作
     */
    private function api($page)
    {
        $data = [
            "1" => ["最后的生還者", "神秘海域", "塞爾達(dá)傳說", "獵天使魔女", "光環(huán)", "極品飛車", "使命召喚", "最后的守護(hù)者", "戰(zhàn)神", "鬼泣", "仁王"],
            "2" => ["超級馬里奧", "地平線-零之曙光", "怪物獵人", "DOOM", "無冬", "風(fēng)之旅人"]
        ];
        return $data[$page];
    }
}

附上前端頁面代碼

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8"><!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
    <link rel="stylesheet" 
          integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">

    <!-- 可選的 Bootstrap 主題文件(一般不用引入) -->
    <link rel="stylesheet" 
          integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">

    <!-- 最新的 Bootstrap 核心 JavaScript 文件 -->
    <script src="https://cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js"
            integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa"
            crossorigin="anonymous"></script>
    <title>分頁測試</title>
</head>
<body style="border: 25px">
<table class="table-striped table">
    {volist name="page" id="item"}
    <tr>
        <td>{$item}</td>
    </tr>
    {/volist}
</table>
<!---如果顯示的是html代碼愈案,加上raw方法后會正常顯示-->
{$page->render()|raw}
</body>
</html>

附上我自己項(xiàng)目中用到的一個(gè)分頁服務(wù)代碼

<?php

namespace app\common\service;

use think\paginator\driver\Bootstrap;

class PageService
{
    /**
     * 只負(fù)責(zé)生成分頁信息挺尾,不攜帶數(shù)據(jù)
     * @param $total 總數(shù)據(jù)量
     * @param $pageSize 每頁大小
     * @param $page 當(dāng)前頁
     * @param $path 路徑
     * @param array $query ["query"=>["key"=>"game"]]
     * @return mixed
     */
    public function onlyPage($total, $pageSize, $page, $path, $query = [])
    {
        $page = Bootstrap::make([],
            $pageSize,
            $page,
            $total,
            false,
            ["query" => $query,"path"=>$path]);
        return $page;
    }
}

使用分頁工具

//$galley 是接口請求得到的數(shù)據(jù),20是接口中數(shù)據(jù)庫分頁大小站绪,$page是當(dāng)前頁碼
//剩下兩個(gè)參數(shù)分別為路徑和查詢參數(shù)
$pages = (new PageService())->onlyPage($galley['count'],20, $page,
            '/intro/galley/zwgx.html',['galley_cate_id'=>$galley_cate_id]);
        $this->assign("pages", $pages);
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末遭铺,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子恢准,更是在濱河造成了極大的恐慌魂挂,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,273評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件馁筐,死亡現(xiàn)場離奇詭異涂召,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)敏沉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,349評論 3 398
  • 文/潘曉璐 我一進(jìn)店門果正,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人盟迟,你說我怎么就攤上這事秋泳。” “怎么了攒菠?”我有些...
    開封第一講書人閱讀 167,709評論 0 360
  • 文/不壞的土叔 我叫張陵迫皱,是天一觀的道長。 經(jīng)常有香客問我辖众,道長卓起,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,520評論 1 296
  • 正文 為了忘掉前任凹炸,我火速辦了婚禮戏阅,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘还惠。我一直安慰自己饲握,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,515評論 6 397
  • 文/花漫 我一把揭開白布蚕键。 她就那樣靜靜地躺著救欧,像睡著了一般。 火紅的嫁衣襯著肌膚如雪锣光。 梳的紋絲不亂的頭發(fā)上笆怠,一...
    開封第一講書人閱讀 52,158評論 1 308
  • 那天,我揣著相機(jī)與錄音誊爹,去河邊找鬼蹬刷。 笑死瓢捉,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的办成。 我是一名探鬼主播泡态,決...
    沈念sama閱讀 40,755評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼迂卢!你這毒婦竟也來了某弦?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,660評論 0 276
  • 序言:老撾萬榮一對情侶失蹤而克,失蹤者是張志新(化名)和其女友劉穎靶壮,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體员萍,經(jīng)...
    沈念sama閱讀 46,203評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡腾降,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,287評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了碎绎。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片螃壤。...
    茶點(diǎn)故事閱讀 40,427評論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖筋帖,靈堂內(nèi)的尸體忽然破棺而出映穗,到底是詐尸還是另有隱情,我是刑警寧澤幕随,帶...
    沈念sama閱讀 36,122評論 5 349
  • 正文 年R本政府宣布,位于F島的核電站宿接,受9級特大地震影響赘淮,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜睦霎,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,801評論 3 333
  • 文/蒙蒙 一梢卸、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧副女,春花似錦蛤高、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,272評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至沟涨,卻和暖如春恤批,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背裹赴。 一陣腳步聲響...
    開封第一講書人閱讀 33,393評論 1 272
  • 我被黑心中介騙來泰國打工喜庞, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留诀浪,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,808評論 3 376
  • 正文 我出身青樓延都,卻偏偏與公主長得像雷猪,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子晰房,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,440評論 2 359

推薦閱讀更多精彩內(nèi)容

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法求摇,類相關(guān)的語法,內(nèi)部類的語法嫉你,繼承相關(guān)的語法月帝,異常的語法,線程的語...
    子非魚_t_閱讀 31,660評論 18 399
  • 轉(zhuǎn) # https://www.cnblogs.com/easypass/archive/2010/12/ 08/...
    呂品?閱讀 9,737評論 0 44
  • 我們小組走訪的第二個(gè)孩子幽污,是個(gè)準(zhǔn)高三學(xué)生嚷辅,一個(gè)文文靜靜的男孩子,除了微笑距误,除了只有他必須作答的問題簸搞,不多說一句...
    老虎媽閱讀 333評論 0 0
  • 云的心事,風(fēng)知道准潭; 親愛的趁俊,你的呢? 天空刑然, 湛藍(lán)寺擂, 從清晨到中午至午后; 萬里無云泼掠,一絲云彩都沒來過怔软; 幾朵潔白...
    若無閑事閱讀 429評論 0 1
  • 美國建國之初宣揚(yáng)自由平等,追求市場自由择镇,機(jī)會平等挡逼,市場自由與機(jī)會平等相輔相成,效率與平等互相促進(jìn)腻豌。 ...
    meal墨跡閱讀 271評論 0 0