I currently have a Zend Framework route defined as such:
$route = new Zend_Controller_Router_Route('brand/:brand_name/series/:page',
array('controller' => 'brand',
'action' => 'series',
'page'=>'1'));
$router->addRoute('Brand Series', $route);
I'm trying to adapt this route so that the page parameter only catches numbers, so that I can add another route that uses words in the same place without the two conflicting, something like:
brand/:brand_name/series/:series_name/:page
I figured I would step along with the examples in the ZF documentation here. The very first step would be to change the route to something like this:
$route = new Zend_Controller_Router_Route_Regex('brand/:brand_name/series/(\d+)',
array('controller' => 'brand',
'action' => 'series'));
However, this small change causes routes that matched perfectly before, like /brand/johnnycupcakes/series/2 to fail, telling me Action "johnnycupcakes" does not exist and was not trapped in __call(). And in the stack trace I see:
'controller' => 'brand',
'action' => 'johnnycupcakes',
'series' => '2',
'module' => 'default'
In fact, even if I leave the route and default parameters exactly the same as in the first example, and simply change the class to Router_Route_Regex, I get the same error.
I know that the error isn't a routing conflict, because I haven't added the route that would have conflicted. Plus, it appears that it's attempting to match to the standard route. I'm testing this on version 1.11, so my version should be perfectly compatible with the code in the example.
As far as I can tell, the regex route is simply not matching, despite that it very clearly fits. Why could this possibly be failing?
EDIT:
I omitted the addRoute from the question the first time. I always had it in the code, that's not the issue.
What you need is to name a captured numeric parameter by adding third argument to Zend_Controller_Router_Route_Regex:
$route = new Zend_Controller_Router_Route_Regex(
'brand/:brand_name/series/(\d+)',
array(
'controller' => 'brand',
'action' => 'series'
),
array(
1 => 'series', // name the parameter captured by (\d+)
)
);
The second array may have keys and values in opposite relation 'series' => 1 and it will still work. Check more in ZF manual on regex routes
Related
I am facing some problems in routing under cakephp
there are three actions in my controller
they are as below
www.example.com/photos/newphotos
www.example.com/photos/random
www.example.com/photos/popular
I want them as
www.example.com/newphotos
www.example.com/random
www.example.com/popular
so i routes file under config file I wrote as
Router::connect('/:newphotos', array('controller' => 'photos', 'action' => 'newphotos'));
Router::connect('/:popular', array('controller' => 'photos', 'action' => 'popular'));
Router::connect('/:random', array('controller' => 'photos', 'action' => 'random'));
its working fine when I hit the url
www.example.com/newphotos
but when I hit url www.example.com/random or www.example.com/popular , its again point to action newphotos.
so how can I solve it
(In other words I need to remove controller name "photos" from url for every action)
Many thanks
Why not remove the : from the routes?
If you want to stick with /: paths, then you would need to supply a third parameter to Router::connect() in which to specify patterns for the added options. That is, if you have /:popular as the first parameter, you would need array('popular' => 'popular') as the third parameter, making the rule look like:
Router::connect('/:popular', array('controller' => 'photos', 'action' => 'popular'), array('popular' => 'popular'));
This means that :popular will be matched against the given regex, that is the literal 'popular'. See CakePHP's docs for more info.
Nevertheless, this is useless and silly, so you should stick with paths without colons.
Just delete the colon from the first parameter. They are kind of "capturing variables", so now you basically are routing all / with some parameters to photos/newphotos, and the parameters being captured to :newphotos. As it always will match the first route, then it will not look for the others.
I'm trying to create or find a route which will basically catch all.
What I need is something that can route the something like the following;
/some-page/some-childpage/another-childpage
/another-page
/yet-anotherpage/page
These urls will not be related to any module as such, they're more so an admin can create pages at any url.
I've got something which catches the routes at the moment using wildcard routing and a child wildcard route, but when I use it in the URL view helper it's encoding the forward slashes within the 'url' parameter.
Basically:
$this->url( 'public_page', array( 'url' => 'foo/bar' ) )
Is outputting /foo%2Fbar.
As well as not allowing /s, when trying to retrieve the url parameter, its returning the query string upto the first /.
Any help and suggestions would be great!
Regards,
Michael
I'm not sure you could do that with an arbitrary number of segments. You could specify a segment route with the maximum amount of segments you expect and then just allow them all to be optional, but that seems a dirty way to do it if you're trying to use lots of segments.
'route' => '/:controller[[[[/:action]/:third]/:fourth]/:fifth]',
'constraints' => array(
'controller' => '[a-zA-Z][a-zA-Z0-9_-]+',
'action' => '[a-zA-Z][a-zA-Z0-9_-]+',
),
'defaults' => array(
'controller' => 'Application\Controller\IndexController',
'action' => 'index',
'third' => 'something',
'fourth' => 'something-else',
),
You could possibly get something done with the Regex route, but again that's probably nasty as well.
http://framework.zend.com/manual/2.0/en/modules/zend.mvc.routing.html#zend-mvc-router-http-regex
I would probably suggest to use a better url structure as urls that deep aren't great anyway.
I have a controller that can be invoked as modulename/xmlcoverage with index action and some other actions, let say testAction().
The url to this controller is xml/coverage.
The default way is then that xml/coverage maps to my index action. And that xml/coverage/test maps to testAction. If I need an id for testAction, the url would be like xml/coverage/test/33 for instance.
However, for index action, it would need to be xml/coverage/index/33
Where I would like it to be xml/coverage/33.
This is my route
'xmlcoverage' => array(
'type' => 'segment',
'options' => array(
'route' => '/xml/coverage[/:action][/:id]',
'constraints' => array(
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]+',
),
'defaults' => array(
'controller' => 'modulename/xmlcoverage',
'action' => 'index',
),
),
),
When trying the url xml/coverage/33, I believe 33 should map to id, as it doesn't match the regex of action and both are optional. And since it doesn't match an action, the default (index) should be used.
Instead I get an error saying that the url cannot be matched by routing.
So for me, it acts as if the route was '/xml/coverage[/:action[/:id]]' because I for some reason have to specify action for it to recognize the id.
What am I doing wrong, and how can I get the urls to work as I'd like?
Thanks.
EDIT: Here is a problem.
Doing this in my view:
$this->url('xmlcoverage', array('action' => 'index', 'id' => $someid))
actually gives an URL on the form xml/coverage/1 which will crash!
Changing the route to /xml/coverage[/:action[/:id]] will at least make the url helper produce working urls..
After talking and debugging with the nice ZF2 folks on IRC, we tracked down a bug in the routing.
During the discussion I made a small example to my issue, which is here.
As you can see from the var dump here, the action gets lost in the second case where it should default to "index".
But if anyone needs this functionality to work right now, here are ways that fix it:
Instead of having the route to be /test[/:action][/:id] have it to be /test[/:action[/:id]], then the url helper will add /index/ and at least it works.
Make a new route where you only listen for /test[/:id] in addition to the other one.
In your controller, do public function notFoundAction() { $view = new ViewModel($this->indexAction()); //etc} Kinda hacky, but with this bug it will dispatch a not found action, which you can piggyback.
Here is an example of a Route, taken from this page:
$route = new Zend_Controller_Router_Route_Regex(
'blog/archive/(\d+)-(.+)\.html',
array(
'controller' => 'blog',
'action' => 'view'
),
array(
1 => 'id',
2 => 'description'
),
'blog/archive/%d-%s.html'
);
$router->addRoute('blogArchive', $route);
I can see that it matches paths that follow the pattern 'blog/archive/(\d+)-(.+)\.html', redirecting to the blog controller and view action, and passing along the id and description parameter. But, what is the purpose of the fourth argument; 'blog/archive/%d-%s.html'?
I posted the question and found the answer on the page a few seconds later; what a surprise.
Since regex patterns are not easily
reversed, you will need to prepare a
reverse URL if you wish to use a URL
helper or even an assemble method of
this class. This reversed path is
represented by a string parsable by
sprintf() and is defined as a fourth
construct parameter.
I've got a question considering Zend_Controller_Router. I'm using a a modular-structure in my application. The application is built upon Zend-Framework. The normal Routes are like this:
/modulename/actionname/
Since I always use an IndexController within my modules, it's not necessary to provide it in the url. Now I am able to append params like this:
/modulename/actionname/paramkey/paramvalue/paramkey/paramvalue
So this is normal in ZF, I guess. But in some cases I don't want to provide a paramkey within the url. For example I want a blog-title to be shown within the url. Of course this is intended for SEO:
/blog/show/id/6/this-is-the-blog-title
In this case, blog is the module, show is the action. id is a paramkey and 6 is the id of the blogpost I want to show. this-is-the-blog-title is of course the headline of the blogpost with the id 6. The problem is, that if I do use the assemble()-method of the router like this:
assemble(array('module' =>'blog',
'action' => 'show',
'id' => $row['blog_id'],
$row['blog_headline_de'] . '.html'));
the url results in:
blog/show/id/6/0/this-is-the-blog-title.html
As you can see a 0 is inserted as a key. But I want this 0 to be omitted. I tried this by using the blogtitle as key, like this:
assemble(array('module' =>'blog',
'action' => 'show',
'id' => $row['blog_id'],
$row['blog_headline_de'] . '.html' => ''));
This results in:
blog/show/id/6/this-is-the-blog-title.html/
Now the 0 is omitted, but I've got the slash at the end.
Do you have any solution to get an url without 0 as key and without an ending slash?
Regards,
Alex
You might want to use a custom route for this:
$router->addRoute(
'blogentry',
new Zend_Controller_Router_Route('blog/show/:id/:title',
array('controller' => 'index', 'module' => 'blog'
'action' => 'info'))
);
And call your assemble with the route as second parameter. See the Zend_Controller_Router_Route section of the documentation for more details (they even provide examples with assemble).
Or in a more general way:
$router->addRoute(
'generalseo',
new Zend_Controller_Router_Route(':module/:action/:id/:title',
array('controller' => 'index'))
);