Zend Framework - Optional Router Labels - php

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.

Related

Zend Framework create fully dynamic route while maintaining default routes

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 ?

Zend router, omit controller in URL for single module

I have a module based Zend application.
One of my modules, called portfolio has only one controller, called index. For this single module, I'd like my route to look like this:
$route = new Zend_Controller_Router_Route('portfolio/:action',
array(
'module' => 'portfolio',
'controller' => 'index',
'action' => 'index'
)
);
This works but messes up all links generated through Zend_Navigation.
Can this routing behavior be achieved, without messing up Zend_Navigation? (i.e. only inbound links are routed through this route. Outbound links are generated with the default route)
I can't use mod_rewrite.

Zend_Navigation incompatible with Zend_Router when writing controller/actions?

Novice Zend Framework developer here trying to figure out a simple solution to a Zend Routing problem. I'm sure one of you pros can lend a hand.
I have a website (built in Zend Framework using Zend_Navigation) that contains 75% static HTML page content and a few controllers. Top level navigation is built in Zend_Navigation, looping through partials.
Because of my work I build a lot of sites along these lines (containing lots of static pages) so I want to get this right. I don't want to set up controllers and actions for each and every one of these static pages (there are many) and I wanted to create a solution where I used Zend_Controller_Router_Route to route all static content automatically through to a StaticController whose job it would be to include or render .phtml pages based on a controller/action pairing in the URL from some sort of directory like /layouts/staticpages
Because of SEO and various reasons I don't want to have the controller pairing in the URL for these static pages be visible as /static/page/page1... It has to be "real world descriptions" of the /section/page (eg. advantages/someadvantage )
Here is the problem: Using Zend_Controller_Router_Route can do the job when I set up the correct routes BUT it messes something awful with Zend Navigation... I assume because Zend_Navigaion doesn't play nice with on-the-fly controller/action switching.
Code example:
$router = Zend_Controller_Front::getInstance()->getRouter();
$route = new Zend_Controller_Router_Route('advantages/:page/*',
array('controller' => 'static', 'action' => 'display', 'mode' => 'advantages',
'page' => 'index'));
$router->addRoute('advantages', $route);
This handles the job of switching pages in the "advantages" section well enough, but Zend_Navigation's automatic controller/action writing AND the highlighting of "active" nodes ends up being all screwed up because it now thinks that its controller is "static" and action is "display".
Is Zend_Navigation fundamentally incompatible with Zend_Controller_Router_Route? Is there a better way of doing this single static page controller or handling static content across the board?
Since you are using one controller/action for all static pages, you must customize your Zend Navigation before displaying it.
Check Example 4 in the Zend Documentation.
// the following route is added to the ZF router
Zend_Controller_Front::getInstance()->getRouter()->addRoute(
'article_view', // route name
new Zend_Controller_Router_Route(
'a/:id',
array(
'module' => 'news',
'controller' => 'article',
'action' => 'view',
'id' => null
)
)
);
// a page is created with a 'route' option
$page = new Zend_Navigation_Page_Mvc(array(
'label' => 'A news article',
'route' => 'article_view',
'module' => 'news', // required for isActive(), see note above
'controller' => 'article', // required for isActive(), see note above
'action' => 'view', // required for isActive(), see note above
'params' => array('id' => 42)
));
// returns: /a/42
$page->getHref();

Zend - outputting better module url?

I am currently outputting the url of a particular module like so:
$this->view->url(array('controller'=>'index','action'=>'index','module'=>'somemodule'))
The problem is when I view:
/somemodule/action1/paramid/paramval
The url is showing as:
/somemodule/index/index/paramid/paramval
When all I really want is:
/somemodule/
Any ideas? I have used the above url array because I am trying to force it to display the correct url. sadly, simply array('module'=>'somemodule') doesn't work...
Weird, I would've thought it defaults to index/index if they aren't specified. You could try setting up something with Zend_Controller_Router_Route;
$router = $ctrl->getRouter(); // returns a rewrite router by default
$router->addRoute(
'user',
new Zend_Controller_Router_Route('somemodule',
array('module' => 'somemodule',
'controller' => 'index',
'action' => 'index'))
);
You will however need to set up routes to capture the :id/:val into variables. You can do this with another addRoute(), naming each variable prepending a colon.
$router->addRoute(
'user',
new Zend_Controller_Router_Route('somemodule/:id/:val',
array('module' => 'somemodule',
'controller' => 'index',
'action' => 'index'))
);
Then you should be able to view the module without the index/index in the URL which might fix the problem with the url helper.
More info here http://framework.zend.com/manual/en/zend.controller.router.html

Zend Framework - How do make a hierarchy without it being a module?

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.

Categories