Zend Route Regex and invalid controller - zend-framework

php i have method to add routes:
public function addRoutes()
{
$front = Zend_Controller_Front::getInstance();
$redirect = $front->getRouter();
$router = new Zend_Controller_Router_Route_Regex(
"p\/(a-zA-Z0-9)\.htm",
array(
'controller'=>'page',
'action'=>'index',
1=>'ja.htm'
),
array( 1 => 'page_name')
);
$route2 = new Zend_Controller_Router_Route_Regex("(a-zA-Z0-9)\.html",
array('controller'=>'page',
'action'=>'index',
1=>'ja.html'),
array(1=>'page_name'));
$redirect->addRoute('pages',$router);
$redirect->addRoute('hmtmled',$route2);
$front->setRouter($redirect);
}
I tried to enter url like: p/ja.htm but i get error: Invalid controller specified (p). I know its for reason of default route, but how to change that?

Is that method part of your Bootstrap class? If so, are you sure it is being run? Remember, the Bootstrap methods that get called automatically are those of the form _initXXX() (note the leading underscore).
Also, as #Tim Fountain astutely notes in the comments, the regex needs to be:
p/([0-9A-Za-z]+)\.htm

you try to remove the default routes:
//excerpt from ZF reference 24.5.4. Default Routes... If you do
not want this particular default route in your routing schema, you may
override it by creating your own 'default' route (i.e., storing it
under the name of 'default') or removing it altogether by using
removeDefaultRoutes():
// Remove any default routes
$router->removeDefaultRoutes();

Related

how to make optional parametres in zendframework URL

