If someone is familier with Zend Framewor, they know what routes are and how they affect the system overall. My question is concerned about ways to can configure this routes. I know two ways to configure them, through Bootstrap.php and application.ini.
However, not hiding the fact that, I am pretty much of a learner in Zend Framework myself, I dont know which one is better and which should be preferred over the other.
Moreover, I do not know, if these are only ways available to configure the router?
So, please tell me what are ways through which we can configure router and which method is better over others.
P.S: I have included the two ways I knew as an answer.
Routing is an configuration which doesn't get change at runtime hence its better to put in configuration file separating from code which is dynamic . Define router in Bootstrap.php if your router depends upon some condition which is dynamic in nature .
Since I am attempting this to be as a guide for those like me, I would like to include the two ways I know of.
Application.ini
resources.router.routes.cat.route = "/browse/:catid/:name/"
resources.router.routes.cat.defaults.controller = index
resources.router.routes.cat.defaults.action = browse
Here What you do is,
resources.router.routes.XXX.route Define the name of the route in place of XXX
catid and name are the two paramters that will taken, when you pass the url is such way /browse/1/pc 1 will be assinged to catid and pc to name
Remaining two line defines the default parameter from controller and action, from MVC
Bootstrap.php
$front = Zend_Controller_Front::getInstance();
// Get Router
$router = $front -> getRouter();
$routeBrowse = new Zend_Controller_Router_Route(
'/browse/:catid/:name',
array(
'controller' => 'index',
'action' => 'index'
)
);
$router -> addRoute('browse', $routeBrowse);
I will avoid the explanation, since pretty much is same as before.
However, I am not sure which one is better that the other one. So, those who knows, update my answer.
Related
I am trying to have a REST design, but I am running in a bit of a problem. I have a resource schedule. Therefore, the normal notation of /schedules/{id} is not very applicable since I would like to have /schedules/{day}/{month}/{year} and then apply REST, and have /edit and such.
Is there a way to do this with Route::resource() ? or do I need to do them through Route::get() ?
As far as I know route::resource only gives you the routes that are detailed in the documentation so for what you want you would need to declare your own route. It is still restful and if it is only one of the resourceful routes you want to change you should still be able to do the following because the routes are prioritized in the order they are declared.
Route::get('schedule/{day}/{month}/{year}/edit', array('as' => 'editSchedule', 'uses' => 'ScheduleController#edit'));
Route::resource('schedule', 'ScheduleController');
Yes, there is a very simple way. Here is an example:
Specify your route like this:
Route::resource("schedules/day.month.year", "ScheduleController");
The request will be like this:
/schedules/day/1/month/12/year/2014
And now you can get all three parameters in show method of your
contoller:
public function show($day, $month, $year)
Hi there this might be handy if you want to call your route by name. Also you can use one or multiple parameters. It works with me on laravel 5.1
According to the laravel docs:
http://laravel.com/docs/5.1/routing#named-routes
Route::get('user/{id}/profile', ['as' => 'profile', function ($id) {
//
}]);
$url = route('profile', ['id' => 1]);
This works with Route:resource aswell.
for example:
Route::resource('{foo}/{bar}/dashboard', 'YourController');
Will create named routes like: {foo}.{bar}.dashboard.show
To call this with the route method, you set it up as followed.
route('{foo}.{bar}.dashboard.show', ['foo' => 1, 'bar'=> 2])
Which will create the url yourdomain.com/1/2/dashboard
Ill hope this is usefull.
Pascal
I'm writing my first community page with Lithium and mongoDB. I really like the schema-less way of mongo, but there is one problem making it impossible working without a schema:
For instance we have a simple form like this:
<?=$this->form->create();?>
<?=$this->form->field('name',array('label' => 'Topic title'));?>
<?=$this->form->field('text',array('label' => 'Content'));?>
<?=$this->form->submit('create');?>
which will be even simpler saved by this:
if($this->request->is('post')) {
$board_post = BoardPosts::create($this->request->data);
$board_post->save();
}
Now it's possible for everyone to add some form inputs by DOM manipulation with Firebug, Developer Tools etc. Of course that it might be some sensless fields in the database, but maybe someone adds a field, that is really used.
The only way to prevent this, is creating a schema in model. But for me this makes the whole idea of a schema-less database useless, doesn't it? And how to make schemas for different situations/actions, when some fields must not occur?
The Model::save() method accepts a 'whitelist' param in its options. See http://li3.me/docs/lithium/data/Model::save()
$whitelist = array(
'title',
'text'
);
$post = BoardPosts::create();
$post->save($this->request->data, compact('whitelist'));
You can also define protected $_schema in your Model and set protected $_meta = array('locked' => true); which will automatically set the whitelist to the fields defined in your schema. However, it is a good idea to define the whitelist in your controller to avoid attacks like you describe.
This problem is called a mass-assignment vulnerability and exists in many frameworks if developers are not careful.
I use modules layout to structure my controllers:
:module/:controller/:action
I would like to add a new custom route so that the following url will work.
domain.com/username
where username is a username of any registered user on the website.
Can anyone point me in the right direction?
Thank you
See this blog post for a detailed explanation of how to do this in ZF:
http://tfountain.co.uk/blog/2010/9/9/vanity-urls-zend-framework
Not sure if you can make something like domain.com/username. Instead you could do domain.com/u/username or domain.com/user/username. For example, to make the second route in you application.ini you could put something similar to the following:
resources.router.routes.user.route = "/user/:user"
resources.router.routes.user.type = "Zend_Controller_Router_Route"
resources.router.routes.user.defaults.module = default
resources.router.routes.user.defaults.controller = user
resources.router.routes.user.defaults.action = user
resources.router.routes.user.defaults.user =
resources.router.routes.user.reqs.user = "\s+"
http://framework.zend.com/manual/en/zend.controller.router.html covers quite well all the different ways you can add routes. Keep in mind, once you add custom routes, the default one will not work anymore unless you explicitly define it (as well as in url view helpers etc.).
I'm trying to implement a REST API to my website.
My problem is that the default Zend routing gets in the way. I've first tried using Zend_Rest_Route but I haven't been able to understand how I was supposed to use it correctly for "deep" routes, aka website/api/resource1/filter/resource2/id.
Using the default Zend routing, I'd need to create a gigantic Resource1Controller to take care of all the possible actions, and I don't think it's the "good" way to do this.
I've tried using Resauce ( http://github.com/mikekelly/Resauce/), creating an api module and adding routes, but I'm not able to get it working correctly :
The patterns I added were :
$this->addResauceRoutes(array(
'api/resource' => 'resource',
'api/resource/:id' => 'custom',
'api/resource/filter' => 'resource-filter',
'api/resource/filter/:id' => 'custom',
));
Which then leads to this :
public function addResauceRoutes($routes) {
$router = Zend_Controller_Front::getInstance()->getRouter();
foreach ($routes as $pattern => $controller) {
$router->addRoute($controller,
new Zend_Controller_Router_Route($pattern, array(
'module' => 'api',
'controller' => $controller
)
)
);
}
Zend_Controller_Front::getInstance()->setRouter($router);
website/api/resource gets me the
Resource1Controller, ok
website/api/resource/filter gets me to the
resource1filterController, ok
website/api/resource/filter/:id gets me to
a custom controller, ok
I'd like for website/api/resource/:id to get me to the same custom controller... But it redirects me to the Resource1Controller.
What solution is there for me to correctly create my API ? Is there a good way to do this with Zend_Rest_Route ?
Edit : Mike,
I felt that it was not appropriate for me to use different controllers since I need the pathes "website/api/resource/:id" and "website/api/resource/filter/:id" to give me almost the exact same result (the only difference is that because the filter is there, I may get a message telling "content filtered" here).
I thought it was a waste creating another almost identical controller when I could've used the same controller and just checked if a parameter "filter" was present.
However, I don't want to use the basic Zend routing since for the path "website/api/resource/filter/resource2" I'd like to have a totally different comportment, so I'd like to use another controller, especially since I'm trying to use Zend_Rest_Action and need my controllers to use the basic actions getAction(), putAction(), postAction() and deleteAction().
Please could you explain why it is you need two URI patterns pointing to the same controller. A better solution might be to use a separate controller for each of the two patterns and move any shared logic into your model.
Forcing a unique controller for each routing pattern was an intentional design decision, so I'd be interested to hear more detail about your use case where you feel this isn't appropriate.
I thought it was a waste creating
another almost identical controller
when I could've used the same
controller and just checked if a
parameter "filter" was present.
Personally, I think it is cleaner to move the shared logic into the model and to keep your controllers skinny. To me it's not wasteful, it's just more organised - it will make your code easier to manage over time.
If you really need to use the same controller you could always use a query parameter instead, that would work fine:
api/resource/foo?filter=true
That URI would be taken care of by the first route ('api/resource/:id' => 'custom') for free.
But please consider using two controllers, I think that is a better approach.
Okay, the reason I didn't get the good controllers was because Resauce uses the controller name as the name of the route, which has to be unique - so second url pointing to "custom" controller couldn't work. Now I'm able to get the files I want :)
So instead of what was previously noted, I use directly the $router->addRoute(); and define new names each times, even if pointing to the same controller.
Example :
$router->addRoute('resource', new Zend_Controller_Router_Route('/api/resources/:id', array('module' => 'api', 'controller' => 'resource')));
$router->addRoute('resourceFiltered', new Zend_Controller_Router_Route('/api/resources/filter1/:id', array('module' => 'api', 'controller' => 'resource', 'filter' => 'filter1'));
Because of the problems I experienced here: Zend_ Controller_ Router_Exception: “xyz” is not specified
I want to have this route:
":module/:controller/:id"
and map it onto this:
":module/:controller/:action/id/$id"
Is there any possibility to do this with Zend Framework? I do not want to forward the browser to that URL. I just want to tell Zend Framework how to handle this route.
As for reasons why I would like to do this, you can find them in that linked SO question.
Yes it is possible. In my application.ini I specify my routes using regex this way:
resources.router.routes.something.type = "Zend_Controller_Router_Route_Regex"
resources.router.routes.something.route = "mymodule/mycontroller/([0-9]+)"
resources.router.routes.something.defaults.module = "mymodule"
resources.router.routes.something.defaults.controller = "mycontroller"
resources.router.routes.something.defaults.action = "myaction"
resources.router.routes.something.map.1 = "id"
I am not familiar with the ":variable" way of defining routes, but you can take from my example the ability to set default controllers, modules, and actions, without the need to explicitly define them in the url.