i thought i had the routing under control until i found out that i have now clue of how to have the default action url change, that means:
when ever a user enters a url, for example:
http://www.mysite.com/form/myform
the routing will always redirect him to the default action "show" (one of many actions this controller has):
http://www.mysite.com/form/myform/show
but my url remains the same (with the "show" action):
http://www.mysite.com/form/myform
what am i missing here?
'routes' => array(
'form' => array(
'type' => 'segment',
'options' => array(
'route' => '/form[/:form[/:action]]',
'constraints' => array(
'form' => '[a-zA-Z][a-zA-Z0-9_-]*',
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
),
'defaults' => array(
'controller' => 'Form\Controller\Form',
'action' => 'show',
),
),
),
),
thanks!
edited note:
i have noticed (thanks to #codeHeart marks) that i had some mistakes/misclarification trying to explain the problem, so i edited the main question examples.
thanks again all!
Looking at this in your question/
http://www.mysite.com/controller
and your router configuration I expect that should be throwing a 404 error, as there is no matching route in your config that matches /controller(If there are more routes other than the one that you show in you question, let us know or maybe you mistyped this url).
Apart from above,
your route tells to do the following:-
if url is
http://yoursite/form OR
http://yoursite/form/controller
go to the controller action that you have mentioned in the defaults, as the route was matched to the url but didn't get matched completely to an action so going to the default.
A non existing controller or a non existing action should be throwing 404. e.g
http://yoursite/form/controller/non-existing-action
Even this url
http://yoursite/form/
won't get matched according to your route and will be throwing a 404.
And for your question if you want to change the default action to something other then the "show" action, simply change the action parameter/key in defaults
'defaults' => array(
'controller' => 'Form\Controller\Form',
'action' => 'some-other-action',
),
Hope this helps and sorry if I was of no help.
Related
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've created a module, a basic copy of the the albums example given in the ZF2 documentation, however, with the new module, I am not able to access it at all - I'm always given a 404 error. I'm building this on the ZF2 skeleton.
I've got three modules loaded: Application, Frontend and Security.
Both Frontend and Security are duplicates of each other, however, I have thoroughly checked and there is no reference to old code (as I literally copied the module folder and renamed/rewrote references).
The module is also loaded in application.config.php.
Any ideas on what I'm missing?
Module Config:
return array(
'controllers' => array(
'invokables' => array(
'Security\Controller\Security' => 'Security\Controller\SecurityController',
),
),
'router' => array(
'routes' => array(
'security' => array(
'type' => 'segment',
'options' => array(
'route' => '/security[/:action][/:id]',
'constraints' => array(
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]+',
),
'defaults' => array(
'controller' => 'Security\Controller\Security',
'action' => 'index',
),
),
),
),
),
'view_manager' => array(
'template_path_stack' => array(
'security' => __DIR__ . '/../view',
),
),
);
I had the same problem while following the skeleton application tutorial (Getting started: A skeleton application). Whenever I would go to the album url in the browser (ZendSkeletonApplication/public/album in my case), I would get a 404 error page but no details on why I got the 404. It wasn't clear to me how I would be able determine why I was getting the 404 when I had double checked everything and was pretty sure I copied and configured the Album module properly. It turned out that I was missing a slash in my route (module.config.php). For example I had 'route' => 'album[/:action][/:id]' instead of 'route' => '/album[/:action][/:id]'.
I was only able to figure it out by intentionally causing errors by misspelling things like making the 'Album\Controller\Albums' instead of 'Album\Controller\Album'in the invokables value, this would cause a stack trace to display which then showed the ZF2 classes that where called on the request. I would continue to misspell, test, and then correct each part of the module.config.php until I was given a clue to what part of the configuration was causing the error.
I'm pretty sure this was not the best way to debug an application's configuration.
There is few things that need to be make sure is:-
You have to add your module in
application.config.php (which you are saying you done it.)
Security\Controller\Security has to be same in default too (which you already has)
One more thing is Your folder structure....
-
Just to doulbe check you have a /MODULE/src/MODULE/Controller/CONTROLLER_FILE_NAME.php
I hope that helps..
I know it is an old post. However another thing to make sure you have in the modules top directory (same directory as the Module.php file) is the "autoload_classmap.php"
file with "<?php return array();?>" inside of it.
A simple tip to know whether your rule has already added correctly to the routes or not, you may check the routes value in the config file inside any working module, as following:
$config = $this->serviceLocator->get('config');
var_dump($config);
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.
I tried this:
Route::set('default_controllers', '(<controller>(/<action>(/<id>)))')
->defaults(array(
'controller' => 'welcome',
'action' => 'index',
));
Route::set('default', '<uri>')
->defaults(array(
'controller' => 'cms',
'directory' => 'cms',
'action' => 'render',
));
But actually I want the 'default' (with the render action) to come first than the default_controllers.
I want it to first check any controllers, and if there is nothing then it should run the second default, render. Render checks the uri in the database and returns the page if exists or else it throws a error.
If i switch on the two's route position, so the 'default' route come before 'default_controllers' then it works fine with the cms pages, but not with the controllers (since it does not look for further routes, after the render function has thrown an error that the page does not exists.)
What do i do here? How can i make them both work?
You basically have two catchall routes here. You should remove one of them, and make your routes more specific. The (<controller>(/<action>(/<id>))) route is actually very bad, and is only provided as an example.
To get this to work, you have to specifically tell the route which controllers to load.
Route::set('default_controllers', '(<controller>(/<action>(/<id>)))', array(
'controller' => 'controller|anotherController|etcController'
))
->defaults(array(
'controller' => 'welcome',
'action' => 'index',
));
If you wanted to, you could write a class to go look for the controllers and cache the result as to not increase load times. You'd then pass this value into the value for the controller key in the array.
Your other route can remain how you had it:
Route::set('default', '<uri>')
->defaults(array(
'controller' => 'cms',
'directory' => 'cms',
'action' => 'render',
));
I have an application that is essentially working until I tried to implement an Auth module for logins and registrations.
My application directory structure is basically:
application
-- classes
-- controller
-- admin
(admin area)
-- block
(blocks to display within pages)
-- page
(default pages)
By default I want to have URL's such as http://www.testsite.com/test which would access the Controller_Page_Test class. Or to explicitly call admin or block pages http://www.testsite.com/admin/test which would access the Controller_Admin_Test class. To further complicate matters it also needs to handle optional actions and id's.
I said at the top that this is basically working correctly - until I've tried to add in the Auth module. The Auth module calls http://www.testsite.com/user/login but instead of accessing the module's path via the default, it looks in the page directory.
To overcome this I placed a higher level route but now this has become my default page handler. Explicit calls still get through.
My routes currently look like this:
Route::set('user', '(<controller>(/<action>(/<id>)))', array('controller' => 'user|admin_user'))
->defaults(array(
'controller' => 'user',
'action' => 'index',
'id' => NULL,
));
Route::set('with_dir', '<directory>/<controller>(/<action>(/<id>))', array('directory' => 'block|admin'))
->defaults(array(
'directory' => 'page',
'controller' => 'home',
'action' => 'index',
));
Route::set('just_id', '<controller>(/<id>)', array('id' => '\d+'))
->defaults(array(
'directory' => 'page',
'controller' => 'home',
'action' => 'index',
));
Route::set('auto_dir', '<controller>(/<action>(/<id>))', array('id' => '\d+'))
->defaults(array(
'directory' => 'page',
'controller' => 'home',
'action' => 'index',
));
Route::set('default', '(<controller>(/<action>(/<id>)))')
->defaults(array(
'controller' => 'prototype',
'action' => 'index',
));
Can this be cleaned up any better? And how do I get this module to only kick in when I need it to?
Yes, it can be cleaned better. Kohana developers encourage people using this framework to add as much routes as needed. You can even specify them for each action which will enable you to change URLs in the future (eg. instead of /user/login you may wish to have /signin), if you use proper methods to generate links etc. (eg. Route::url() helper).
Now, saying that, here is the other way to specify the user route:
Route::set('user', '<controller>(/<action>(/<id>))', array('controller' => '(user|admin_user)'))
->defaults(array(
'controller' => 'user',
'action' => 'index',
));
Which will match only the requests, where the first part of the URI is given and is equal either to user or admin_user. Previously the controller part was optional, thus was also matching calls to / URI.