Posts tagged 'navigation'

Playing with Zend_Navigation and routes

published on August 09, 2009.
Heads-up! You're reading an old post and the information in it is quite probably outdated.

O hai. First things first - someone should slap me for being such a lazy blogger. Somehow I lost all the motivation I had in the beginning, but looks like it’s back now :) I finally had the time to play around with the latest Zend Framework version (v 1.9 now). I managed to skip the whole 1.8.x version, so this whole Zend_Application stuff is quite new to me. I spent a few days poking around the manual and the code to make it work. And it works! Yey for me! And yey for Rob Allen for his post on Bootstrapping modules in ZF 1.8!

Zend_Tool is an awesome tool. Creating a new project is like “zf create project project_name” :) And the new bootstrapping process with the Bootstrap class is somehow much clearer to me now… Anyways, lets skip to the code.

The goal

I wanted to set up routes in such way that when a user requests a page, all requests for non-existing controllers/modules are directed to a specific controller (not the error controller). In other words, if we have controllers IndexController, FooController and PageController, anything but http://example.com/index and http://example.com/foo is directed to the PageController. This can be useful for CMSs or blogs to make pretty links. Here’s where the Zend_Controller_Router_Route_Regex stuff comes in:

<?php
$route = new Zend_Controller_Router_Route_Regex(
    '(?(?=^index$|^foo$)|([a-z0-9-_.]+))',
    array(
        'controller' => 'page',
        'action' => 'view',
        'slug' => null
    ),
    array(
        1 => 'slug',
    ),
    '%s'
    );

$router->addRoute('viewPage', $route);

Basically the regex does the following: if it’s index or foo don’t match anything, thus calling up those controllers, in any other case match what’s requested and pass it to the PageController’s viewAction as the slug parameter. The fourth parameter, the ‘%s’, is needed so that ZF can rebuild the route in components like the Zend_Navigation.

Now, when the PageController, viewAction get’s called up, we can check, for example, if a page with that slug exists (like, in a database). If it exists, show the content, otherwise call up a 404 page with the error controller. In this fancy and sexy way we can call up pages without passing ID’s or even letting the user know what part of the website is working on his request. He just request’s http://example.com/some_random_article and kaboom! he get’s the content :)

Page navigation

Oh the joy when I saw Zend_Navigation in the library! And it even includes view helpers to help us render links and menus and breadcrumbs! Yey! There are a several blog posts which go in details about Zend_Navigation, so I won’t be bothering with that. What I wanted to make with Zend_Navigation is to have a menu of all the pages rendered everywhere. Here’s where action helpers kick in. I made an action helper which makes up the structure of the links/pages. Something like this:

<?php
class Zend_Controller_Action_Helper_LinkStructure extends
        Zend_Controller_Action_Helper_Abstract{
function direct(){
$structure = array(
    array(
         'label'=>'Home page',
         'uri'=>'/'
    ),
    array(
         'label'=>'Articles',
         'uri'=>'',
         'pages'=>array(array(
                                  'label'=>'Article 1',
                                  'uri'=>'article_1'),
                              array(
                                  'label'=>'Article 2',
                                  'uri'=>'article_2'),
                         )
    )
);
return new Zend_Navigation($structure);
}
}

This is a simple example of the structure; I’m actually making it out from the database, with all the categories, subcategories and pages.

Links everywhere

To have this menu on all pages, we need to render it in the layout.phtml. Rendering is quite simple:

<?php
// somewhere in layout.phtml
<?php echo $this->navigation()->menu(); ?>

Of course, we need to pass the menu to the navigation helper somehow. To avoid doing $this->navigation($this->_helper->linkStructure()); in all the controllers, we could do that once in the bootstrap (any other ways to make it happen?):

<?php
// in Bootstrap.php somewhere in the Bootstrap class
function _initView(){

        $view = new Zend_View();
        $view->doctype('XHTML1_STRICT');
        $view->headMeta()->appendHttpEquiv('Content-Type', 'text/html; charset=UTF-8');

        // our helper is in app/controllers/helpers folder, but ZF doesn't know that, so tell him
        Zend_Controller_Action_HelperBroker::addPath(APPLICATION_PATH.'/controllers/helpers');
        // now get the helper
        $linkStructure = Zend_Controller_Action_HelperBroker::getStaticHelper('LinkStructure');
        // and assign it to the navigation helper
        $view->navigation($linkStructure->direct());

        $viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper('ViewRenderer');
        $viewRenderer->setView($view);

        return $view;
}

