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
Pagemodel. 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 thePagesController.
The pages database table might look something like this:
`id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT, `title` TEXT, `slug` varchar(255), `content` TEXT, `created` datetime, `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:
// Load details of stored pages. uses('model' . DS . 'model'); loadModel('Page'); $Page = new Page(); $pages = $Page->generateList(null,'slug DESC',null,null,'{n}.Page.slug'); //If the URL matches the slug of a stored page, route to PagesController::index() and set $this->params['page'] to whatever the slug is.
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
sectionstable. Associations could then be set up to say that a pagehasManysections and a sectionbelongsToa 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,/servicescould be displayed as being a parent of/services/technical. - Pages could be assigned positions on navigation menus. For example, a link to the
/aboutpage could be set to appear on the site's main navigation menu.
Comments
Leave a Comment
Article Tags
Show all articles, or just those tagged as:
- Apache (1)
- CakePHP (10)
- Domains (1)
- Freeware (1)
- Graphics (1)
- Life (1)
- Open Source (2)
- Servage (1)
- SMS (1)
- Software (3)
- Ubuntu (2)
- WAMP (2)
- Web Development (13)
- Windows (2)
- Work (2)
Feed
The articles RSS feed is available.
Elsewhom
- Edinburgh's Dark Side.
-
Mi Blog.
CakePHP-related articles, downloads and demonstrations -
FFFFOUND!.
Image bookmarking -
Jeffrey Zeldman Presents the Daily Report.
Web design, news and info since 1995 -
mattheaton.com.
Bluehost Blog
Matt is CEO of Bluehost, a successful web hosting provider

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, '|')));