alokiN
alokiN

Reputation: 41

Zend Route Url with regex

I'm trying to create a route that will "cover" this kind of URLs:

www.test.com/parent1/parent2/parent3/item

www.test.com/parent1/parent2/parent3/parent4/item1

Number of those parents in unspecified, and it should only serve to give a better, more intuitive look to site URLs. Main parameter is that "item".

I suppose that only way to solve that is to use Route_Regex, and so I tried to accomplish this route task with something like this:

routes.test.type = "Zend_Controller_Router_Route_Regex"
routes.test.route = "test/(?:.*)?([^\/]+)"
routes.test.defaults.module = default
routes.test.defaults.controller = test
routes.test.defaults.action = index
routes.test.map.1 = "path"
routes.test.map.2 = "item"
routes.test.reverse = "test/%s%s"

I haven't been testing this to much, because I'm not sure if I'm doing the right thing... I have no idea how that regex should even look like, and how should I treat that "path".

Can you advice what should I do to fulfill this kind of route demand? So, I need that path (parent1, parent2, etc.) only for appearance, and main param is that "item"...

Upvotes: 4

Views: 5520

Answers (3)

Peter Boughton
Peter Boughton

Reputation: 112230

If the parent items are completely unimportant, a simple solution might be to remove them before they even reach Zend - that is, rewrite the URLs so it only every sees test/:item

For example, using:

RewriteEngine On
RewriteRule ^(test/).*/([^/]+) $1$2  [L]

(The "test/" part can obviously be changed or made dynamic as required.)

That goes into Apache's config file for the site - or in .htaccess file on shared hosting.

If you're not using Apache, check the URL rewriting functionality for whatever web server you're using - the syntax may vary slightly but will be similar.

Upvotes: 1

Kenneth
Kenneth

Reputation: 91

I know this is an old question, but I had a similar problem and just thought I should post my solution. Maybe it can help others viewing this question.

I wrote my routes in a plugin, Obviously you need to add the plugin into the bootstrap for this to work ;)

class Plugin_RoutesPage extends Zend_Controller_Plugin_Abstract
{
    public function routeStartup(Zend_Controller_Request_Abstract $request)
    {
        $front_controller = Zend_Controller_Front::getInstance();
        $router = $front_controller->getRouter();

        // Page SEO friendly hierarchical urls
        $routePageSeoTree = new Zend_Controller_Router_Route_Regex(
            '([-a-zA-Z0-9/]+)/([-a-zA-Z0-9]+)',
            array(
                // default Route Values
                'controller' => 'page',
                'action' => 'open',
            ),
            array(
                // regex matched set names
                1 => 'parents',
                2 => 'item'
            )
        );
        $router->addRoute('page-seo-tree',$routePageSeoTree);

        // only one level
        $routeSinglePage = new Zend_Controller_Router_Route_Regex(
            '([-a-zA-Z0-9]+)',
            array(
                // default Route Values
                'controller' => 'page',
                'action' => 'open',
            ),
            array(
                // regex matched set names
                1 => 'item'
           )
        );
        $router->addRoute('page-single',$routeSinglePage);
    }
}

This is how you can use it in your controller's action

class PageController extends Zend_Controller_Action
{
    public function openAction()
    {
        // the part of the uri that you are interested in 
        $item = $this->_request->getParam('item');
    }
}

Here's a quick example of how to include it into your bootstrap

class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
    protected function _initPlugins()
    {
            $front_controller = Zend_Controller_Front::getInstance();

            $front_controller->registerPlugin(new Plugin_RoutesPage(), 1);
    }
}

I had to use two routes, because the current page we are trying to view/open might not have any parents. I'm sure there's probably a better way to write the regex, but this is what worked for me. If anyone knows how to improve the regex, please let me know.

Upvotes: 6

Peter Boughton
Peter Boughton

Reputation: 112230

I don't know what zend route is (something php related?), but if you can use normal programming functions then a much simpler solution than a regex is to use built-in list/split functions, eg:

end(explode($Url,'/'))

Url.split('/').last()

ListLast(Url,'/')

etc


If you do need a regex, you can do it simply with this:

[^/]+$

That will give you everything after the last forward-slash upto the end of the line.
(You only need to escape the / with a backslash if you're using it in a context which requires escaping.)


(btw, in your example, you've got test/ at the start - is that deliberate/required?)

Upvotes: -2

Related Questions