views:

88

answers:

2

I would like to create a custom CMS within Codeigniter, and I need a mechanism to route general pages to a default controller - for instance:

mydomain.com/about
mydomain.com/services/maintenance

These would be routed through my pagehandler controller. The default routing behaviour in Codeigniter is of course to route to a matching controller and method, so with the above examples it would require an About controller and a Services controller. This is obviously not a practical or even sensible approach.

I've seen the following solution to place in routes.php:

$route['^(?!admin|products).*'] = "pagehandler/$0";

But this poses it's own problems I believe. For example, it simply looks for "products" in the request uri and if found routes to the Products controller - but what if we have services/products as a CMS page? Does this not then get routed to the products controller?

Is there a perfect approach to this? I don't wish to have a routing where all CMS content is prefixed with the controller name, but I also need to be able to generically override the routing for other controllers.

+1  A: 

You are in luck. I am developing a CMS myself and it took me ages to find a viable solution to this. Let me explain myself to make sure that we are on the same page here, but I am fairly certain that we area.

Your URLS can be formatted the following ways:

http://www.mydomain.com/about - a top level page with no category
http://www.mydomain.com/services/maintenance - a page with a parent category
http://www.mydomain.com/services/maintenace/server-maintenance - a page with a category and sub category.

In my pages controller I am using the _remap function that basically captures all requests to your controllers and lets you do what you want with them.

Here is my code, commented for your convenience:

<?php

class Pages extends Controller {

    // Captures all calls to this controller
    public function _remap() 
    {
        // Get out URL segments
        $segments = $this->uri->uri_string();
        $segments = explode("/", $segments);

        // Remove blank segments from array
            foreach($segments as $key => $value) {
               if($value == "" || $value == "NULL") {
                   unset($segments[$key]);
               }
            }

            // Store our newly filtered array segments
            $segments = array_values($segments); 

            // Works out what segments we have
            switch (count($segments))
            {
                // We have a category/subcategory/page-name
                case 3:
                    list($cat, $subcat, $page_name) = $segments;
                break;

                // We have a category/page-name
                case 2:
                    list($cat, $page_name) = $segments;
                    $subcat = NULL;
                break;

                // We just have a page name, no categories. So /page-name
                default:
                    list($page_name) = $segments;
                    $cat = $subcat = NULL;
                break;
            }

        if ($cat == '' && $subcat == '') {

            $page  = $this->mpages->fetch_page('', '', $page_name);

        } else if ($cat != '' && $subcat == '') {

            $page  = $this->mpages->fetch_page($cat, '', $page_name);

        } else if ($category != "" && $sub_category != "") {

            $page = $this->mpages->fetch_page($cat, $subcat, $page_name);
        }

                // $page contains your page data, do with it what you wish.

}
?>

You of course would need to modify your page fetching model function accept 3 parameters and then pass in info depending on what page type you are viewing.

In your application/config/routes.php file simply put what specific URL's you would like to route and at the very bottom put this:

/* Admin routes, login routes etc here first */

$route['(:any)'] = "pages"; // Redirect all requests except for ones defined above to the pages controller.

Let me know if you need any more clarification or downloadable example code.

Dwayne
The problem with doing that is you have to set WAAAY to many routes, just upgrade to CI 2 and use the 404_override :)
Phil Sturgeon
A: 

If you use CodeIgniter 2.0 (which has been stable enough to use for months) then you can use:

$route['404_override'] = 'pages';

This will send anything that isn't a controller, method or valid route to your pages controller. Then you can use whatever PHP you like to either show the page or show a much nicer 404 page.

Read me guide explaining how you upgrade to CodeIgniter 2.0. Also, you might be interested in using an existing CMS such as PyroCMS which is now nearing the final v1.0 and has a massive following.

Phil Sturgeon