routing
Beautiful URLs are an absolute must for any serious web application. This means that ugly URLs like index.php?article_id=57
will be replaced by /read/intro-to-symfony
.
Having flexibility is even more important. What do you need to do to change the URL of the page from /blog
to /news
? How many links do you need to track and update to make changes? This is easy if you use Symfony's routing.
Symfony Router allows you to define creative URLs that map to different areas of your application. By the end of this chapter, you will be able to:
Create complex routes that will map to controllers
In templates and controls Generate URL in the server
Load routing resources from Bundle (can also be from other places)
Debug routing
Routing example ¶
A route refers to the mapping from a URL path (path) to a controller (controller). For example, you want to match some URLs: /blog/my-post
and /blog/all-about-symfony
, and send a route to a "can query and render that blog post" " on the controller. Routing is very simple:
Annotations:// src/AppBundle/Controller/BlogController.phpnamespace AppBundle\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller;use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; class BlogController extends Controller{ /** * @Route("/blog/{slug}", name="blog_show") */ public function showAction($slug) { // ... }}
YAML:# app/config/routing.ymlblog_show: path: /blog/{slug} defaults: { _controller: AppBundle:Blog:show }
XML:<!-- app/config/routing.xml --><?xml version="1.0" encoding="UTF-8" ?><routes xmlns="http://symfony.com/schema/routing" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd"> <route id="blog_show" path="/blog/{slug}"> <default key="_controller">AppBundle:Blog:show</default> </route></routes>
PHP:// app/config/routing.phpuse Symfony\Component\Routing\RouteCollection;use Symfony\Component\Routing\Route; $collection = new RouteCollection();$collection->add('blog_show', new Route('/blog/{slug}', array( '_controller' => 'AppBundle:Blog:show',))); return $collection;
define blog_show
routing pattern, used to match URLs like /blog/*
, use slug for relevant parameters or wildcards
represents and is passed in. For a URL like /blog/my-blog-post
, the slug
variable gets the value of my-blog-post
and is used by your controller. Meishiblog_show
is an internal name. It has no practical meaning and is just a unique identifier. Later, you can use it to generate some URLs.
If you don't want to use annotations because you don't like them, or because you don't want to depend on SensioFrameworkExtraBundle, you can also use YAML, XML or PHP. In these formats, the _controller
parameter is a special key that tells symfony which controller should be executed for the URL specified by the route. _controller
The string is called logical name. It follows the rules and points to a specific php class and method, AppBundle\Controller\BlogController::showAction
method.
Congratulations! You just created a route and connected it to the controller. Now, when you visit /blog/my-post
, the showAction
controller will be executed and the $slug
variable will be equal to my-post
.
The goal of Symfony routing: Map the requested URL to the controller. Following this goal, you'll learn a variety of techniques that make mapping even the most complex URLs simple.
Routing: A Deeper Look ¶
When a request is sent to your application, it contains the exact "resource" address of the client request. This address is called a URL (or URI), and it can be /contact
, /blog/read-me
, or anything else. Here is an example of an HTTP request:
GET /blog/my-blog-post
The purpose of the symfony routing system is to parse the URL and determine which controller to call. The whole process is like this:
The request is processed by Symfony's front-end controller (such as
app.php
).The core of symfony (Kernel kernel) requires the router to check the request.
Route matches the input URL to a specific route and returns the route information, including the controller information to be executed.
The Symfony kernel executes the controller and ultimately returns the
Response
object.
Routing converts an input URL into a specific tool to execute the controller.
Create Routes ¶
Symfony loads all routes into your application from a single routing configuration file. The beautiful routing configuration file is usually app/config/routing.yml
, but you can also place the file anywhere through the application configuration file (including configuration files in xml or php format).
YAML:# app/config/config.yml framework: # ... router: { resource: '%kernel.root_dir%/config/routing.yml' }
XML:<!-- app/config/config.xml --><?xml version="1.0" encoding="UTF-8" ?><container xmlns="http://symfony.com/schema/dic/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:framework="http://symfony.com/schema/dic/symfony" xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/symfony http://symfony.com/schema/dic/symfony/symfony-1.0.xsd"> <framework:config> <!-- ... --> <framework:router resource="%kernel.root_dir%/config/routing.xml" /> </framework:config></container>
PHP:// app/config/config.php$container->loadFromExtension('framework', array( // ... 'router' => array( 'resource' => '%kernel.root_dir%/config/routing.php', ),));
Although all routes can be loaded from a file, it is common practice to include additional routing resources. To do this, you configure the external routing file into the main routing file. For detailed information, please see this chapter: Contains external routing resources.
Basic routing configuration ¶
It is easy to define a route, and a typical application should also have many routes. A basic route contains two parts: path
match and defaults
array:
Annotations:// src/AppBundle/Controller/MainController.php // ...class MainController extends Controller{ /** * @Route("/") */ public function homepageAction() { // ... }}
YAML:# app/config/routing.yml_welcome: path: / defaults: { _controller: AppBundle:Main:homepage }
XML:<!-- app/config/routing.xml --><?xml version="1.0" encoding="UTF-8" ?><routes xmlns="http://symfony.com/schema/routing" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd"> <route id="_welcome" path="/"> <default key="_controller">AppBundle:Main:homepage</default> </route> </routes>
PHP:// app/config/routing.phpuse Symfony\Component\Routing\RouteCollection;use Symfony\Component\Routing\Route; $collection = new RouteCollection();$collection->add('_welcome', new Route('/', array( '_controller' => 'AppBundle:Main:homepage',))); return $collection;
The route matches the homepage (/
) and map it to the AppBundle:Main:homepage
controller. _controller
The string is converted by Symfony into a PHP function for execution. The aesthetic process is briefly mentioned in this chapter (Controller Naming Patterns).
Routing with parameters ¶
The routing system supports many interesting ways of writing routes. Many routes can contain one or more "parameter or wildcard" placeholders:
Annotations:// src/AppBundle/Controller/BlogController.php // ...class BlogController extends Controller{ /** * @Route("/blog/{slug}") */ public function showAction($slug) { // ... }}
YAML:# app/config/routing.ymlblog_show: path: /blog/{slug} defaults: { _controller: AppBundle:Blog:show }
XML:<!-- app/config/routing.xml --><?xml version="1.0" encoding="UTF-8" ?><routes xmlns="http://symfony.com/schema/routing" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd"> <route id="blog_show" path="/blog/{slug}"> <default key="_controller">AppBundle:Blog:show</default> </route></routes>
PHP:// app/config/routing.phpuse Symfony\Component\Routing\RouteCollection;use Symfony\Component\Routing\Route; $collection = new RouteCollection();$collection->add('blog_show', new Route('/blog/{slug}', array( '_controller' => 'AppBundle:Blog:show',))); return $collection;
Pretty paths will match any /blog/*
URL. Even better, the beautiful {slug}
placeholder will be automatically matched into the controller. In other words, if the URL is /blog/hello-world
, the value of the $slug
variable in the controller is hello-world
. This can be used to match strings in blog post titles.
However, routing in this way will not match URLs like /blog
, because by default, all placeholders are required. Of course, this can also be modified by adding placeholder (parameter) values to the defaults
array.
Add {wildcard} conditions ¶
Take a quick look at the routes you have created:
Annotations:// src/AppBundle/Controller/BlogController.php // ...class BlogController extends Controller{ /** * @Route("/blog/{page}", defaults={"page" = 1}) */ public function indexAction($page) { // ... } /** * @Route("/blog/{slug}") */ public function showAction($slug) { // ... }}
YAML:# app/config/routing.ymlblog: path: /blog/{page} defaults: { _controller: AppBundle:Blog:index, page: 1 }blog_show: path: /blog/{slug} defaults: { _controller: AppBundle:Blog:show }
XML:<!-- app/config/routing.xml --><?xml version="1.0" encoding="UTF-8" ?><routes xmlns="http://symfony.com/schema/routing" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd"> <route id="blog" path="/blog/{page}"> <default key="_controller">AppBundle:Blog:index</default> <default key="page">1</default> </route> <route id="blog_show" path="/blog/{slug}"> <default key="_controller">AppBundle:Blog:show</default> </route></routes>
PHP:// app/config/routing.phpuse Symfony\Component\Routing\RouteCollection;use Symfony\Component\Routing\Route; $collection = new RouteCollection();$collection->add('blog', new Route('/blog/{page}', array( '_controller' => 'AppBundle:Blog:index', 'page' => 1,))); $collection->add('blog_show', new Route('/blog/{show}', array( '_controller' => 'AppBundle:Blog:show',))); return $collection;
Can you spot the problem? Both routes match URLs like /blog/*
. Symfony routing always chooses the first matching (blog) route it matches. In other words, the blog_show
route will always be matched. In contrast, a URL like /blog/my-blog-post
will match the first (blog
) route and return a my-blog-post
The value is given to the {page}
parameter.
Route | Parameters | |
---|---|---|
/blog/2
| blog_list
| $page = 2
|
| blog_show | $slug = my-blog-post
|
Controller Class | Method Name | |
---|---|---|
| BlogController
| showAction
|