20
Advanced Usage of Zend_Paginator The Dutch PHP BBQ 2009 Jurriën Stutterheim

2009-08-28 PHP Benelux BBQ: Advanced Usage Of Zend Paginator

Embed Size (px)

Citation preview

Page 1: 2009-08-28 PHP Benelux BBQ: Advanced Usage Of Zend Paginator

Advanced Usage of Zend_Paginator

The Dutch PHP BBQ 2009Jurriën Stutterheim

Page 2: 2009-08-28 PHP Benelux BBQ: Advanced Usage Of Zend Paginator

About Me

• ZF user since ZF 0.2

• ZF contributor since 2007

• Author and co-author of Zend_Paginator and Zend_Feed_Reader

Page 3: 2009-08-28 PHP Benelux BBQ: Advanced Usage Of Zend Paginator

This Presentation

• Short Introduction to Zend_Paginator

• Zend_Paginator & Relational Databases

• Zend_Paginator & Domain Models

• Alternative use-cases

Page 4: 2009-08-28 PHP Benelux BBQ: Advanced Usage Of Zend Paginator

“Zend_Paginator is a flexible component for paginating collections of data and presenting that data to users.”- Zend Framework Reference Guide

Short Introduction

Page 5: 2009-08-28 PHP Benelux BBQ: Advanced Usage Of Zend Paginator

Primary Design Goals

• Paginate arbitrary data, not just relational databases

• Fetch only the results that need to be displayed

• Do not force users to adhere to only one way of displaying data or rendering pagination controls

• Loosely couple Zend_Paginator to other Zend Framework components so that users who wish to use it independently of Zend_View, Zend_Db, etc. can do so

- Zend Framework Reference Guide

Page 6: 2009-08-28 PHP Benelux BBQ: Advanced Usage Of Zend Paginator

Simple Example// Create a Paginator that will paginate an// array with the values 1 to 100$paginator = new Zend_Paginator( new Zend_Paginator_Adapter_Array(range(1, 100)));$paginator->setItemCountPerPage(10);$paginator->setCurrentPageNumber(2);// Echoes numbers 21 to 30foreach ($paginator as $item) {

echo $item;}// This assumes the view helper has been setupecho $paginator

Page 7: 2009-08-28 PHP Benelux BBQ: Advanced Usage Of Zend Paginator

Available Adapters

Out of the box Zend_Paginator supports:

• arrays

• Iterators

• Zend_Db_Select

• Zend_Db_Table_Select

Page 8: 2009-08-28 PHP Benelux BBQ: Advanced Usage Of Zend Paginator

Paginator & Database

• The total number of items is needed to calculate the number of pages

• A count-query is executed to determine the total number of items the original query would retrieve

• Paginator only fetches the rows for the current page

Page 9: 2009-08-28 PHP Benelux BBQ: Advanced Usage Of Zend Paginator

The Count Query

The COUNT query forSELECT * FROM huge_table

isSELECT COUNT(1) AS zend_paginator_row_count FROM huge_table

In order to fetch the rows for the current page:SELECT * FROM huge_table LIMIT 20, 10

Page 10: 2009-08-28 PHP Benelux BBQ: Advanced Usage Of Zend Paginator

Complex QueriesIn case of more complex queries, subqueries are used instead. Original query:SELECT *, MAX(rating) AS highest_rating FROM publicationsWHERE publication_year > 2006GROUP BY category, publication_year, authorHAVING highest_rating > 3

Count query:SELECT COUNT(1) AS zend_paginator_row_count FROM ( SELECT *, MAX(rating) AS highest_rating FROM publications WHERE publication_year > 2006 GROUP BY category, publication_year, author HAVING highest_rating > 3)

Page 11: 2009-08-28 PHP Benelux BBQ: Advanced Usage Of Zend Paginator

Custom Queries

It’s also possible to use a custom COUNT query:// $select contains the query from the last example$adapter = new Zend_Paginator_Adapter_DbTableSelect($select);$adapter->setRowCount( $db->select()->from('publication_counts', array( Zend_Paginator_Adapter_DbSelect::ROW_COUNT_COLUMN => 'highest_rating_count' )));$paginator = new Zend_Paginator($adapter);

Page 12: 2009-08-28 PHP Benelux BBQ: Advanced Usage Of Zend Paginator

Fixed Page Count

You can specify a fixed page count. No COUNT query is executed in this case:// This table has tens of thousands of records$table = new Zend_Db_Table('publications');$select = $table->select()->order('rating DESC');$adapter = new Zend_Paginator_Adapter_DbTableSelect($select);$adapter->setRowCount(500);$paginator = new Zend_Paginator($adapter);

Page 13: 2009-08-28 PHP Benelux BBQ: Advanced Usage Of Zend Paginator

Paginator & Domain Models

• When using a domain model you don’t want to pass database rows to your view, but rather use them to construct domain objects.

• You do however wish to keep the Paginator features at your disposal.

• Zend_Paginator supports this using filters.

Page 14: 2009-08-28 PHP Benelux BBQ: Advanced Usage Of Zend Paginator

Filters

• Filter the result from the adapter

• Need to implement Zend_Filter_Interface

• Can be chained if required

• Zend_Filter_Callback allows you to easily reuse existing models to construct domain objects

Page 15: 2009-08-28 PHP Benelux BBQ: Advanced Usage Of Zend Paginator

Exampleclass MyObject { // Snip... public static function factory($rows) { $objects = array(); foreach ($rows as $row) { $objects[] = new MyObject($row); } return $objects; } public function getFoo() { return 'foo'; }}// $select is a Zend_Db_Table_Select object$paginator = new Zend_Paginator( new Zend_Paginator_Adapter_DbTableSelect($select));$paginator->setFilter(new Zend_Filter_Callback( array('MyObject', 'factory')));foreach ($paginator as $item) { echo $item->getFoo(); // echoes foo}

Page 16: 2009-08-28 PHP Benelux BBQ: Advanced Usage Of Zend Paginator

Alternative Use-cases

• Batch Processing

• Zend_Entity

Page 17: 2009-08-28 PHP Benelux BBQ: Advanced Usage Of Zend Paginator

Batch Processing

• For example, rebuilding a Zend_Search_Lucene search index using a large amount data from a database

• Each page contains a relatively large number of items

• Main advantage is limited memory usage because not all rows are loaded into memory at once

Page 18: 2009-08-28 PHP Benelux BBQ: Advanced Usage Of Zend Paginator

Batch Examplepublic function rebuild(){ $paginator = new Zend_Paginator( new Zend_Paginator_Adapter_DbTableSelect($this->getSelect()) ); $paginator->setCacheEnabled(false); // Batch size is 500 records per page/batch $paginator->setItemCountPerPage(500);

$searchIndex = $this->getSearchIndex();

for ($i = 1; $i <= $paginator->count(); $i++) { $items = $paginator->getItemsByPage($i); foreach ($items as $item) { $searchIndex->addPublication($item); } }}

Page 19: 2009-08-28 PHP Benelux BBQ: Advanced Usage Of Zend Paginator

Zend_Entity

• Is a data mapper implementation for ZF

• Currently under heavy development

• Uses Zend_Paginator_AdapterAggregate

• Is used to load subsets of data from the datasource to improve performance and memory consumption

Page 20: 2009-08-28 PHP Benelux BBQ: Advanced Usage Of Zend Paginator

Finished!

foreach ($questions as $question) {

$question->answer();

}

$this->bbq(); // \o/