1
votes

I'm having some trouble creating custom routes for my blog module (which I'm doing to learn Magento better).

What I did so far: Created a custom table that also contains the required slugs. Added in my config.xml the following

<default>
    <web> <!-- what does this represent??? -->
        <routers>
            <namespace_blog_list>
                <area>frontend</area>
                <class>Namespace_Blog_Controller_Router</class>
            </namespace_blog_list>
        </routers>
    </web>
</default>

So, I create the Namespace_Blog_Controller_Router class, and copied the match() method from the CMS Controller, but not quite sure how to modify it.

Here is what I have so far:

// $identifier is 'blog/view/my-slug-name';
$parts = explode('/', $identifier);
    if ($parts[0] == 'blog') {
        $post = Mage::getModel('namespace_blog/post');
        $routeInformation = $post->checkIdentifier($identifier);

        $request->setModuleName('namespace_blog')
            ->setControllerName($routeInformation['controller'])
            ->setActionName($routeInformation['action']);

        if (isset($routeInformation['params']) && count($routeInformation['params'])) {
            foreach ($routeInformation['params'] as $key => $param) {
                $request->setParam($key, $param);
            }
        }

        $request->setAlias(
            Mage_Core_Model_Url_Rewrite::REWRITE_REQUEST_PATH_ALIAS,
            $identifier
        );
        return true;
    }

PS: $post->checkIdentifier returns the following array:

array(
    'controller' => 'index',
    'action' => 'index',
    'params' => array(
        'id' => 3
    )
)

The problem is that it goes in an infinite loop, I found the following report:

a:5:{i:0;s:52:"Front controller reached 100 router match iterations";i:1;s:337:"#0 /var/www/app/code/core/Mage/Core/Controller/Varien/Front.php(183): Mage::throwException('Front controlle...')
#1 /var/www/app/code/core/Mage/Core/Model/App.php(354): Mage_Core_Controller_Varien_Front->dispatch()
#2 /var/www/app/Mage.php(683): Mage_Core_Model_App->run(Array)
#3 /var/www/index.php(87): Mage::run('', 'store')
#4 {main}";s:3:"url";s:21:"/index.php/blog/index";s:11:"script_name";s:10:"/index.php";s:4:"skin";s:7:"default";}`

Any ideas? Is this the best way to do it, or is there another recommended solution ?

Thanks,

1

1 Answers

2
votes

CMS page route is added with help of controller_front_init_routers event.

First of all you need to define standard frontend route for your module

<config>
    <frontend>
        <routers>
            <mymodule>
                <use>standard</use>
                <args>
                    <module>My_Module</module>
                    <frontName>mymodule</frontName>
                </args>
            </mymodule>
        </routers>
    </frontend>
</config>

This allows you to send request as http://example.com/mymodule/controller/action/

After this look at Mage_Core_Controller_Varien_Front::init(). In this method magento collects standard and admin routes (these are default for frontend and admin routing). When these routers are added mageto fires event controller_front_init_routers and using this global event you can register your own rout:

<config>
    <global>
        <events>
            <controller_front_init_routers>
                <observers>
                    <mymodule>
                        <class>My_Module_Controller_Router</class>
                        <method>initControllerRouters</method>
                    </mymodule>
                </observers>
            </controller_front_init_routers>
        </events>
    </global>
</config>

and in route you should check if identifier matches your needs and call your controller

class My_Module_Controller_Router extends Mage_Core_Controller_Varien_Router_Abstract
{

    /**
     * Inject new route into the list of routes
     *
     * @param Varien_Event_Observer $observer
     */
    public function initControllerRouters($observer)
    {
        $front = $observer->getEvent()->getFront();

        $route = new My_Module_Controller_Router();
        $front->addRouter('myroute', $route);
    }

    /**
     * Compare current path with the route rules
     *
     * @param Zend_Controller_Request_Http $request
     * @return boolean
     */
    public function match(Zend_Controller_Request_Http $request)
    {

        if (!Mage::app()->isInstalled()) {
            Mage::app()->getFrontController()->getResponse()
                    ->setRedirect(Mage::getUrl('install'))
                    ->sendResponse();
            return FALSE;
        }

        $route = 'myroute';

        $identifier = $request->getPathInfo();

        if (substr(str_replace("/", "", $identifier), 0, strlen($route)) == $route) {
            if (str_replace("/", "", $identifier) == $route) {
                $request->setModuleName('mymodule')
                        ->setControllerName('index')
                        ->setActionName('index');
                return TRUE;
            }

            $suffix = Mage::helper('catalog/product')->getProductUrlSuffix();
            $identifier = substr_replace($request->getPathInfo(), '', 0, strlen("/" . $route . "/"));
            $identifier = str_replace($suffix, '', $identifier);

            // here we make some check to make sure we have requested page
            $mymodule = Mage::getModel('mymodule/mymodule');
            $module_id = $mymodule->checkIdentifier($identifier, Mage::app()->getStore()->getId());
            if (!$module_id) {
                return FALSE;
            }

            // send request to the module's controller
            $request->setModuleName('mymodule')
                    ->setControllerName('index')
                    ->setActionName('view')
                    ->setParam('id', $module_id);

            return TRUE;
        } else {
            return FALSE;
        }
    }

}

That's all.

<default>
    <web>
        <default>
            <cms_home_page>home</cms_home_page>
            <cms_no_route>no-route</cms_no_route>
            <cms_no_cookies>enable-cookies</cms_no_cookies>
            <front>cms</front>
            <no_route>cms/index/noRoute</no_route>
            <show_cms_breadcrumbs>1</show_cms_breadcrumbs>
        </default>
    </web>
</default>

this is the default secton of the cms module. You can find these setting in admin under System - configuration - web - default pages