You are Here: Articles » Managing Simple Pages in CakePHP

Managing Simple Pages in CakePHP

Creating pages dynamically with a PagesController and using a dynamic route to publish them at any URL.

Tagged with CakePHP and Web Development
Posted on 15/7/07 by Paul Herron

As well as complex functionality like blogs or product listings, websites often need simple pages. An about us or our services page, for example, might consist of only text and images.

CakePHP has two obvious ways to set up simple pages like these. The first is to drop a view file into app/views/pages. This is quick and easy, but the page won't be dynamic and the standard URLs of /pages/about and /pages/services might seem strange when, from the user's perspective, /about and /services would be more logical.

The second approach is to set up controllers and views for the pages. The above example could use an AboutController and a ServicesController, each with their own empty index() action and an index.ctp view file. The pages are now accessible at intuitve URLs - /about and /services - and page content can easily be managed in the database, rather than being hard-coded into the view files. The disadvantage of this approach is that coding would be required to add new pages.

Alternative Approach

The best aspects of the techniques mentioned above can be combined by introducing the following:

  • A Page model. This will store all of the website's simple pages.
  • A dynamic route in routes.php. This will recognise URL requests for stored pages and route them through to the PagesController.

The pages database table might look something like this:

  1. `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  2. `title` TEXT,
  3. `slug` varchar(255),
  4. `content` TEXT,
  5. `created` datetime,
  6. `modified` datetime

The slug field is simply the relative URL at which the page will be accessible. For example, a slug of about will be used to set up a page at http://example.com/about and a slug of services/technical will be available at http://example.com/services/technical.

A PagesController and corresponding views should be set up. A main index() action will be used to display the stored pages. Admin actions such as admin_add() could also be used to allow editing of the pages' content. It might also be worth taking a copy of Cake's core display() action from cake/libs/controller/pages_controller.php so that static pages in app/views/pages can still be displayed.

A route is then required to send requests for stored pages to PagesController::index(). To recognise which URLs correspond to stored pages, it will be necessary to load and query the Page model. This gives us a list of slugs to add as conditions to the $params array of the route. This could be done by putting the following code in app/config/routes.php:

  1. // Load details of stored pages.
  2. uses('model' . DS . 'model');
  3. loadModel('Page');
  4. $Page = new Page();
  5. $pages = $Page->generateList(null,'slug DESC',null,null,'{n}.Page.slug');
  6.  
  7. //If the URL matches the slug of a stored page, route to PagesController::index() and set $this->params['page'] to whatever the slug is.
  8. $Route->connect ('/:page/*', array('controller'=>'pages', 'action'=>'index'), array('page' => implode($pages, '|')));

Note: It's important to retrieve the page slugs in descending alphabetical order, otherwise child pages will wrongly be routed to their parents. For example, if 'services' appears in the $params array before 'services/technical', a URL requesting 'services/technical' would be routed to 'services'.

The PagesController is then free to pick up $this->params['page'] and fetch the relevant page using $this->Page->findBySlug($this->params['page']).

Extending the Idea

This is a simple description of the technique; it could of course be extended in any number of ways. For example:

  • The actual page content could be stored in a separate sections table. Associations could then be set up to say that a page hasMany sections and a section belongsTo a page. This would allow any section on a page to be linked to directly, e.g. /services/technical#programming. An extension of this would be outputting an 'on this page' element which lists and links to each section on the current page.
  • Pages could be given a parent_id, making a hierarchical page structure possible. For example, /services could be displayed as being a parent of /services/technical.
  • Pages could be assigned positions on navigation menus. For example, a link to the /about page could be set to appear on the site's main navigation menu.

Comments

kabturek wrote on 16/7/07:

Hey

I like the idea but i would do it diffrently myself:

->i would cache the actual pages array (serilize into tmp)

->read the array and search for the desired value

-> if it exist then add the route

->i would update the cached array only when there is an add/edit/delate ( a callback in the model)

 

greets, 

matt wrote on 7/9/08:

I would love to implement this on my site but I am somewhat new to cake, could you possible give some more detail how the index portion of the pages_controller would work?

Thanks 

Andy wrote on 31/12/08:

Great article.  Simple language. Lots of info.

Thanks

Michelle wrote on 2/1/09:

Brief and to the point article, but its missing any details about using mail functionality.  If you can include that, it will become more valuable.

Mich.

Peter wrote on 21/12/09:

Excellent tutorial! I have taken the code and adapted it to cake 1.2 incase anyone is interested.

App::import('model', 'Page');


$Page = new Page();


$pages = $Page->find('list', array('fields' => array('id', 'permalink')));


Router::connect('/:page/*', array('controller' => 'pages'), array('page' => implode($pages, '|')));

Leave a Comment

CAPTCHA[Refresh]

« Articles

Article Tags

Show all articles, or just those tagged as:

Feed

The articles RSS feed is available.

Elsewhom

See More…

Back to top.