I understand how to create a simple custom route in the form of
example.com/archive/:year
However, I need to create a route in the form of
example.com/:make/:model
Both path components are variables. At the same time I want to keep the default Zend Framework routing. How would I go about this?
Thanks
Not for zend, but the technique is instructive and will probably work. I've struggled with this problem too, but was more for internationalisation.
http://darrenonthe.net/2011/05/06/dynamic-routing-from-database-in-codeigniter/
Basically, you cache your routes into a file, and the framework matches them to your controller/variable details. I tried lots of things, complex regexes, and in the end, this worked out really, really well. Might be a good solution for you too.
if you are using a module based file architecture, you can maintain the zend framework default routes, and add custom routes for your modules.
for example
class Example_Bootstrap extends Zend_Application_Module_Bootstrap
{
public function _initModuleRoutes()
{
$this->bootstrap('FrontController');
$frontController = $this->getResource('FrontController');
$router = $frontController->getRouter();
$route = new Zend_Controller_Router_Route(
'modulename/:action/*',
array(
'module' => 'modulename',
'controller' => 'modulecontroller',
'action' => 'index'
)
);
$router->addRoute('routename', $route);
return $router;
}
You need to enforce some condition i.e model is integer type or something else . Like this
$route = new Zend_Controller_Router_Route(
':make/:model',
array(
'controller' => 'car',
'action' => 'logic'
),
array('make' => '\d+')
);
If you cannot distinguish them with extra condition like these then how software gone do this for you weather its action name or make ?
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);
}
So I've been reading a ton of stackoverflow and phalcon forum threads.. (I'm starting to hate this framework), but nothing seem to work and it doesn't explain why like Laravel does, for example.
I'm just trying to be able to operate with this application structure:
As you can see, all I want is to use namespaced controllers in subfolders to make more order for my code.
According to all explanations, here's my loader.php:
<?php
$loader = new \Phalcon\Loader();
/**
* We're a registering a set of directories taken from the configuration file
*/
$loader->registerDirs(
array(
$config->application->controllersDir,
$config->application->modelsDir,
$config->application->pluginsDir
)
)->register();
AFAIK, Phalcon should traverse all subfolders for not found classes when used via registerDirs.
Then I define my routes to specific controller after the main route to index controllers in base directory:
<?php
$router = new Phalcon\Mvc\Router(false);
$router->add('/:controller/:action/:params', array(
'namespace' => 'App\Controllers',
'controller' => 1,
'action' => 2,
'params' => 3,
));
$router->add('/:controller', array(
'namespace' => 'App\Controllers',
'controller' => 1
));
$router->add('/soccer/soccer/:controller', array(
'namespace' => 'App\Controllers\Soccer',
'controller' => 1
));
$router->add('/soccer/:controller/:action/:params', array(
'namespace' => 'App\Controllers\Soccer',
'controller' => 1,
'action' => 2,
'params' => 3
));
return $router;
And one of my controllers look like:
<?php namespace App\Controllers\Soccer;
use App\Controllers\ControllerBase as ControllerBase;
class IndexController extends ControllerBase
{
public function indexAction()
{
}
}
What's wrong here? Default top namespace is not registered? Am I missing something?
This just doesn't work. When I try to open myserver.com/soccer which I expect to go to app/controllers/soccer/IndexController.php, but instead it tells me:
SoccerController handler class cannot be loaded
Which basically means it's looking for SoccerController.php in /controllers directory and totally ignores my subfolder definition and routes.
Phalcon 1.3.0
Stuck on this for a week. Any help - Much appreciated.
I was having a problem with loading the ControllerBase and the rest of the controllers in the controllers folder using namespaces. I was having a hard time since other example projects worked fine and I realized that I was missing a small detail in the despatcher declaration where I was supposed to setDefaultNamespace
(ref: https://github.com/phalcon/vokuro/blob/master/app/config/services.php)
$di->set('dispatcher', function () {
$dispatcher = new Dispatcher();
$dispatcher->setDefaultNamespace('App\Controllers');
return $dispatcher;
});
or you can specify it directly on the routing declaration file like this
$router->add("/some-controler", array(
'namespace' => 'App\Controllers'
'controller' => 'some',
'action' => 'index'
));
that should work as well, it might be a bit confusing at first with namespaces but once you get a hang of it you will love this extremely fast framework
It looks like your namespaces have capitals
App\Controllers\Soccer
and your folder structure does not
app\controllers\soccer
In my app I have controllers with a namespace and I have just tried changing the case of the folders so they don't match and I get the missing class error.
Of course it does raise a question, how many controllers are you planning on having that namespacing them is worthwhile? Are you grouping controllers and action by function or content? I used to have loads of controllers in Zend, but now I have grouped them by function I only have 16 and I am much happier. e.g. I suspect soccer, rugby, hockey etc will probably be able to share a sport controller, articles, league positions etc will have a lot of data in common.
ps Don't give up on Phalcon! In my experience it is sooo much faster than any other PHP framework I have used it is worth putting up with a lot :)
Are you sure Phalcon traverses subfolders when registering directories to the autoloader? Have you tried adding a line to your autoloader which explicitly loads the controllers\soccer directory?
Alternatively, if your soccer controller is namespaced, you can also register the namespace: "App\Controllers\Soccer" => "controllers/soccer/" with the autoloader.
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')
Very likely I'm going about this in the wrong way entirely. I'm completely new to the framework..
The site I am developing has two "parts" that are mainly separate. An informational/community half, and a commerce half. I'm using the following directory structure:
--application
----default
------controllers
------layouts
------models
------views
----store
------controllers
------layouts
------models
------views
--config
--library
--public
I would like to have a URL structure when browsing for products as follows:
/view/category/model/revision
This would pull up a specific product/revision - but I would like to back-track as well (browsing all revisions, all models, etc). I can't figure out how to achieve this.. My route is setup like this:
Bootstrap.php
$front = Zend_Controller_Front::getInstance();
$router = $front->getRouter();
$route = new Zend_Controller_Router_Route(
'view/:cid/:sku/:rev',
array('module' => 'store', 'controller' => 'index', 'action' => 'index')
);
$router->addRoute('view', $route);
This works fine for pulling up a specific product, but throws an exception (it reverts to the default module and complains that the controller 'view' does not exist) when leaving out any of the 3 labeled parameters. Is it possible to put in optional labels, where it would continue to use the view controller under the store module for 1-3 parameters? Am I missing the point?
I found nothing in the framework docs, but I wouldn't be surprised if I just couldn't find the page.. There's something about the Zend Framework documentation that drives me crazy.
Thank You
I'm not really a ZendFramework guy, but it's obvious the missing parameters are causing the issue. Routes are matched in reverse order. Could it be passing a NULL value to the view when 3 parameters are passed and it is expecting 4?
What if you tried something like:
$route = new Zend_Controller_Router_Route(
'view/:cid/:sku/:rev',
array('module' => 'store', 'controller' => 'index', 'action' => 'index', 'cid' => 0, 'sku' => 0, 'rev' => 0)
);
It should pass default values if they are not provided.
Here is my specific issue. I want to make an api level which then under that you can select which method you will use. For example:
test.com/api/rest
test.com/api/xmlprc
Currently I have api mapping to a module directory. I then setup a route to make it a rest route. test.com/api is a rest route, but I would rather have it be test.com/api/rest. This would allow me later to add others.
In Bootstrap.php:
$front = Zend_Controller_Front::getInstance();
$router = $front->getRouter();
$route = new Zend_Controller_Router_Route(
'api/:module/:controller/:id/*',
array('module' =>'default')
);
$router->addRoute('api', $route);
$restRoute = new Zend_Rest_Route($front, array(), array(
'rest'
));
$router->addRoute('rest', $restRoute);
return $router;
In application.ini:
resources.frontController.moduleDirectory = APPLICATION_PATH "/modules"
I know it will involve routes, but sometimes I find the Zend Framework documentation to be a little hard to follow.
When I go to test.com/rest/controller/ it works how it should, but if I go to test.com/api/rest/ it tells me that my module is api and controller is rest.
You might actually want to do something like api/:controller/:action.json or api/:controller/:action.xml (i've seen alot of API's do this, ex: Twitter).
To achieve this you can do something like this:
$front = Zend_Controller_Front::getInstance();
$router = $front->getRouter(); // returns a rewrite router by default
$router->addRoute(
'json_request',
new Zend_Controller_Router_Route_Regex(
'([^-]*)/([^-]*)/([^-]*)\.json',
array(
'controller' => 'index',
'action' => 'index',
'request_type' => 'json'),
array(
1 => 'module',
2 => 'controller',
3 => 'action'
)
));
Then just check your parameter "request-type" and serve the request based on what you have.
You should change your layout to enconde JSON or XML based on your request also.
You would need an API module also with this.
Note: Take care that the bootstrap of a module is added to ALL of your modules currently so you would have this route run in all modules. I am currently checking for a way to fix this so cannot tell you how to do it.
Hope it helped!
Your orginal line was this.
$restRoute = new Zend_Rest_Route($front, array(), array( 'rest' ));
To enable Zend_Rest_Route for specific controllers, add an array of controller names as the value of each module array element.
$restRoute = new Zend_Rest_Route($front, array(), array( 'api' ) => array('rest'));
Also reference
http://framework.zend.com/manual/en/zend.controller.router.html
I hope this may help.