I'm working on a Zend Framework API and need to follow a particular format for URLs, so I was hoping for some help regarding how to configure the routing correctly.
http://example.com/module/controller/method/actionNameHere
The above URL would need to route to the function actionNameHereAction.
Any help is appreciated.
The beauty of routing is that it gives you the tools for hiding exactly those pieces of information you are putting into your URL.
Apart from that, as far as I know ZF routes by default so that your URL would end up in ...
the action with name method of
the controller with name controller of
the module with name module
So either your example-URL is complicating things or you are almost there.
B/c actionNameHere would be a paramter you could handle in your action with name "methodAction".
But I think you want your URL to look like:
example.com/module/controller/actionNameHere
In order to produce the URLs needed, I ended up creating a custom Dispatcher, as it wasn't in the routing that URLs were being converted from actionNameHere to actionnamehereAction, but in the dispatcher. I extended the standard dispatcher and overrode this behaviour so that the action name in the URL remained case-sensitive.
Related
Coming from a straight PHP and Drupal background, I am recently learning the Symfony2 framework. Currently I am in the routing chapter of the book. This is probably a simple question.
What are some real world use cases for why one would want to generate URLs in a Symfony app? I understand the code but I'm having a bit of trouble determining its practical applications.
I'm referring to this section should you need a refresher.
As always, thank you!
P.S. Symfony is amazing. :)
Basically, you need to generate a URL whenever you need to link to anywhere in your application.
Let's say that you have an application that needs to manage some users. This means that you will probably have URLs like /user/create, /user/edit/(user id) and /user/remove/(user id).
Whenever you display a link to edit a user you need to know on what URL you can find the page that allows you to edit a user. So you need to link to /user/edit/(user id). One solution would be to have this as a fixed link so that in your code you could just write
edit this user
But what if you want to change this URL scheme? Let's say someone is unhappy with the term "user", after all the humans managed by this system are not only users, they are actually "person"s! So now you need to change all the URLs containing "user". Probably there are quite a few places in your app where you have had to hardcode these URLs and now you will need to find and change all of them. Eugh.
But fear not, for Symfony routing comes to the rescue!
Instead of hardcoding these URLs, we can simply let the Symfony router generate them for us. This means that we first need to tell Symfony which routes we have, e.g. by adding the following YAML code to our routes config file:
user_edit:
path: /user/edit/{userId}
defaults: { _controller: AppBundle:User:edit }
requirements:
userId: \d+
This tells our application "Okay, whenever somebody requests a page that looks like /user/edit/{userId}, then you need to call the editAction method in our UserController class in the AppBundle namespace and you need to pass the userId as a parameter. Oh, and also you should only call the controller if userId is a valid integer with at least one number."
So this is how Symfony knows how to map URLs to controllers. But the goodness that comes along with it is that we can use this information for the reverse way as well.
Usually, in our application we do not really care about what the URL looks like for a certain action we want to perform. All we know is that when clicking a certain link, then the browser should jump to a page that allows me to edit a user. And since we just defined a route that takes us right there, we can have Symfony generate the correct URL to achieve just that.
So in your view you can now discard the hardcoded URL from earlier and instead replace it with a route generated by the Symfony router:
edit this user
Now whenever you need to change what the URL actually looks like all you need to do is edit your routing config and not a lot of separate views.
Because, imagine you want to change a given page URL and you've hardcoded it in 10 Twig templates. You will have to modify all these files. On the opposite, when using the routing component:
You would only have to change the URL where the route is defined.
The routing component "takes" care of the current environment you are using (dev, prod...)
Also note that is a bad practice to "switch environment", a typical issue is to hardcode an URL in a Javascript. In this case you can expose your Symfony2 routes in the Javascript by using a bundle like FOSJsRoutingBundle.
I almost immediately realized their use and now I feel silly. :) For those who stop by this question in the future:
Notes about Generating URLs:
Similar to the Drupal l() function, sometimes you need to generate links inside your application based on a variety of parameters.
You don't always want to hardcode your links in case you decide to change paths sometime down the line.
In summary: Think of this as an alternative to using straight anchor tags with href elements all over the app and, instead, keeping things dynamic.
Use case
In the project I'm working I use generateUrl to redirect the user
after creating, editing an entity.
For example after creating a Service entity, I redirect the user to the view
of the just created Service.
Controller
return $this->redirect($this->generateUrl('myentity_view', array('id'=> $id)));
Additional note
In twig files, you can use the path function which call the routing component and generate url with given route name and parameters.
I am trying to build up my routes file and for the application we are building we may have a route such as:
/services/{game}/{id}
Is there a way to have that {game} parameter, but not actually pass it to the controller? Its basically there, but doesn't have to be anything specific and the controller doesn't need to know its there, it's purely for the users eye to make their URL make sense.
That is perfectly possible, you can catch it in the controller without doing anything with it, however you will have to catch it.
Do what Bielco said or just minify your route using slugs instead 2 parameters.
For example:
Game: Skyrim Legendary Edition
Slug (unique): skyrim-legendary-edition
Your route: /services/game/skyrim-legendary-edition
In Laravel routes.php
Route::get('services/games/{slug}', 'ServicesController#showGame');
I have my own routing rules in routes.php, defined for all the pages that should be accessible via URL, such as mywebsite/blog/ and mywebsite/blog/category/category-name, i.e. the structure of my whole website is covered by my custom routes.
Now, I have a lot of elements that make use of requestAction, such as
$websiteabstract = $this -> requestAction(array(
'controller' => 'assets',
'action' => 'displayHomeAbstract'
));
This gives me an error Error: Controller could not be found, probably because I have not defined a route for /assets/displayHomeAbstract. But why do I have to define a custom route for that, when I explicitly state the name of the controller and the action? Shouldn't that bypass the routing altogether?
Either I have not understand Routing at all. Or do I really have to define ALL the possible routes (even those that are only used by requestAction) in my routes.php? I mean, I don't want to allow users to directly access mywebsite/assets/displayHomeAbstract anyway, only via an Element.
Thank you
EDIT: Here is my routes.php http://pastebin.com/aAKBwNZJ
Please have a look at line 128, this is exactly what I do not want since /assets/displayHomeAbstract is ONLY accessed via requestAction.
EDIT: And this is the element, that makes the request: http://pastebin.com/0tK5dYJk
Okay, after extensive discussion with the devs in IRC, I think I understand this well enough to explain to you:
You do have to define your custom routes for your requestAction in this case. requestAction is emulating a full request. It dispatches a request as if accessed using the string url every time, even when the url provided is an array. The book is referring to how when you have a custom route defined in addition to using the default routes (the last line of routes.php), you can use array urls to be agnostic of those routes. However, these array urls rely on the default routes.php in the /lib/ folder and are used to construct a url string. If you're going to have a custom routing pattern, you have to construct the url strings on your own.
Note: the comments below were from earlier versions of this answer.
The key to your problem is understanding the scope of Cake's routing and how it work.
When you define a route in CakePHP, it isn't just used for mapping URLs to controllers. It's also used by the Router for things like generating link addresses and, in your case, mapping the path supplied to requestAction() to a controller. Behind the scenes, Cake is creating a URL string based on your parameters, and then passes it off to the Router to find the correct controller. Since no such route exists, it fails.
As a solution, I would actually recommend not using a controller for that logic. Depending on what it does, a component or a helper may be a better place.
Look at line 156. You commented out the line that loads CakePHP's default routes.
How can I configure Zend_Controller_Router to use the default route by default? For whatever reason unknown, it uses the current route.
This is causing some annoying routing issues, and I don't feel like editing hundreds of links to explicitly use the default route is a reasonable solution to add one custom route.
Your question isn't obvious and is confusing, I will try though.
I am going to assume you do not mean Zend_Controller_Route but in fact are talking about links generated in your views.
You can use baseUrl() like this
About Us
You can set the baseUrl in your Bootstrap like this
Zend_Controller_Front::getInstance()->setBaseUrl("/");
If you are working locally you may want to set it to something like this
Zend_Controller_Front::getInstance()->setBaseUrl("/my-app/public");
Using baseUrl() in your views will now use that path to base all your URLs on. Remember you must wrap your links in baseUrl() for this to work.
The url() helper is not useful for this, this is used for doing things like pagination where you want the current parameters of the request object to be maintained.
Hope that helps.
From Matthew Weier O'Phinney:
The logic you quote above is within
the assemble() method. assemble() may
be called with or without routing
having occurred. By default, the
assumption is that if no route name is
provided, the currently matched route
is utilized -- and if matching was
never performed (or no route matched),
the 'default' route will be used.
The rationale for using the currently
matched route is that typically you
will be routing within the same schema
-- as an example, if you are within a RESTful paradigm, the majority of your
links will be within the current
resource. If we were to follow your
suggestion to utilize the "default"
route when no route is specified (at
least, that's how I interpret what you
said), because the Rest_Route is not
the default route, every single call
to assemble() would require using the
route name -- which others would
deride as causing "headaches."
Personally, I prefer to be explicit
and always specify the route name;
this way I know exactly what route I'm
targetting during assemble(), which
makes debugging easier.
Sounds like the only solution is to set the route for each link to use 'default' instead of leaving it NULL.
I've noticed many sites are able to use a username or page title as an action. How is this done?
For example instead of www.example.com/users/my_username (where the users action is generic and responsible for fetching user data) how could I make this www.example.com/my_username?
Thanks very much.
All modern frameworks follow router ideology. So for this task you just need to write yet another route.
How to do this - is a specific task for particular framework.
In CodeIgniter it would be a route like zerkms said. You can define routs in /system/application/config/routes.php. Here's the CodeIgniter documentation on URI routing. Essentially you take the part of the URL (such as the username) specified in your route as a variable and can do a lookup against your db with it.
With mod_rewrite you could write a rule that redirects www.example.com/user/my_username (or without the user) to www.example.com/user/?name=my_username.