I am new to Zend, but very very keen to learn. This is really just a quick question on routing in Zend Framework.
I understand the basic of it but I am still confused about how I can create some optional parameters at the end of my URL. For example, I have the following default page URL:
examplesite.com/accounts/enquiry
I now want to add two additional parameters to it i.e:
userid= 6
location= 12
So, the eventual URL should look like:
examplesite.com/accounts/enquiry/6/12
but
examplesite.com/accounts/enquiry
Will get you to the same page.
I am not clear. How do it do this? I mean, this is not a bespoke URL. so, I don't need to create a custom route. It basically just the last two parameters that need to be added to the page.
How do I do this?
First 2 parameters are controller and action name, the named params.
Here you are:
examplesite.com/accounts/enquiry/userid/6/location/12
or you can define your own route like this:
$route = new Zend_Controller_Router_Route('accounts/enquiry/:userid/:location);
and then add it to router:
$router->addRoute('accounts', $route);
You could add a custom route inside your Bootstrap.php, e.g. (untested):
protected function _initRoutes()
{
[...]
$frontController = Zend_Controller_Front::getInstance();
$router = $frontController->getRouter();
$accounts = new Zend_Controller_Router_Route(
'accounts/enquiry/:userid/:location',
array(
'userid' => '[0-9]{2}',
'location' => '[0-9]{2}',
'controller' => 'accounts',
'action' => 'enquiry',
)
);
$router->addRoute('accounts', $accounts);
[...]
}
http://framework.zend.com/manual/1.12/en/zend.controller.router.html

zend framework get id in /delete/2

I'm actually using zend, and I wonder how to get the id in such url :
/delete/2
I know I can do it using :
// if URL is /delete/id/2
$request->getParam('id');
But what I want is to have url like the first one /delete/2 which sounds more logical to me.
Ideas?
Thanks for your help
I think you should be able to solve this kind of problem using routes. You can create a route for
/delete/2
by adding this to for example your config.ini file:
[production]
routes.delete.route = "delete/:id"
routes.delete.defaults.controller = delete
routes.delete.defaults.action = index
routes.delete.id.reqs = "\d+"
Here you specify the URL to match, in which words starting with a colon : are variables. As you can see, you can also set requirements on your variables regex-style. In your example, id will most likely be one or more digits, resulting in a \d+ requirement on this variable.
This route will point the url to the index action of the delete controller and sets id as a GET-var. You can alter this .ini code to suit your specific needs.
The routes can be added by putting the following code inside your bootstrap:
$config = new Zend_Config_Ini('/path/to/config.ini', 'production');
$router = new Zend_Controller_Router_Rewrite();
$router->addConfig($config, 'routes');
See the docs for more information: here for the general documentation and here for the .ini approach I just described.
Try this: add the following function to your Bootstrap.php
protected function _initRoute(){
$this->bootstrap ('frontcontroller');
$front = $this->getResource('frontcontroller');
$router = $front->getRouter();
$deleteRoute = new Zend_Controller_Router_Route(
'delete/:id',
array(
'controller' => '{enter-your-controller-name-here}',
'action' => '{enter-your-action-name-here}'
)
);
$router->addRoute('delete', $deleteRoute);
}
Don't forget to replace {enter-your-controller-name-here} with controller name and {enter-your-action-name-here} with action name.
With this code added, $request->getParam('id'); should work just fine.

Have a default controller in Zend

I have a module-based arhitecture in Zend Framework 1.11 (site.com/module/controller/action).
I've setup my site to have a default module, so that if I have the site module as default, and you go to site.com/something1/something2, it will actually take you to site.com/site/something1/something2.
I want to achieve the same thing 1 level further: say if you go to site.com/something, it should take you to site.com/site/index/something. I'm not talking about a redirect, just a re-routing.
Would something like this be possible?
If I understand correctly, it is possible and here is an example you can put in your Bootstrap:
protected function _initControllerDefaults()
{
$this->bootstrap('frontcontroller');
$front = Zend_Controller_Front::getInstance();
// set default action in controllers to "something" instead of index
$front->setDefaultAction('something');
// You can also override the default controller from "index" to something else
$front->setDefaultControllerName('default');
}
If you need the default action name to be dynamic based on the URL accessed, then I think you are looking for a custom route. In that case try:
protected function _initRoutes()
{
$router = Zend_Controller_Front::getInstance()->getRouter();
// Custom route:
// - Matches : site.com/foo or site.com/foo/
// - Routes to: site.com/site/index/foo
$route = new Zend_Controller_Router_Route_Regex(
'^(\w+)\/?$',
array(
'module' => 'site',
'controller' => 'index',
),
array(1 => 'action')
);
$router->addRoute('actions', $route);
}

Full dynamic router in Zend Framework

By default you have the following URL-syntax in ZF: /module/controller/action. What i want, is to build an menu-system where i can use any URL I want.
Lets say I make an menu-item called 'news'. When i call http://www.site.com/news i want to have the folowing loaded:
module: news
controller: frontpage
action: display
These config-values must be configured in the database-record for the menu-item.
How can I do this in zend? I spend a lot of time searching for it, but I still can't figure out how to. Does anybody?
I'd suggest using a front controller plugin to scan your database for all the entries, create routing rules based on those entries and add them to the router (see this).
Of course caching strategy is recommended so that you don't do a lot of processing on every request.
You can create a plugin and in routeStartup define something that intercept your request and route /module/controller/action to /action, but for this all your action names must be unique :
class My_CustomRouterPlugin extends Zend_Controller_Plugin_Abstract
{
public function routeStartup(Zend_Controller_Request_Abstract $request)
{
$fc = Zend_Controller_Front::getInstance();
$action =$fc->getRequest()->getActionName();
$router = $fc->getRouter();
$model= new myModel();
$myPage = $model->getPageByAction($action);
$route = new Zend_Controller_Router_Route('/action', array(
'module' => $myPage->getModule();
'controller' => $myPage->getController();
'action' => $action;
));
$router->addRoute($action, $route);
return $router;
}
}
In myModel define a method can get you an object(or an array) that contains module, controller names (from you DB ).
and register this plugin in your bootstrap:
$front->registerPlugin(new My_CustomRouterPlugin());

Hostname and Custom routing in Zend Framework don't work together for me

I am building an application that uses hostname routing to detect subdomains like
user1.example.com
user2.example.com
and also have custom routes like user1.example.com/login
This works well so far, however when I add custom routes they do not work. I have searched and read a lot but seems there is something I am missing. Here is what I have so far:
//my routes in routes.ini
[development]
routes.login.type = "Zend_Controller_Router_Route"
routes.login.route = "/login"
routes.login.defaults.controller = "user"
routes.login.defaults.action = "login"
//This part in Bootstrap file
$this->bootstrap('frontController');
$router = $this->frontController->getRouter();
$routerConfig = new Zend_Config_Ini(
APPLICATION_PATH . '/configs/routes.ini',
'production'
);
//I create a default route
$routeDefault = new Zend_Controller_Router_Route_Module(
array(),
$this->frontController->getDispatcher(),
$this->frontController->getRequest()
);
$router->addConfig($routerConfig, 'routes');
// hostname route
$hostnameRoute = new Zend_Controller_Router_Route_Hostname(
':username.mysite.com',
array(
'module' => 'default',
'controller' => 'index',
'action' => 'index',
)
);
//I add the default route.
$router->addRoute('default', $routeDefault);
//I chain the routes so that all routes have subdomain routing too
foreach ($router->getRoutes() as $key => $theroute) {
$router->addRoute($key, $hostnameRoute->chain($theroute));
}
When I go to a custom route like http://user1.example.com/login I get the error: 'Invalid controller specified (login)' which means my custom route is not being recognized. I am also not sure if the way I am adding the default route is correct and necessary. If I remove that code then it doesn't work. So my problem really is that I would like my hostname matching, custom routes and default routes to all work. If you can spot where I'm going wrong please help, I have read previous related posts all over on routes, chaining, default routes etc (including this very related one: How do I write Routing Chains for a Subdomain in Zend Framework in a routing INI file?) but haven't found the solution so far.
You should be able to setup your routing using a custom param in the route:
routes.testdynamicsubdomain.type = "Zend_Controller_Router_Route_Hostname"
routes.testdynamicsubdomain.route = ":subdomain.domain.dev"
routes.testdynamicsubdomain.defaults.module = public
routes.testdynamicsubdomain.defaults.controller = index
routes.testdynamicsubdomain.defaults.action = index
If your apache/hostfile etc are configured correctly going to test.domain.dev should load the index action in your indexController where you could get the :subdomain param:
echo $this->getRequest()->getParam('subdomain');
Also, as you discovered, the order of the routes is very important. See also Zend Router precedence for more info about this.