wrathican Posted October 28, 2008 Share Posted October 28, 2008 So, im pretty new to OOP and have read many a tutorial on alot of stuff to do with it. I recently needed a pagination class and decided to write one. I have no idea whether its good/bad/ugly but it works and it didnt take long either. this is the class: <?php ############################################# ############################################# ############# Pagination Class ############## ############################################# ############################################# # Purpose: # To manage the pagination of database query # results. # # Make this generic. Any set of results can # be passed to the class and paginated. # Count the amount of results, divide by # rows to show and boom! Result set would be # a 2 dimensional array so gotta put something # in to make sure everything is ok. # # Two return functions: One to return the pagination # links. Other to return the result set to # show. # # Version 1.0 - First attempt ############################################# class Pagination { # Properties private $server_addr; # Current address in address bar. private $rows_to_show; # Declares the number of database rows to show private $all_records; # Contains all records passed to the class private $total_records; # Contains the number of total records private $current_page; # Sets the number of current page private $max_num_pages; # Contains the maximum number of pages private $row_start; # Sets the row number to start at private $returned_records; # Contains the records that are going to be returned private $paged_links; # Contains the paginated links to display. private $links_first; # Contains the links to be displayed private $links_prev; private $links_sep; private $links_next; private $links_last; private $query_string; private $previous_page; private $next_page; # Parsing function // Function to call all other functions public function paginateResults ($results, $page, $an_array) { $this->setRowsToShow(); $this->storeRecords($results); $this->countResults(); $this->setCurrentPage($page); $this->setMaxPages(); $this->setRowStart(); $this->setReturnedRecords(); $this->setServerAddr(); $this->setLinksFormat($an_array); $this->setPagedLinks(); } // function ###################################################### ################### SETTER METHODS ################### ###################################################### # Sets the number of rows to show // This function uses a constant defined in class.conf.php private function setRowsToShow () { $this->rows_to_show = ROWS_TO_SHOW; } // function # Store all the records private function storeRecords ($results) { $this->all_records = $results; } // function # Count number of rows private function countResults () { $this->total_records = count($this->all_records); } // function # Set current page private function setCurrentPage ($page) { if($page == '') { $this->current_page = 1; }else{ $this->current_page = $page; } } // function # Set max number of pages private function setMaxPages () { $this->max_num_pages = ceil($this->total_records / $this->rows_to_show); } // function # Set row_start private function setRowStart() { // do some math! noooooooooo! if($this->current_page < 1) { $this->row_start = 0; }elseif($this->current_page > $this->max_num_pages) { $this->row_start = $this->max_num_pages * $this->rows_to_show - $this->rows_to_show; }else{ $this->row_start = $this->current_page * $this->rows_to_show - $this->rows_to_show; } // if } // function # Check page is within scope private function checkPage () { // count results divide them up etc... // don't know if i really need this function... } // function # Set returned records private function setReturnedRecords() { // splice the array $this->returned_records = array_slice($this->all_records, $this->row_start, $this->rows_to_show, true); } // function # Sets the next, prev, first, last and seperator private function setLinksFormat ($an_array) { // $an_array will always be an array // [0] = first // [1] = prev // [2] = seperator // [3] = next // [4] = last $this->links_first = $an_array[0]; $this->links_prev = $an_array[1]; $this->links_sep = $an_array[2]; $this->links_next = $an_array[3]; $this->links_last = $an_array[4]; } // function # Sets the page and query string. E.g - /index.php?p=1&d=2 private function setServerAddr () { $this->query_string = $_SERVER['QUERY_STRING']; $this->server_addr = basename($_SERVER['SCRIPT_FILENAME']) . '?'; // do some cleaning of the query string to remove the page variable. //split the QS into different sections $this->query_string_array = explode("&", $this->query_string); // '/(.*)page=[0-9]*/i' Match the page pattern $this->server_addr .= preg_replace('/&page=[0-9]*/i', '', $this->query_string); // encode ampersands $this->server_addr = preg_replace('/&/', '&', $this->server_addr); } # Sets the links that are displayed on a page. private function setPagedLinks () { $this->paged_links = ''; // First/Prev if($this->current_page > 1) { // First Link $this->paged_links .= '<a href="'.$this->server_addr . '&page=1">' . $this->links_first .'</a> '; // Previous Link if($this->current_page - 1 < 1) { $this->previous_page = 1; }else{ $this->previous_page = $this->current_page - 1; } $this->paged_links .= '<a href="'.$this->server_addr . '&page=' . $this->previous_page . '">' . $this->links_prev .'</a> '; }else{ $this->paged_links .= $this->links_first . ' ' . $this->links_prev . ' '; } // page links for($i = $this->current_page - 3; $i < $this->current_page + 3; $i++) { if($i == $this->current_page) { $this->paged_links .= '- Page ' . $i . ' of ' . $this->max_num_pages . ' - '; }elseif (($i < 1) || ($i > $this->max_num_pages)) { $this->paged_links .= ''; }elseif ($i == $this->max_num_pages){ $this->paged_links .= '<a href="' . $this->server_addr . '&page=' . $i . '">' . $i .'</a> '; }else{ $this->paged_links .= '<a href="' . $this->server_addr . '&page=' . $i . '">' . $i .'</a> '; } } // Next/Last if($this->current_page < $this->max_num_pages) { // Next link if($this->current_page + 1 > $this->max_num_pages) { $this->next_page = $this->max_num_pages; }else{ $this->next_page = $this->current_page + 1; } $this->paged_links .= '<a href="'.$this->server_addr . '&page=' . $this->next_page . '">' . $this->links_next .'</a> '; // Last link $this->paged_links .= '<a href="'.$this->server_addr . '&page=' . $this->max_num_pages . '">' . $this->links_last .'</a>'; }else{ $this->paged_links .= $this->links_next . ' ' . $this->links_last; } } // function ###################################################### ################### GETTER METHODS ################### ###################################################### # returns the paged records public function getReturnedRecords () { return $this->returned_records; } // function #returns the paged links public function getPagedLinks () { return $this->paged_links; } // function } ?> presume database connection is made and includes are already included (couldnt be bothered writing it in) and it would be used something like this: <?php define('ROWS_TO_SHOW', '10'); $link_format = array('<<First', '<Prev', '|', 'Next>', 'Last>>'); $query = "select * from table"; $result mysql_query($query); $all_files = mysql_fetch_assoc($result) $r->paginateResults($all_files, $_GET['page'], $link_format); $trunc_files = $r->getReturnedRecords(); for($i=0; $i < count($trunc_files); $i++) { //display the truncated rsults } echo $r->getPagedLinks(); ?> if it sucks, i would really appreciate knowing why, and your suggestions for making it better. Thanking all who look kindly, Wrathican Quote Link to comment Share on other sites More sharing options...
Mastodont Posted October 29, 2008 Share Posted October 29, 2008 Personally, I can't stand methods with one executable line and called only once (crumbled code). Your method setRowsToShow is IMHO also unneeded, because you can directly use constant ROWS_TO_SHOW. Otherwise it looks good, although I am surprised to see URL composed only from server_addr and page_number. (Where is component_name or subject_name or st. of that kind?) Quote Link to comment Share on other sites More sharing options...
Daniel0 Posted October 29, 2008 Share Posted October 29, 2008 I don't like the way you handle configuration data. You're better off using a setter function which you already have. Just give it an argument and set it instead of relying on external data. Quote Link to comment Share on other sites More sharing options...
wrathican Posted October 30, 2008 Author Share Posted October 30, 2008 The reason i define the ROWS_TO_SHOW is because i use this class on many pages and i needed a way of being able to set that data globally, rather than in every instance. The reason i set $rows_to_show using a method is because i like to have all the class properties stored inside the class rather than using external data for any calculation. Mastodont: I dont get what you mean by this: (Where is component_name or subject_name or st. of that kind?) also, Which methods are you referring to? I can't stand methods with one executable line and called only once (crumbled code) Thanks for you feed back! Quote Link to comment Share on other sites More sharing options...
Daniel0 Posted October 30, 2008 Share Posted October 30, 2008 The reason i define the ROWS_TO_SHOW is because i use this class on many pages and i needed a way of being able to set that data globally, rather than in every instance. It's still incredibly bad practice. You could have something like a static method Pagination::setDefaultConfig() which will take default configuration using an associative array. You can then set it in the constructor. You'll then still have the regular setter methods for custom configuration data. Quote Link to comment Share on other sites More sharing options...
wrathican Posted October 30, 2008 Author Share Posted October 30, 2008 that's a good point. I never thought of it like that. so add a contructor method like so: <?php //inside of class private function __contruct($array) { $this->rows_to_show = $array['rows']; $this->links_first = $array['first']; } //on instanciation $array = ('rows' => 10, 'first' => '<<First'); $p = new Pagination($array); ?> or am i missing the point? Thanks for the advice Quote Link to comment Share on other sites More sharing options...
Daniel0 Posted October 30, 2008 Share Posted October 30, 2008 You could do that, but I was thinking of something more like this: class Pagination { static private $defaultConfig = array(); private $config = array(); public function __construct() { $this->config = self::$defaultConfig; } static public function setDefaultConfig(array $config) { self::$defaultConfig = $config; } public function setConfig(array $config) { foreach ($config as $key => $value) { $this->config[$key] = $value; } return $this; } public function getConfig($key = null) { if (!is_null($key) && isset($this->config[$key])) { return $this->config[$key]; } return $this->config; } // etc. } Pagination::setDefaultConfig(array('foo' => 'bar', 'Daniel' => 'cool')); $paginationOne = new Pagination(); // this one has the default config $paginationTwo = new Pagination(); // so does this one... for now... $pagination->setConfig(array('foo' => '123')); // ... but we changed a bit here So you have a default setter and a specific setter and getter for the configuration data. Quote Link to comment Share on other sites More sharing options...
wrathican Posted October 30, 2008 Author Share Posted October 30, 2008 Ahh that makes alot of sense. Thanks so much for your advice. here is the amended class: <?php ############################################# ############################################# ############# Pagination Class ############## ############################################# ############################################# # Purpose: # To manage the pagination of database query # results. # # Make this generic. Any set of results can # be passed to the class and paginated. # Count the amount of results, divide by # rows to show and boom! Result set would be # a 2 dimensional array so gotta put something # in to make sure everything is ok. # Two functions: One to return the pagination # links. Other to return the result set to # show. # # Version 1.0 - First attempt ############################################# class Pagination { # Config properties static private $defaultConfig = array(); private $config = array(); # Properties private $server_addr; # Current address in address bar. private $all_records; # Contains all records passed to the class private $total_records; # Contains the number of total records private $current_page; # Sets the number of current page private $max_num_pages; # Contains the maximum number of pages private $row_start; # Sets the row number to start at private $returned_records; # Contains the records that are going to be returned private $paged_links; # Contains the paginated links to display. private $query_string; private $previous_page; private $next_page; # Configuration functions public function __construct(){ $this->config = self::$defaultConfig; } static public function setDefaultConfig(array $config){ self::$defaultConfig = $config; } public function setConfig(array $config){ foreach ($config as $key => $value) { $this->config[$key] = $value; } return $this; } public function getConfig($key = null){ if (!is_null($key) && isset($this->config[$key])) { return $this->config[$key]; } return $this->config; } # Parsing function // Function to call all other functions public function paginateResults ($results, $page, $an_array) { $this->storeRecords($results); $this->countResults(); $this->setCurrentPage($page); $this->setMaxPages(); $this->setRowStart(); $this->setReturnedRecords(); $this->setServerAddr(); $this->setPagedLinks(); } // function ###################################################### ################### SETTER METHODS ################### ###################################################### # Store all the records private function storeRecords ($results) { $this->all_records = $results; } // function # Count number of rows private function countResults () { $this->total_records = count($this->all_records); } // function # Set current page private function setCurrentPage ($page) { if($page == '') { $this->current_page = 1; }else{ $this->current_page = $page; } } // function # Set max number of pages private function setMaxPages () { $this->max_num_pages = ceil($this->total_records / $this->config['rows']); } // function # Set row_start private function setRowStart() { // do some math! noooooooooo! if($this->current_page < 1) { $this->row_start = 0; }elseif($this->current_page > $this->max_num_pages) { $this->row_start = $this->max_num_pages * $this->config['rows'] - $this->config['rows']; }else{ $this->row_start = $this->current_page * $this->config['rows'] - $this->config['rows']; } // if } // function # Set returned records private function setReturnedRecords() { // splice the array $this->returned_records = array_slice($this->all_records, $this->row_start, $this->config['rows'], true); } // function # Sets the page and query string. E.g - /index.php?p=1&d=2 private function setServerAddr () { $this->query_string = $_SERVER['QUERY_STRING']; $this->server_addr = basename($_SERVER['SCRIPT_FILENAME']) . '?'; // do some cleaning of the query string to remove the page variable. //split the QS into different sections $this->query_string_array = explode("&", $this->query_string); // '/(.*)page=[0-9]*/i' Match the page pattern $this->server_addr .= preg_replace('/&page=[0-9]*/i', '', $this->query_string); // encode ampersands $this->server_addr = preg_replace('/&/', '&', $this->server_addr); } # Sets the links that are displayed on a page. private function setPagedLinks () { $this->paged_links = ''; // First/Prev if($this->current_page > 1) { // First Link $this->paged_links .= '<a href="'.$this->server_addr . '&page=1">' . $this->config['first'] .'</a> '; // Previous Link if($this->current_page - 1 < 1) { $this->previous_page = 1; }else{ $this->previous_page = $this->current_page - 1; } $this->paged_links .= '<a href="'.$this->server_addr . '&page=' . $this->previous_page . '">' . $this->config['prev'] .'</a> '; }else{ $this->paged_links .= $this->config['first'] . ' ' . $this->config['prev'] . ' '; } // page links for($i = $this->current_page - 3; $i < $this->current_page + 3; $i++) { if($i == $this->current_page) { $this->paged_links .= $i; }elseif (($i < 1) || ($i > $this->max_num_pages)) { $this->paged_links .= ''; }elseif($i < $this->current_page){ $this->paged_links .= '<a href="' . $this->server_addr . '&page=' . $i . '">' . $i .'</a>' . $this->config['sep']; }elseif($i > $this->current_page){ $this->paged_links .= $this->config['sep'] . '<a href="' . $this->server_addr . '&page=' . $i . '">' . $i .'</a>'; } } // Next/Last if($this->current_page < $this->max_num_pages) { // Next link if($this->current_page + 1 > $this->max_num_pages) { $this->next_page = $this->max_num_pages; }else{ $this->next_page = $this->current_page + 1; } $this->paged_links .= ' <a href="'.$this->server_addr . '&page=' . $this->next_page . '">' . $this->config['next'] .'</a> '; // Last link $this->paged_links .= ' <a href="'.$this->server_addr . '&page=' . $this->max_num_pages . '">' . $this->config['last'] .'</a>'; }else{ $this->paged_links .= ' ' .$this->config['next'] . ' ' . $this->config['last']; } } // function ###################################################### ################### GETTER METHODS ################### ###################################################### # returns the paged records public function getReturnedRecords () { return $this->returned_records; } // function #returns the paged links public function getPagedLinks () { return $this->paged_links; } // function } ?> Anything more i should do to make it better? Thanks a lot Wrathican Quote Link to comment Share on other sites More sharing options...
Daniel0 Posted October 30, 2008 Share Posted October 30, 2008 One final addition could be the usage of fluent interfaces for methods that do not return a value so you'll be able to do something like this: $obj = new Foo(); $foo->doSomething() ->doSomethingElse(); It just looks nicer. You'll make a method able to do this by returning $this. It's just a nice little addition, but in no way required. It saves you from typing the name of the variable each time if you need the object to perform a lot of operations after each other and neither of those return any value. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.