I'm working on a Zend Framework application and I just got my vanity routing working using the guide at http://tfountain.co.uk/blog/2010/9/9/vanity-urls-zend-framework/, but my pagination isn't working, and none of the vanity url guides I've been able to find touch on it.
My vanity route is set up as /:username/:filter/:pag
', where the last 2 parameters are optional. The page is displaying correctly, '/jaimerump/badges/2' is going to the second page of my badges, but the paginator isn't working because it can't seem to figure out what the url of the next page should be. I'm using the standard paginationControl.phtml file from every Zend pagination tutorial, code here:
<?php if ($this->pageCount): ?>
<div class="paginationControl" id="paginationControl">
<!-- Previous page link -->
<?php if (isset($this->previous)): ?>
<a href="<?php echo $this->url(array('page' => $this->previous)); ?>" id="previous">
< Previous
</a> |
<?php else: ?>
<span class="disabled">< Previous</span> |
<?php endif; ?>
<!-- Infinite Scroll doesn't use numbered page links -->
<!-- Next page link -->
<?php if (isset($this->next)): ?>
<a id="next" href="<?php echo $this->url(array('page' => $this->next)); ?>" >
Next >
</a>
<?php else: ?>
<span class="disabled">Next ></span>
<?php endif; ?>
</div>
<?php endif; ?>
Instead of returning '/jaimerump/badges/3', $this->url()
returns '/'. I'm sure that this has something to do with my custom route class. I changed the match function from Tim Fountain's tutorial and I changed the name of the class to VanityRouteUser and put it in my models folder, but other than that, everything is identical. Match function:
public function match( $path, $partial = false )
{
/* User profile routes are of form /:username/:filter/:page
Where filter can be haves, wants, badges, etc.
*/
if ($path instanceof Zend_Controller_Request_Http) {
$path = $path->getPathInfo();
}
$path = trim($path, $this->_urlDelimiter);
$pathBits = explode($this->_urlDelimiter, $path);
if ( count($pathBits) < 1 ) {
return false;
}
// check database for this user
$result = DB::call()->fetchRow('SELECT user_id
FROM users
WHERE username = ?', $pathBits[0]);
if ($result) {
// user found
$values = $this->_defaults;
$values['username'] = $pathBits[0];
$values['page'] = ( empty( $pathBits[2] ) )?1:$pathBits[2]; //if they didn't provide a page
// figure out which action based on second segment
$filter = $pathBits[1];
if( empty( $filter ) || $filter == 'default'
|| $filter == 'haves' || $filter == 'wants' ){
//Looking for user's haves, wants, or both
$values['action'] = 'index';
$values['filter'] = ( empty($filter) )?'default':$filter; //To catch the blank
}
else if( $filter == 'badges' ){
//Looking for user's badges
$values['action'] = 'badges';
}
else if( $filter == 'shelves' ){
//Looking for user's shelves
$values['action'] = 'shelves';
}
else{
//Must be a shelf id
$values['action'] = 'index';
$values['filter'] = $filter;
}
return $values;
}
return false;
}
What is $this->url()
? I haven't been able to find a url function in the Zend Paginator. And I'm assuming it's calling some function in the route class to try to get the url of the next page. What function is it calling, and do I have to overload it?
The problem was the assemble function. I was trying to use the function provided in Tim Fountain's tutorial, which was:
public function assemble($data = array(), $reset = false, $encode = false)
{
return $data['username'];
}
And I was getting '/' back because $data['username']
was undefined; the router was only providing a page parameter. When writing your own custom route classes, your assemble function must provide default values for any segments that aren't being passed in in the data array. Fixed it with:
public function assemble($data = array(), $reset = false, $encode = false)
{
//Check if username was provided
$username = ( $data['username'] )?$data['username']:$this->_defaults['username'];
//Check if filter was provided
$filter = ( $data['filter'] )?$data['filter']:$this->_defaults['filter'];
//Check if page was provided
$page = ( $data['page'] )?$data['page']:$this->_defaults['page'];
return $username.'/'.$filter.'/'.$page;
}