4

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"...

animuson
  • 53,861
  • 28
  • 137
  • 147
alokiN
  • 41
  • 1
  • 2

3 Answers3

6

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.

Kenneth
  • 91
  • 2
  • 7
1

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.

Peter Boughton
  • 110,170
  • 32
  • 120
  • 176
-2

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?)

Peter Boughton
  • 110,170
  • 32
  • 120
  • 176
  • Zend Route is part of the Zend Framework which is a well known PHP Framework. – Tamas Kalman May 23 '12 at 00:40
  • And this guy has 33k rep? That's not even PHP code you wrote there. – Eduard Luca Mar 07 '13 at 10:56
  • 2
    Eduard, "this guy" _didn't have 33k rep_ when he responded to the question _four and half years ago_, and was deliberately providing pseudo-code in an attempt to help the OP (when, at that time, nobody else had) rather than just ignoring the question because he didn't then know what tool they were using. – Peter Boughton Mar 07 '13 at 11:41