There. Now we have our menu rendered on all pages. Sexy isn’t it? :)

That’s it for now. Hope someone will find this useful :) Now I gotta go, need to get ready for a punk rock concert tonight!

Happy hacking!

Wordpress paging navigation

published on October 06, 2008.
Heads-up! You're reading an old post and the information in it is quite probably outdated.

As I’m not a big fan of Wordpress plug—ins, and I wanted to use a normal page navigation, not just the default “Previous posts” and “Next posts”, I decided to play around a bit and create my own paging navigation, or pagination.

Preparation

First, I wrote on a piece of paper which links I need: first page, last page, next page, previous page and the links with the page numbers. Next, I needed to see what functions are already in Wordpress, to reuse as much as I can. After a little searching, I found that the functions for the default navigation are located in the link-template.php file, under the wp-includes folder. There are the functions for the next and previous pages, and the function that creates the URL. Furthermore, I wanted a sliding pagination (like Yahoo has on it’s search page), ‘cause it’s easy to use and looks cool.

The function

So, let’s take a look at the code. I called the function simply get_pagination; it’s quite self—describing. I put it in the link-template.php file, that way, all functions for navigation are in one place.

<?php
/**
* A pagination function
* @param integer $range: The range of the slider, works best with even numbers
* Used WP functions:
* get_pagenum_link($i) - creates the link, e.g. http://site.com/page/4
* previous_posts_link(' &laquo; '); - returns the Previous page link
* next_posts_link(' &raquo; '); - returns the Next page link
*/
function get_pagination($range = 4){
  // $paged - number of the current page
  global $paged, $wp_query;
  // How much pages do we have?
  if ( !$max_page ) {
    $max_page = $wp_query->max_num_pages;
  }
  // We need the pagination only if there are more than 1 page
  if($max_page > 1){
    if(!$paged){
      $paged = 1;
    }
    // On the first page, don't put the First page link
    if($paged != 1){
      echo "<a href=" . get_pagenum_link(1) . "> First </a>";
    }
    // To the previous page
    previous_posts_link(' &laquo; ');
    // We need the sliding effect only if there are more pages than is the sliding range
    if($max_page > $range){
      // When closer to the beginning
      if($paged < $range){
        for($i = 1; $i <= ($range + 1); $i++){
          echo "<a href='" . get_pagenum_link($i) ."'";
          if($i==$paged) echo "class='current'";
          echo ">$i</a>";
        }
      }
      // When closer to the end
      elseif($paged >= ($max_page - ceil(($range/2)))){
        for($i = $max_page - $range; $i <= $max_page; $i++){
          echo "<a href='" . get_pagenum_link($i) ."'";
          if($i==$paged) echo "class='current'";
          echo ">$i</a>";
        }
      }
      // Somewhere in the middle
      elseif($paged >= $range && $paged < ($max_page - ceil(($range/2)))){
        for($i = ($paged - ceil($range/2)); $i <= ($paged + ceil(($range/2))); $i++){
          echo "<a href='" . get_pagenum_link($i) ."'";
          if($i==$paged) echo "class='current'";
          echo ">$i</a>";
        }
      }
    }
    // Less pages than the range, no sliding effect needed
    else{
      for($i = 1; $i <= $max_page; $i++){
        echo "<a href='" . get_pagenum_link($i) ."'";
        if($i==$paged) echo "class='current'";
        echo ">$i</a>";
      }
    }
    // Next page
    next_posts_link(' &raquo; ');
    // On the last page, don't put the Last page link
    if($paged != $max_page){
      echo " <a href=" . get_pagenum_link($max_page) . "> Last </a>";
    }
  }
}

The “range” is the range of the sliding effect, i.e. how many numbers are shown besides the current number: if the range is 4, and the current page is 5, then the numbers 3, 4, 5, 6 and 7 are visible.

Usage

It’s quite simple to use it: where the pagination is needed, just call the get_pagination() function, and it will show up. Add some CSS style to it, and your good to go.

Hope someone will find this useful :)

Robert Basic

Robert Basic

Software engineer, consultant, open source contributor.

Let's work together!

If you require outsourcing or consulting help on your projects, I'm available!

Robert Basic © 2008 — 2019
Get the feed