Building Example Pager Class
Moderator: General Moderators
- Christopher
- Site Administrator
- Posts: 13596
- Joined: Wed Aug 25, 2004 7:54 pm
- Location: New York, NY, US
Building Example Pager Class
In this thread (viewtopic.php?t=43622) was a discussion Pagers (one of the comon questions around here). I found a few that are regularly referenced here and commented on them. There may be others around as well. I have one as well but it is too complex to use as an example. I had suggested that we build a fairly simple, solid, "better practices" example that we can refer people to when they ask Pager questions.
I think I can summarize my thoughts in just a few points:
- Build a class something like jcart's pagination class.
- Allow for multiple formatters such as jspro2's create_pagination()
- Make it database independent
- Probably it will end up as a couple of classes
So I am wondering if others are interested, especially jspro2 and jcart whose code could be used as a base. We could do the design/coding session right in this thread so people could see the process. Anyone interested?
I think I can summarize my thoughts in just a few points:
- Build a class something like jcart's pagination class.
- Allow for multiple formatters such as jspro2's create_pagination()
- Make it database independent
- Probably it will end up as a couple of classes
So I am wondering if others are interested, especially jspro2 and jcart whose code could be used as a base. We could do the design/coding session right in this thread so people could see the process. Anyone interested?
(#10850)
- feyd
- Neighborhood Spidermoddy
- Posts: 31559
- Joined: Mon Mar 29, 2004 3:24 pm
- Location: Bothell, Washington, USA
I think it's definitely a worthy excersize, and would allow newcomers to get a feel for TDD among other concepts. Although we may need/want to have a separate thread that does explanations, but maybe not, maybe we coudl do them here.
As some may know, the Revival Corp may get a build of MediaWiki up very soon as a ~new version of what PHPComplete was originally, a site where newcomers to php can not only learn the basics, but become more aware of all the fun issues we often deal with. So the explanations, along with the thought processes could also be translated there once we get rolling here. Just something to keep in mind.
As some may know, the Revival Corp may get a build of MediaWiki up very soon as a ~new version of what PHPComplete was originally, a site where newcomers to php can not only learn the basics, but become more aware of all the fun issues we often deal with. So the explanations, along with the thought processes could also be translated there once we get rolling here. Just something to keep in mind.
- Christopher
- Site Administrator
- Posts: 13596
- Joined: Wed Aug 25, 2004 7:54 pm
- Location: New York, NY, US
I agree, though as there seem to be few TDDers here I though we could just design it stepwise without the tests to show the issues and thought-processes behind each step of the design. I think that's what helps most.feyd wrote:I think it's definitely a worthy excersize, and would allow newcomers to get a feel for TDD among other concepts. Although we may need/want to have a separate thread that does explanations, but maybe not, maybe we coudl do them here.
I was hoping for a small group of coders like you, jspro2 or jcart to go through the process with. If there is no one else interested, maybe you can "mentor" / "peer-review" me through the process.
Sounds cool.feyd wrote:As some may know, the Revival Corp may get a build of MediaWiki up very soon as a ~new version of what PHPComplete was originally, a site where newcomers to php can not only learn the basics, but become more aware of all the fun issues we often deal with. So the explanations, along with the thought processes could also be translated there once we get rolling here. Just something to keep in mind.
(#10850)
- Christopher
- Site Administrator
- Posts: 13596
- Joined: Wed Aug 25, 2004 7:54 pm
- Location: New York, NY, US
Hey feyd, it seems there were not takers for this so are you interesting in proceeding? If so we can either just jump in and go back and forth, or do it pair programing style where we take roles of the the driver and observer (switching occasionally if you like). Either way we could start with a statement something like this:
"Implement a PHP class or classes that allow arrays and DB records to be displayed paged in various ways on website. It should be as flexible as possible while meeting the goal that code is simple enough for newbies to use, understand and learn from. "
"Implement a PHP class or classes that allow arrays and DB records to be displayed paged in various ways on website. It should be as flexible as possible while meeting the goal that code is simple enough for newbies to use, understand and learn from. "
(#10850)
- John Cartwright
- Site Admin
- Posts: 11470
- Joined: Tue Dec 23, 2003 2:10 am
- Location: Toronto
- Contact:
- feyd
- Neighborhood Spidermoddy
- Posts: 31559
- Joined: Mon Mar 29, 2004 3:24 pm
- Location: Bothell, Washington, USA
I'm definitely in. Maybe we should wait a little bit for us to firm up about the Wiki so we can do the whole thing there? We still need to figure out integration with the user tables and junk.. so it may be worthwhile to just start it here for now. Since I'm not the best at object oriented stuffs, I may take a bit of a backseat, letting you guys run wild while I inject possible questions and explainations about things at various points that may be confusing the newcomers.
- Christopher
- Site Administrator
- Posts: 13596
- Joined: Wed Aug 25, 2004 7:54 pm
- Location: New York, NY, US
Great. I think starting here and having at least one pass through the design would be good. This forum will be more interactive than a wiki and we can write a cleaned-up narrative of this converstation for the wiki if we come up with something worthwhile.feyd wrote:I'm definitely in. Maybe we should wait a little bit for us to firm up about the Wiki so we can do the whole thing there? We still need to figure out integration with the user tables and junk.. so it may be worthwhile to just start it here for now. Since I'm not the best at object oriented stuffs, I may take a bit of a backseat, letting you guys run wild while I inject possible questions and explainations about things at various points that may be confusing the newcomers.
It is also quite possible that when we have gone through once we will not be compeletly happy with the result so another pass (all of us being smarter then) may be needed. Or we may find that we need two separate pagers: a really simple pager and a fully functional pager, because we can't meet all of our requirements with one. Who know at this point.
Since Jcart is in maybe we can get going. As I recall with pair programming, they say that three programmers one two computers is a better "pair" it ends up, plus three can vote on features easier.
(#10850)
- Christopher
- Site Administrator
- Posts: 13596
- Joined: Wed Aug 25, 2004 7:54 pm
- Location: New York, NY, US
Excellent. I'm glad you found it.Jcart wrote:Hey arborint,
I hadn't come across this thead until now, but I am definantly interested.
I am busy as well, but I think we can take our time and see how it goes.Jcart wrote:I am a bit busy with other stuff at the moment, so if your not in a rush to produce anything quality then count me in
One question I have since you are involved is whether we should refactor your class or start from scratch? I would favor starting from scratch for a couple of reasons, the main one being that your class is very nice and makes a reasonable set of design tradeoffs -- so I think it stands on its own as a good solution. If we build something with a slightly different spin, then there will be two classes around that people can choose from.
Part of it depends on whether you and feyd agree with my proposal to create clearer dependencies by separating, for example, the database query, request processor/values calculator, and the HTML outputter(s). So what are your thoughts?
(#10850)
- John Cartwright
- Site Admin
- Posts: 11470
- Joined: Tue Dec 23, 2003 2:10 am
- Location: Toronto
- Contact:
Yes I would definantly start from scratch for a couple reasons.
1) That class I wrote was basically a quick solution, and was specifically designed with my needs in mind. I would prefer to use a better example of OOP principles.
2) There could be better seperation of the layers, as you mentioned.
3) It would be educational for everyone else as to why we make certain decisions.
I really like the idea of creating two working examples on how to approach this problem.. so we can really focus on OOP programming, and not specifically what the program is. So in one version, we could create a class much like the one I did -- improved mind you -- that tackles all of the task in one class.. we all know this is generally not good OOP programming, but it gets the job done. Then, in our next version focus much more on seperation of design pattern.
1) That class I wrote was basically a quick solution, and was specifically designed with my needs in mind. I would prefer to use a better example of OOP principles.
2) There could be better seperation of the layers, as you mentioned.
3) It would be educational for everyone else as to why we make certain decisions.
I really like the idea of creating two working examples on how to approach this problem.. so we can really focus on OOP programming, and not specifically what the program is. So in one version, we could create a class much like the one I did -- improved mind you -- that tackles all of the task in one class.. we all know this is generally not good OOP programming, but it gets the job done. Then, in our next version focus much more on seperation of design pattern.
- Christopher
- Site Administrator
- Posts: 13596
- Joined: Wed Aug 25, 2004 7:54 pm
- Location: New York, NY, US
Great. It sounds like we are starting out in the same page.Jcart wrote:Yes I would definantly start from scratch for a couple reasons.
1) That class I wrote was basically a quick solution, and was specifically designed with my needs in mind. I would prefer to use a better example of OOP principles.
2) There could be better seperation of the layers, as you mentioned.
3) It would be educational for everyone else as to why we make certain decisions.
I agree. I think a single, simple class that just does the basic Use Cases well and makes it easy for a newbie to get the thing running is in the spirit of PHP.Jcart wrote:I really like the idea of creating two working examples on how to approach this problem.. so we can really focus on OOP programming, and not specifically what the program is. So in one version, we could create a class much like the one I did -- improved mind you -- that tackles all of the task in one class.. we all know this is generally not good OOP programming, but it gets the job done. Then, in our next version focus much more on seperation of design pattern.
I would actually suggest that we build it full OO first and then combine into a single class once we have a fuller understanding of the implementation. The full OO version is going to be clearer design-wise. So which way is it? Feyd? Our first vote?
(#10850)
- feyd
- Neighborhood Spidermoddy
- Posts: 31559
- Joined: Mon Mar 29, 2004 3:24 pm
- Location: Bothell, Washington, USA
I like both ideas, however going the full OO way, seem sot make more sense. We'll refactor and refactor as we go along, so things will solidify in the end. Some UML diagrams may be helpful. Maybe a crash course in UML would be a good side bit. hmm... so many things to add onto the list of things or the Wiki 
- Christopher
- Site Administrator
- Posts: 13596
- Joined: Wed Aug 25, 2004 7:54 pm
- Location: New York, NY, US
Well, in true Agile fashion if we don't have a certainity we will kick that decision down the road a little.feyd wrote:I like both ideas, however going the full OO way, seem sot make more sense. We'll refactor and refactor as we go along, so things will solidify in the end.
So Feyd had added doing UML diagrams AND adding UML support to the Wiki to his apparently empty plate!feyd wrote:Some UML diagrams may be helpful. Maybe a crash course in UML would be a good side bit. hmm... so many things to add onto the list of things or the Wiki
OK ... Lets get started. Here are some parts and some rambling thoughts:
1. Get Request parameters. This is pretty simple, but I think we could improve over many designs by not hard coding the paramter name.
2. Deal with data records. Feyd said that the system he uses can page any kind of data -- which makes sense. Our goal should be that kind of independence. So we should allow array data to be paged. But what the most commonly requested Use Case is for something that manages the LIMIT clause of an SQL query.
3. Do the calculations to determine the start and end record numbers for the page based on the page number. We need to determine what data values we want to make available and how (var or method?) and what settings we have (e.g. number of records per page). Also if we support both arrays and DB then we need to decide where to deal with zero or one based.
4. Output HTML. We want this to be separate because there are many ways to show the paging links. We will need to decide what the output of the default outputter is. And we need to decide what links to support next/prev, first/last. As a second example we can adapt jshpro2's create_pagination() function.
Dependencies (I think):
Pager --> Request
Pager --> Data Mgr
Outputter --> Pager
(#10850)
- feyd
- Neighborhood Spidermoddy
- Posts: 31559
- Joined: Mon Mar 29, 2004 3:24 pm
- Location: Bothell, Washington, USA
I'm seeing a pluggable system.
Input handling
An input handling class could be employed to allow a user to customize how the inputs are processed and found. For example, an implementation of the interface could use pathinfo to build the information bits needed by the main class. This class should also have a URL generation function for the links created (for use by the output), since that leads to the input characteristics it'll look for.
Data interface
Having a data interface would allow implementations for both DB and array based handling of information. Special cases for the main class would be then handled by the implementation as it is handling the actual data fetches, wherever they may come from. A default of an array handler would probably be best since it's the most generic.
Page numbering callback
Having an callback (with defaults, of course) for creating the page numbering display would allow for simple customization.
Output
After trimming and various processing by the main class, which under my idea would really just be a sequencial delegator, all the information collected by the various outputs from the above systems would be passed to this class. This class determines final appearance and output (or not) of the actual paging. It may be XML, XHTML, RSS, or C.. who-knows?
Input handling
An input handling class could be employed to allow a user to customize how the inputs are processed and found. For example, an implementation of the interface could use pathinfo to build the information bits needed by the main class. This class should also have a URL generation function for the links created (for use by the output), since that leads to the input characteristics it'll look for.
Data interface
Having a data interface would allow implementations for both DB and array based handling of information. Special cases for the main class would be then handled by the implementation as it is handling the actual data fetches, wherever they may come from. A default of an array handler would probably be best since it's the most generic.
Page numbering callback
Having an callback (with defaults, of course) for creating the page numbering display would allow for simple customization.
Output
After trimming and various processing by the main class, which under my idea would really just be a sequencial delegator, all the information collected by the various outputs from the above systems would be passed to this class. This class determines final appearance and output (or not) of the actual paging. It may be XML, XHTML, RSS, or C.. who-knows?
- Christopher
- Site Administrator
- Posts: 13596
- Joined: Wed Aug 25, 2004 7:54 pm
- Location: New York, NY, US
Starting to look like a framework. This is always a struggle for me because what you or I might consider a bare bones system looks very complex to new PHP programmers.feyd wrote:I'm seeing a pluggable system.
We could do a Request class, but I'm not sure it gets us much and it adds a bunch of code that newbies have to wade through. I was thinking that intval($_GET[$this->page_parameter]) might do for this pass. I use a Request class in my own code so I definitely like the idea -- I just worry about complexity.feyd wrote:Input handling
An input handling class could be employed to allow a user to customize how the inputs are processed and found. For example, an implementation of the interface could use pathinfo to build the information bits needed by the main class. This class should also have a URL generation function for the links created (for use by the output), since that leads to the input characteristics it'll look for.
At a minimum it just needs to tell us the Total Rows. We need to decide if we want to fetch data internally or have the application responsible for dealing with the rows.feyd wrote:Data interface
Having a data interface would allow implementations for both DB and array based handling of information. Special cases for the main class would be then handled by the implementation as it is handling the actual data fetches, wherever they may come from. A default of an array handler would probably be best since it's the most generic.
I'm not clear on what you mean by "callback" but in OO/pattern speak it sounds like Decorator. My guess is you want the programmer to provide formatting code that is called to render each link. Sounds good, but it is really not clear to me yet how this should be implemented.feyd wrote:Page numbering callback
Having an callback (with defaults, of course) for creating the page numbering display would allow for simple customization.
I like the idea of being able to support different output renderers. The thing that is not clear to me is whether we should render the whole thing or just provide methods that can create the various links and let the application render everything else. Jcart's class (here) does the latter which is was along the lines of what I was thinking about. But maybe we should go farther?feyd wrote:Output
After trimming and various processing by the main class, which under my idea would really just be a sequencial delegator, all the information collected by the various outputs from the above systems would be passed to this class. This class determines final appearance and output (or not) of the actual paging. It may be XML, XHTML, RSS, or C.. who-knows?
Here is a quick hack of a pseudo-implementation based on the dependencies I listed above to show generally what I am thinking:
Code: Select all
// create a data object that has the interface needed by the Pager object
$datasource = new PagerArrayDatasource($myarray);
// create pager using values from datasource and request parameters
$pager = new Pager($datasource);
// create Outputter that gets its values from Pager object
$output = new PagerHTMLOutputter($pager);
$output->render();
// Outputer might also might have specific methods getPrevLink(), getNextLink(), getCurrentPage(), getTotalPages()(#10850)
- feyd
- Neighborhood Spidermoddy
- Posts: 31559
- Joined: Mon Mar 29, 2004 3:24 pm
- Location: Bothell, Washington, USA
my post was directed at end goal points, not just first pass. Yes, my end goal would resemble, if not be, a framework of sorts. Obviously a complete framework is outside the boundries of this excersize, but one can push towards it.arborint wrote:Starting to look like a framework. This is always a struggle for me because what you or I might consider a bare bones system looks very complex to new PHP programmers.
It's perfectly fine to use the basic straight-forward intval() et al for first, maybe even second passes. It certainly can get complex, but that is up to the implementation of the request class. The paging class should only need to talk with 1 to maybe 3 functions from it, of which should overall be fairly simple in implementation depending on how far gone one goes down OOP lanesarborint wrote:We could do a Request class, but I'm not sure it gets us much and it adds a bunch of code that newbies have to wade through. I was thinking that intval($_GET[$this->page_parameter]) might do for this pass. I use a Request class in my own code so I definitely like the idea -- I just worry about complexity.
True, the most basic would give total rows and "here's the data."arborint wrote:At a minimum it just needs to tell us the Total Rows. We need to decide if we want to fetch data internally or have the application responsible for dealing with the rows.
I'm using PHP's definition of callback in this instance (http://php.net/language.pseudo-types#la ... s.callback.)arborint wrote:I'm not clear on what you mean by "callback" but in OO/pattern speak it sounds like Decorator. My guess is you want the programmer to provide formatting code that is called to render each link. Sounds good, but it is really not clear to me yet how this should be implemented.
Both should be possible using a Fascade to allow any number of choices in output, including none at all (shunting the data to a separate object for later rendering by the application.)arborint wrote:I like the idea of being able to support different output renderers. The thing that is not clear to me is whether we should render the whole thing or just provide methods that can create the various links and let the application render everything else. Jcart's class (here) does the latter which is was along the lines of what I was thinking about. But maybe we should go farther?
That's roughly what is in my head for the initiation.arborint wrote:Here is a quick hack of a pseudo-implementation based on the dependencies I listed above to show generally what I am thinking:Code: Select all
// create a data object that has the interface needed by the Pager object $datasource = new PagerArrayDatasource($myarray); // create pager using values from datasource and request parameters $pager = new Pager($datasource); // create Outputter that gets its values from Pager object $output = new PagerHTMLOutputter($pager); $output->render(); // Outputer might also might have specific methods getPrevLink(), getNextLink(), getCurrentPage(), getTotalPages()