I'm using Zend FW 1.9.2, want to disable the default routes and supply my own. I really dislike the default /:controller/:action routing.
The idea is to inject routes at init, and when the request cannot be routed to one of the injected routes it should be forwarded to the error controller. (by using the defaultly registere Zend_Controller_Plugin_ErrorHandler)
This all works fine, until I disable the default routes with $router->removeDefaultRoutes();
When I do that, the error controller no longer routes unrouted requests to the error controller. In stead, it routes all unrouted requests to indexAction on the default controller.
Anyone have any idea how to disable the default /:controller/:action routing but KEEP the route error handling?
Basically, this is what I do:
$frontController = Zend_Controller_Front::getInstance();
$router = $frontController->getRouter();
$router->removeDefaultRoutes(); // <-- when commented, errorhandling works as expected
$route = new Zend_Controller_Router_Route_Static(
'',
array('controller' => 'content', 'action' => 'home')
);
$router->addRoute('home', $route);
The problem when you remove the default routes is that Zend no longer understands the urls /:module/:controller/:action, so whenever a route is sent, it gets routed to the default Module, index Controller, index Action.
The Error plugin works on the postDispath method of the controller dispatch and it works because in the standard router if the controller, or module, or action isn't found it throws a error.
To enable custom routes in this config you must write a new plugin that works on the preDispatch, and check if the route and then redirect to the error plugin in the event it's a invalid URL.
When you remove the default routes, you remove the default route that the error handler plugin utilizes. This means that when it tries to route to
array('module' => 'default, 'controller' => 'error', 'action' => 'index')
none of your routes match this setup. Thus it'll fail. I suppose you could add just this route from the default like so:
$frontController = Zend_Controller_Front::getInstance();
$router = $frontController->getRouter();
$router->removeDefaultRoutes(); // <-- when commented, errorhandling works as expected
// Re-add the error route
$router->addRoute(
'error',
new Zend_Controller_Router_Route (
'error/:action',
array (
'controller' => 'error',
'action' => 'error'
)
)
);
$route = new Zend_Controller_Router_Route_Static(
'',
array('controller' => 'content', 'action' => 'home')
);
$router->addRoute('home', $route);
I encountered the same issue for an old application, here is what solved my problem:
$front = Zend_Controller_Front::getInstance();
$router = $front->getRouter();
$router->removeDefaultRoutes();
// forward all routes to the not found error action
$route = new Zend_Controller_Router_Route('*', array('controller'=>'error', 'module'=>'error', 'action'=>'notfound'));
$router->addRoute('default', $route);
// After that add your routes.
$route = new Zend_Controller_Router_Route_Static('', array('controller' => 'content', 'action' => 'home'));
$router->addRoute('home', $route);
You need to add this route first as it needs to be the last processed.
And in ErrorController I defined:
public function notfoundAction()
{
throw new Zend_Controller_Action_Exception('This page does not exist', 404);
}
This way any route that is not matched to our routes will use the default error handler.
Related
I am using Zend Framework version 1.12.16. I have created two modules i.e. user and admin. I have set user module as my default module by enabling it in application.ini:
resources.frontController.moduleDirectory = APPLICATION_PATH "/modules"
resouces.modules[]=
resources.frontController.defaultModule = "user"
So, whenever users the name of the site in the url he is automatically taken to index action of indexController in user module. Similarly, I want the user to be taken to index action of the loginController of admin module whenever user types in http://example.local/admin. Can I achieve that using some settings in application.ini ?
Zend only allows for a single definition of default module/controller/action. Behind the scenes, this creates a default route in Zend's routing system for you. Routing is the key for your problem. To match your case, you could of course do some dynamic/placeholder/whatever overkill, but a simple static route is all you need actually. This can look like that:
$route = new Zend_Controller_Router_Route_Static(
'admin',
array('module' => 'admin', 'controller' => 'login', 'action' => 'index')
);
$router->addRoute('admin', $route);
Thanks Jossif!! I completely forgot this option. Adding the following method in Bootstrap.php class resolved my problem.
protected function _initRoutes()
{
$frontController = Zend_Controller_Front::getInstance();
$router = $frontController->getRouter();
$route = new Zend_Controller_Router_Route_Static(
'admin',
array(
'module' => 'admin',
'controller' => 'login',
'action' => 'index'
)
);
$router->addRoute('admin', $route);
}
In my project I have some pages defined in my index controller, like ie. the About us page. In order for me not to have to type domain.com/index/about but domain.com/about I have this route:
$route = new Zend_Controller_Router_Route_Static ( 'about', array (
'controller' => 'Index',
'action' => 'about'
) );
$router->addRoute ( 'about', $route );
It does the job. The problem is that sometimes I have 6 or 7 pages and I have to repeat this route 6 or 7 times. Is there a way for me to do a route that would always remove "index" from the url? I would never need a url that has index in it. Thanks!
You can write dynamic routes by avoiding the static route type:
$route = new Zend_Controller_Router_Route(
'/:action',
array (
'controller' => 'index',
'action' => 'index',
)
);
$router->addRoute('pages', $route);
This will add a route called 'pages' that will match any single action in the index controller. The action and controller defined in this route are merely the defaults and as you are not passing the controller as a variable it will always route to the IndexController. The action will default to indexAction but can be overridden by the route, ie:
/about -> IndexController / aboutAction
/contact -> IndexController / contactAction
etc ...
Bear in mind this will override any other routes so you need to structure your routing heirachy properly. Routes defined later in the process will override routes already defined.
For more information check the docs: Zend Framework Standard Router
I try to use a router with phalcon. This is how it is included in index.php right after registering the 'events manager':
$di->set('router', function(){
require __DIR__.'/../app/config/routes.php';
return $router;
});
and this is how the routes.php looks like:
<?php
$router = new Phalcon\Mvc\Router(false);
$router->add("/", array(
'controller' => 'index',
'action' => 'index'
));
$router->add("/topics", array(
'controller' => 'wurst',
'action' => 'index'
));
$router->handle();
return $router;
The website reacts as if the router was not existent. /topics and topics say this:
TopicsController handler class cannot be loaded
and I also cannot use a die("test"); function inside routes.php . nothing happens.
I also tried to activate it without a separate file, but the result was the same :(
(The sample web-application INVO was used as starting point for my site )
$router->setUriSource(Router::URI_SOURCE_SERVER_REQUEST_URI); will use default $_SERVER['REQUEST_URI']
If your index/index action is working when you access domain.com/index.php, check that you are using proper uri source, if using nginx or php built-in server you might have some problems with routing and $_GET['_uri'] which phalcon use for handling uris.
can find more about it on phalcon router documentation about uri sources -> http://docs.phalconphp.com/en/latest/reference/routing.html#uri-sources
now it seems to work:
Action 'route404' was not found on handler 'index'
the problem was , that I put the function to set the router in index.php within "set dispatcher function". ..did not see the closing braces.
I need to Add the route to Zend Framwork Application.
I want to display All the Posts from the database where catagory = the controller name
domain.com/action
domian.com/drama
domain.com/thriller
How can i do this ? I gone through the ZF Routes Documentation. But found No Solution.
To be able to do this, you will have to put something like this in your application.ini
resources.router.routes.category.type = "Zend_Controller_Router_Route"
resources.router.routes.category.route = ":category"
resources.router.routes.category.defaults.module = "default"
resources.router.routes.category.defaults.controller = "index"
resources.router.routes.category.defaults.action = "index"
This way, everything that didn't match as a valid controller will be directed as category parameter in index controller index action. Keep in mind to handle invalid category names and trigger 404.
Also, here's a good article about tricks and tips in application.ini
This can be done using addRoute() method in the bootstrap.php file
// Retrieve the front controller from the bootstrap registry
$FrontController = $this->getResource('FrontController');
$router = $FrontController->getRouter();
$router->addRoute('genre',
new Zend_Controller_Router_Route(
':genre',array( 'controller' => 'index' , 'action' => 'index' )) );
To get the Genre in the Controller
echo $this->getRequest()->getParam('genre')
I have the following code in my PortfolioController:
function index()
{
$this->set('posts', $this->Portfolio->find('all'));
}
function view ( $id, $slug )
{
$post = $this->Portfolio->read(null, Tiny::reverseTiny($id));
$this->set(compact('post'));
}
However in order to get the view to remove /view/ from the URL, I have added the following to my routes: Router::connect('/portfolio/*', array('controller' => 'portfolio', 'action' => 'view'));
This breaks the index method as it overrides it by calling the view method instead and shows a blank view
How do I fix this?
What are you trying to do exactly? (And what's with $slug?)
It sounds like what you want to do is remove the action (or at least the view() action?) from displaying in the URL, amirite? Kind of like the default pages_controller display() method - catch-all action for static pages?
How do I fix this?
Well, I'd suggest starting with un-breaking that route, because otherwise it's doing exactly what you told it to:
Router::connect('/portfolio/*',
// * is a wildcard matching anything & everything after /portfolio/
array('controller' => 'portfolio',
// and routing to portfolio's view() action, with or w/o required $args to pass
'action' => 'view'));
so what you see when you call index() is not a blank view, it's a suppressed fatal error, which is what happens when index() reroutes to view() and doesn't have an $id to pass in for the first arg.
Note the ending DS. Route order matters; first rule that catches, wins. The following routes would all map to index by default if the url's action were omitted, but they're not the same.
// Targets inside the controller (its methods)
Router::connect('/portfolio/',
array('controller' => 'portfolio', 'action' => 'index'));
is not the same as
// Targets the controller
Router::connect('/portfolio',
// Specifies the default controller action, can be whatever
array('controller' => 'portfolio', 'action' => 'index'));
For what you're trying to do, it should be
// Targets the controller
Router::connect('/portfolio',
// Routes to 'controller default method' which is index() by Cake default
array('controller' => 'portfolio');
This allows Cake to enforce auto default mapping to the controller's index() whenever the action is missing from the URL.
It would still have worked except for the trailing DS and trailing asterisk. The same rule that should catch index() reroutes to view() instead, thanks to the trailing asterisk targeting all actions in portfolio.
Hence Foo's suggestion doesn't work -> trailing DS + wildcard:
Router::connect('/portfolio/',
// the trailing DS changes it to target 'inside portfolio' instead of 'portfolio'
array('controller'=>'portfolio', 'action'=>'index'));
// trailing arbitrary wildcard maps any / all actions directly to view() method
Router::connect('/portfolio/*',
array('controller' => 'portfolio', 'action' => 'view'));
Which just ensures ALL actions in portfolio map directly to portfolio view() method (including /portfolio/index action). Do not pass go, etc. Any portfolio action resolves to the wildcard no matter what, aliasing the whole controller to that method. So you could knock the DS off the first route but any url starting with /portfolio that isn't /portfolio would still route to view(). Including the url /portfolio/index.
Try this:
// catches portfolio/index() without index in the url
Router::connect('/portfolio',
array('controller' => 'portfolio'));
// maps to portfolio/view() without view in url, just /portfolio/integer id
Router::connect('/portfolio/:id',
array('action'=>'view', array('id' => '[0-9]+'));
// routes everything else in portfolio as usual
Router::connect('/portfolio/:action/*',
array('controller'=>'portfolio'));
Routes can be tricky. Here are some links; HTH. :)
http://bakery.cakephp.org/articles/Frank/2009/11/02/cakephp-s-routing-explained
http://book.cakephp.org/view/46/Routes-Configuration
I'm new to CakePHP myself, but I believe you can add
Router::connect('/portfolio/', array('controller' => 'portfolio', 'action' => 'index'));
Before the route with the star.
as per my knowledge is concern
you should give like this:
Router::connect('/pages/*', array('controller' => 'pages', 'action' => 'display'));
I mean you should changes the aliases of the controller name.
Router::connect('/portfolios/*', array('controller' => 'portfolios', 'action' => 'view'));