首先,我們還是準備好測試資料。
$data = [ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', ]; // $p = $_GET['p']; $p = 2; $currentPage = $p c4b0d4fdcfca79a44e60304665677797 // string(1) "D" // [1]=> // string(1) "E" // [2]=> // string(1) "F" // }
array_slice() 函數需要三個參數,第二個參數就是偏移量,第三個參數是查詢幾個資料。其中,第三個參數是可選的,不填的話就會把目前設定的偏移量之後的資料全部顯示出來。是不是跟我們的 MySQL 查詢語句一模一樣。沒錯,他們本身就是類似的操作。
array_chunk
array_chunk() 函數則是根據一個數值參數將一個陣列分組,也就是將陣列分割成一段一段的子陣列。我們就可以根據分割後的陣列來取得指定下標的子數組內容,這些內容就是目前的頁面需要展示的資料了。
$pages = array_chunk($data, $pageSize); var_dump($pages); // array(4) { // [0]=> // array(3) { // [0]=> // string(1) "A" // [1]=> // string(1) "B" // [2]=> // string(1) "C" // } // [1]=> // array(3) { // [0]=> // string(1) "D" // [1]=> // string(1) "E" // [2]=> // string(1) "F" // } // [2]=> // array(3) { // [0]=> // string(1) "G" // [1]=> // string(1) "H" // [2]=> // string(1) "I" // } // [3]=> // array(2) { // [0]=> // string(1) "J" // [1]=> // string(1) "K" // } // } var_dump($pages[$currentPage]); // array(3) { // [0]=> // string(1) "A" // [1]=> // string(1) "B" // [2]=> // string(1) "C" // }
這段程式碼我們輸出了分割後的陣列內容,然後需要的是第二頁也就是下標為1 的數據,直接透過分割後的陣列就可以方便地取得到所需要的內容了。使用這個函數來做數組分頁的功能非常地簡單直觀,而且它不需要去計算偏移量,直接就是使用當前頁$currentPage 和$pageSize 就可以完成對於數據的分組了,非常推薦大家使用這個函數來進行類似的操作。
LimitIterator
最後我們要學習到的是使用一個迭代器類來實現數組分頁的能力,這個使用的就比較少了,估計都沒什麼人知道,但其實LimitIterator 類在PHP5.1 時就已經提供了。它的作用是允許遍歷一個 Iterator 的限定子集的元素。也就是說,如果我們的程式碼中使用了迭代器模式,實作了迭代器接口,那麼這些迭代器類別都可以使用這個類別進行分頁操作。
foreach (new LimitIterator(new ArrayIterator($data), $offset, $pageSize) as $d) { var_dump($d); } // string(1) "D" // string(1) "E" // string(1) "F"
它需要的實例化構造參數包含3個,第一個是一個迭代器對象,由於數組不是迭代器對象,所以我們使用ArrayIterator 實例將我們的數組資料轉換為一個迭代器對象。後面兩個參數就是偏移量和資料數量了,這個和 array_slice() 函數是類似的,不過不同的是,它的偏移量參數也是可以選的。如果我們不給後面的可選參數的話,那麼它將遍歷所有的資料。
foreach (new LimitIterator(new ArrayIterator($data)) as $d) { var_dump($d); } // string(1) "A" // string(1) "B" // string(1) "C" // string(1) "D" // string(1) "E" // string(1) "F" // string(1) "G" // string(1) "H" // string(1) "I" // string(1) "J" // string(1) "K"
參數錯誤時的表現
接下來,我們看看如果參數錯誤,也就是偏移量或所需的資料量大小有問題的話,這些運算會會有什麼樣的表現。
var_dump(array_slice($data, $offset, 150)); // array(8) { // [0]=> // string(1) "D" // [1]=> // string(1) "E" // [2]=> // string(1) "F" // [3]=> // string(1) "G" // [4]=> // string(1) "H" // [5]=> // string(1) "I" // [6]=> // string(1) "J" // [7]=> // string(1) "K" // } var_dump(array_slice($data, 15, $pageSize)); // array(0) { // }
array_slice() 函數對於偏移錯誤的相容就是展示一個空的陣列。而資料量超標的話則會顯示所有偏移量之後的資料。
var_dump($pages[15]); // NULL
array_chunk() 對於下標不存在的資料當然就是回傳一個 NULL 值啦。
foreach (new LimitIterator(new ArrayIterator($data), $offset, 150) as $d) { var_dump($d); } // string(1) "D" // string(1) "E" // string(1) "F" // string(1) "G" // string(1) "H" // string(1) "I" // string(1) "J" // string(1) "K" foreach (new LimitIterator(new ArrayIterator($data), 15, $pageSize) as $d) { var_dump($d); } // Fatal error: Uncaught OutOfBoundsException: Seek position 15 is out of range
LimitIterator 則是對於偏移量錯誤的資料直接回傳錯誤異常訊息了。這也是類模式處理的好處,有錯誤都會以異常的形式進行返回,方便我們對異常進行後續的處理。
其它的測試大家還可以自行偵測,例如偏移量是 0 或是負數的情況,資料量是 0 或是負數的情況。這些我就不多寫了,大家可以根據已有的知識先猜想一下結果會是什麼樣的,然後再自己寫程式碼驗證一下結果是符合自己的預期,這樣學習的效果會非常棒哦! (在下方測試程式碼連結有測試,結果裡面是有坑的哦)
总结
一个功能使用了三种方式来实现,这就是代码的魅力。至于哪个好哪个坏我们不多做评价,一切都是以业务为核心来进行选取。类似的功能虽说并不常见,但很多项目里都会遇到,比如说后台用户组管理就会非常常见,一般来说后台用户分组如果不是特别大型的 ERP 项目都不会很多,但有时候也会达到需要分页的程度,这时候,我们就可以考虑考虑使用今天所学的知识来做咯!
测试代码:
https://github.com/zhangyue0503/dev-blog/blob/master/php/202008/source/PHP%E4%B8%AD%E7%9A%84%E6%95%B0%E7%BB%84%E5%88%86%E9%A1%B5%E5%AE%9E%E7%8E%B0%EF%BC%88%E9%9D%9E%E6%95%B0%E6%8D%AE%E5%BA%93%EF%BC%89.php
参考文档:
https://www.php.net/manual/zh/function.array-slice.php https://www.php.net/manual/zh/function.array-chunk.php https://www.php.net/limititerator
推荐学习:《PHP视频教程》