Symfony Framework
Symfony Framework
Version: 3.4
generated on April 20, 2019
Getting Started (3.4)
This work is licensed under the “Attribution-Share Alike 3.0 Unported” license (http://creativecommons.org/
licenses/by-sa/3.0/).
You are free to share (to copy, distribute and transmit the work), and to remix (to adapt the work) under the
following conditions:
• Attribution: You must attribute the work in the manner specified by the author or licensor (but not in
any way that suggests that they endorse you or your use of the work).
• Share Alike: If you alter, transform, or build upon this work, you may distribute the resulting work only
under the same, similar or a compatible license. For any reuse or distribution, you must make clear to
others the license terms of this work.
The information in this book is distributed on an “as is” basis, without warranty. Although every precaution
has been taken in the preparation of this work, neither the author(s) nor SensioLabs shall have any liability to
any person or entity with respect to any loss or damage caused or alleged to be caused directly or indirectly by
the information contained in this work.
If you find typos or errors, feel free to report them by creating a ticket on the Symfony ticketing system
(http://github.com/symfony/symfony-docs/issues). Based on tickets and users feedback, this book is
continuously updated.
Contents at a Glance
This article explains how to install Symfony in different ways and how to solve the most common issues
that may appear during the installation process.
Do you prefer video tutorials? Check out the Joyful Development with Symfony1 screencast series.
1. https://symfonycasts.com/screencast/symfony3
PDF brought to you by Chapter 1: Installing & Setting up the Symfony Framework | 4
Once the Symfony Installer is installed, create your first Symfony application with the new command:
This command creates a new directory called my_project_name/ that contains an empty project based
on the most recent stable Symfony version available. In addition, the installer checks if your system meets
the technical requirements to execute Symfony applications. If not, you'll see the list of changes needed
to meet those requirements.
If the installer doesn't work for you or doesn't output anything, make sure that the PHP Phar
extension2 is installed and enabled on your computer.
If the SSL certificates are not properly installed in your system, you may get this error:
cURL error 60: SSL certificate problem: unable to get local issuer certificate.
Listing 1-5
2. https://php.net/manual/en/intro.phar.php
PDF brought to you by Chapter 1: Installing & Setting up the Symfony Framework | 5
Each version has its own documentation, which you can select on any documentation page.
Read the Symfony Release process to better understand why there are several Symfony versions and
which one to use for your projects.
You can also install any other Symfony version by passing a second argument to the create-project
command:
If your Internet connection is slow, you may think that Composer is not doing anything. If that's
your case, add the -vvv flag to the previous command to display a detailed output of everything that
Composer is doing.
3. https://getcomposer.org/
PDF brought to you by Chapter 1: Installing & Setting up the Symfony Framework | 6
If you see a blank page or an error page instead of the Welcome Page, there is a directory permission
misconfiguration. The solution to this problem is explained in the Setting up or Fixing File Permissions.
When you are finished working on your Symfony application, stop the server by pressing Ctrl+C from
the terminal or command console.
Symfony's web server is great for developing, but should not be used on production. Instead, use
Apache or Nginx. See Configuring a Web Server.
Symfony provides a command to check whether your project's dependencies contain any known
security vulnerability:
A good security practice is to execute this command regularly to be able to update or replace
compromised dependencies as soon as possible.
PDF brought to you by Chapter 1: Installing & Setting up the Symfony Framework | 7
Keep Going!
With setup behind you, it's time to Create your first page in Symfony.
4. https://github.com/symfony/symfony-standard
5. https://github.com/symfony/demo
6. https://github.com/symfony-cmf/standard-edition
7. http://cmf.symfony.com/
8. https://github.com/gimler/symfony-rest-edition
9. https://github.com/FriendsOfSymfony/FOSRestBundle
PDF brought to you by Chapter 1: Installing & Setting up the Symfony Framework | 8
PDF brought to you by Chapter 1: Installing & Setting up the Symfony Framework | 9
Creating a new page - whether it's an HTML page or a JSON endpoint - is a two-step process:
1. Create a route: A route is the URL (e.g. /about) to your page and points to a controller;
2. Create a controller: A controller is the PHP function you write that builds the page. You take
the incoming request information and use it to create a Symfony Response object, which can hold
HTML content, a JSON string or even a binary file like an image or PDF.
Do you prefer video tutorials? Check out the Joyful Development with Symfony1 screencast series.
Symfony embraces the HTTP Request-Response lifecycle. To find out more, see Symfony and HTTP
Fundamentals.
Suppose you want to create a page - /lucky/number - that generates a lucky (well, random) number
and prints it. To do that, create a "Controller class" and a "controller" method inside of it that will be
executed when someone goes to /lucky/number:
1. https://symfonycasts.com/screencast/symfony3
Before diving into this, test it out! If you are using PHP's internal web server go to:
http://localhost:8000/lucky/number
If you see a lucky number being printed back to you, congratulations! But before you run off to play the
lottery, check out how this works. Remember the two steps to creating a page?
1. Create a route: The @Route above numberAction() is the route: it defines the URL pattern for this
page. You'll learn more about routing in its own section, including how to make variable URLs;
2. Create a controller: The method below the route - numberAction() - is called the controller. This is
a function where you build the page and ultimately return a Response object. You'll learn more
about controllers in their own section, including how to return JSON responses.
Now, use the handy render() function to render a template. Pass it our number variable so we can
render that:
2. https://twig.symfony.com
3. https://github.com/symfony/symfony/blob/3.4/src/Symfony/Bundle/FrameworkBundle/Controller/Controller.php
Finally, template files should live in the app/Resources/views directory. Create a new app/
Resources/views/lucky directory with a new number.html.twig file inside:
Listing 2-4 1 {# app/Resources/views/lucky/number.html.twig #}
2 <h1>Your lucky number is {{ number }}</h1>
The {{ number }} syntax is used to print variables in Twig. Refresh your browser to get your new
lucky number!
http://localhost:8000/lucky/number
In the Creating and Using Templates article, you'll learn all about Twig: how to loop, render other
templates and leverage its powerful layout inheritance system.
src/
Your PHP code lives here.
99% of the time, you'll be working in src/ (PHP files) or app/ (everything else). As you keep reading,
you'll learn what can be done inside each of these.
So what about the other directories in the project?
bin/
The famous bin/console file lives here (and other, less important executable files).
tests/
The automated tests (e.g. Unit tests) for your application live here.
var/
This is where automatically-created files are stored, like cache files (var/cache/), logs (var/logs/) and
sessions (var/sessions/).
web/
This is the document root for your project: put any publicly accessible files here (e.g. CSS, JS and
images).
For example, TwigBundle is responsible for adding the Twig tool to your app!
Eventually, you'll download and add more third-party bundles to your app in order to get even more
tools. Imagine a bundle that helps you create paginated lists. That exists!
You can control how your bundles behave via the app/config/config.yml file. That file - and other
details like environments & parameters - are discussed in the Configuring Symfony (and Environments)
article.
What's Next?
Congrats! You're already starting to master Symfony and learn a whole new way of building beautiful,
functional, fast and maintainable applications.
Ok, time to finish mastering the fundamentals by reading these articles:
• Routing
• Controller
• Creating and Using Templates
• Configuring Symfony (and Environments)
Then, learn about other important topics like the service container, the form system, using Doctrine (if
you need to query a database) and more!
4. https://getcomposer.org
Beautiful URLs are a must for any serious web application. This means leaving behind ugly URLs like
index.php?article_id=57 in favor of something like /read/intro-to-symfony.
Having flexibility is even more important. What if you need to change the URL of a page from /blog to
/news? How many links would you need to hunt down and update to make the change? If you're using
Symfony's router, the change should be trivial.
The Symfony router lets you define creative URLs that you map to different areas of your application. By
the end of this article, you'll be able to:
Routing Examples
A route is a map from a URL path to attributes (i.e a controller). Suppose you want one route that
matches /blog exactly and another more dynamic route that can match any URL like /blog/my-post
or /blog/all-about-symfony.
Routes can be configured in YAML, XML, PHP or annotations. All formats provide the same features
and performance, so choose the one you prefer:
• If the user goes to /blog, the first route is matched and listAction() is executed;
• If the user goes to /blog/*, the second route is matched and showAction() is executed. Because the route
path is /blog/{slug}, a $slug variable is passed to showAction() matching that value. For example, if the
user goes to /blog/yay-routing, then $slug will equal yay-routing.
Whenever you have a {placeholder} in your route path, that portion becomes a wildcard: it matches
any value. Your controller can now also have an argument called $placeholder (the wildcard and
argument names must match).
However the slash / is ignored by default in placeholder values because the router uses it as separator
between different placeholders. To learn more about this, you can read How to Allow a "/" Character
in a Route Parameter.
Each route also has an internal name: blog_list and blog_show. These can be anything (as long as
each is unique) and don't have any meaning yet. Later, you'll use it to generate URLs.
This is the goal of the Symfony router: to map the URL of a request to a controller. Along the way, you'll
learn all sorts of tricks that make mapping even the most complex URLs easy.
When two routes match the same URL, the first route that's loaded wins. Unfortunately, that means that
/blog/yay-routing will match the blog_list. No good!
To fix this, add a requirement that the {page} wildcard can only match numbers (digits):
The \d+ is a regular expression that matches a digit of any length. Now:
To learn about other route requirements - like HTTP method, hostname and dynamic expressions - see
How to Define Route Requirements.
Now, when the user visits /blog, the blog_list route will match and $page will default to a value of
1.
As you've seen, this route will only match if the {_locale} portion of the URL is either en or fr and if
the {year} is a number. This route also shows how you can use a dot between placeholders instead of a
slash. URLs matching this route might look like:
• /articles/en/2010/my-post
• /articles/fr/2010/my-post.rss
• /articles/en/2013/my-latest-post.html
_format
Used to set the request format (read more).
_fragment
Used to set the fragment identifier, the optional last part of a URL that starts with a # character and
is used to identify a portion of a document.
New in version 3.2: The _fragment parameter was introduced in Symfony 3.2.
_locale
Used to set the locale on the request (read more).
In summary, adding a trailing slash in the route path is the best way to ensure that both URLs work. Read
the Redirect URLs with a Trailing Slash article to learn how to avoid the 404 error when the request URL
contains a trailing slash and the route path does not.
Notice that Symfony adds the string Controller to the class name (Blog => BlogController) and
Action to the method name (show => showAction()).
You could also refer to this controller using its fully-qualified class name and method: AppBundle\
Controller\BlogController::showAction. But if you follow some simple conventions, the
logical name is more concise and allows more flexibility.
To refer to an action that is implemented as the __invoke() method of a controller class, you do
not have to pass the method name, but can just use the fully qualified class name (e.g. AppBundle\
Controller\BlogController).
In addition to using the logical name or the fully-qualified class name, Symfony supports a third
way of referring to a controller. This method uses just one colon separator (e.g.
service_name:indexAction) and refers to the controller as a service (see How to Define
Controllers as Services).
Loading Routes
Symfony loads all the routes for your application from a single routing configuration file: app/config/
routing.yml. But from inside of this file, you can load any other routing files you want. In fact, by
default, Symfony loads annotation route configuration from your AppBundle's Controller/ directory,
which is how Symfony sees our annotation routes:
For more details on loading routes, including how to prefix the paths of loaded routes, see How to Include
External Routing Resources.
The generateUrl() method defined in the base Controller1 class is just a shortcut for this
code:
$url = $this->container->get('router')->generate(
Listing 3-8
'blog_show',
['slug' => 'my-blog-post']
);
1. https://github.com/symfony/symfony/blob/3.4/src/Symfony/Bundle/FrameworkBundle/Controller/Controller.php
Troubleshooting
Here are some common errors you might see while working with routing:
This happens when your controller method has an argument (e.g. $slug):
Listing 3-11
public function showAction($slug)
{
// ...
}
But your route path does not have a {slug} wildcard (e.g. it is /blog/show). Add a {slug} to your
route path: /blog/show/{slug} or give the argument a default value (i.e. $slug = null).
Some mandatory parameters are missing ("slug") to generate a URL for route "blog_show".
This means that you're trying to generate a URL to the blog_show route but you are not passing a slug
value (which is required, because it has a {slug}) wildcard in the route path. To fix this, pass a slug
value when generating the route:
Listing 3-12
$this->generateUrl('blog_show', ['slug' => 'slug-value']);
// or, in Twig
// {{ path('blog_show', {'slug': 'slug-value'}) }}
Translating Routes
Symfony doesn't support defining routes with different contents depending on the user language. In those
cases, you can define multiple routes per controller, one for each supported language; or use any of
the bundles created by the community to implement this feature, such as JMSI18nRoutingBundle2 and
BeSimpleI18nRoutingBundle3.
Summary
Routing is a system for mapping the URL of incoming requests to the controller function that should be
called to process the request. It both allows you to specify beautiful URLs and keeps the functionality
of your application decoupled from those URLs. Routing is a bidirectional mechanism, meaning that it
should also be used to generate URLs.
2. https://github.com/schmittjoh/JMSI18nRoutingBundle
3. https://github.com/BeSimple/BeSimpleI18nRoutingBundle
A controller is a PHP function you create that reads information from the Symfony's Request object
and creates and returns a Response object. The response could be an HTML page, JSON, XML, a file
download, a redirect, a 404 error or anything else you can dream up. The controller executes whatever
arbitrary logic your application needs to render the content of a page.
See how simple this is by looking at a Symfony controller in action. This renders a page that prints a lucky
(random) number:
But in the real world, your controller will probably do a lot of work in order to create the response. It
might read information from the request, load a database resource, send an email or set information on
the user's session. But in all cases, the controller will eventually return the Response object that will be
delivered back to the client.
If you haven't already created your first working page, check out Create your First Page in Symfony
and then come back!
The controller is the numberAction() method, which lives inside a controller class
LuckyController.
This controller is pretty straightforward:
• line 2: Symfony takes advantage of PHP's namespace functionality to namespace the entire
controller class.
• line 4: Symfony again takes advantage of PHP's namespace functionality: the use keyword imports
the Response class, which the controller must return.
• line 7: The class can technically be called anything - but should end in the word Controller (this isn't
required, but some shortcuts rely on this).
• line 12: Each action method in a controller class is suffixed with Action (again, this isn't required,
but some shortcuts rely on this). This method is allowed to have a $max argument thanks to the {max}
wildcard in the route.
• line 16: The controller creates and returns a Response object.
http://localhost:8000/lucky/number/100
That's it! You now have access to methods like $this->render() and many others that you'll learn about
next.
You can extend either Controller or AbstractController. The difference is that when you
extend AbstractController, you can't access your services via $this->get() or $this-
>container->get(), only to a set of common Symfony services. This forces you to write more
robust code to access services.
Moreover, in Symfony 4.2 Controller was deprecated in favor of AbstractController, so
using the latter will make your applications future-proof.
New in version 3.3: The AbstractController class was introduced in Symfony 3.3.
Generating URLs
The generateUrl()4 method is just a helper method that generates the URL for a given route:
Listing 4-4
$url = $this->generateUrl('blog_show', ['slug' => 'slug-value']);
Redirecting
If you want to redirect the user to another page, use the redirectToRoute() and redirect()
methods:
1. https://github.com/symfony/symfony/blob/3.4/src/Symfony/Bundle/FrameworkBundle/Controller/Controller.php
2. https://github.com/symfony/symfony/blob/3.4/src/Symfony/Bundle/FrameworkBundle/Controller/AbstractController.php
3. https://github.com/symfony/symfony/blob/master/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerTrait.php
4. https://github.com/symfony/symfony/blob/3.4/src/Symfony/Bundle/FrameworkBundle/Controller/Controller.php
The redirect() method does not check its destination in any way. If you redirect to some
URL provided by the end-users, your application may be open to the unvalidated redirects security
vulnerability5.
The redirectToRoute() method is simply a shortcut that creates a Response object that
specializes in redirecting the user. It's equivalent to:
Rendering Templates
If you're serving HTML, you'll want to render a template. The render() method renders a template
and puts that content into a Response object for you:
Listing 4-7
// renders app/Resources/views/lucky/number.html.twig
return $this->render('lucky/number.html.twig', ['number' => $number]);
Templates can also live in deeper sub-directories. Just try to avoid creating unnecessarily deep structures:
Listing 4-8
// renders app/Resources/views/lottery/lucky/number.html.twig
return $this->render('lottery/lucky/number.html.twig', [
'number' => $number,
]);
The Symfony templating system and Twig are explained more in the Creating and Using Templates article.
5. https://www.owasp.org/index.php/Open_redirect
Awesome!
What other services can you type-hint? To see them, use the debug:autowiring console command:
If you need control over the exact value of an argument, you can bind the argument by its name:
You can of course also use normal constructor injection in your controllers.
You can only pass services to your controller arguments in this way. It's not possible, for example,
to pass a service parameter as a controller argument, even by using bind. If you need a parameter,
use the $this->getParameter('kernel.debug') shortcut or pass the value through your
controller's __construct() method and specify its value with bind.
For more information about services, see the Service Container article.
If this isn't working, make sure your controller is registered as a service, is autoconfigured and
extends either Controller6 or AbstractController7. If you use the services.yml configuration
from the Symfony Standard Edition, then your controllers are already registered as services and
autoconfigured.
If you're not using the default configuration, you can tag your service manually with
controller.service_arguments.
6. https://github.com/symfony/symfony/blob/3.4/src/Symfony/Bundle/FrameworkBundle/Controller/Controller.php
7. https://github.com/symfony/symfony/blob/3.4/src/Symfony/Bundle/FrameworkBundle/Controller/AbstractController.php
8. https://github.com/symfony/symfony/blob/3.4/src/Symfony/Bundle/FrameworkBundle/Controller/Controller.php
Check to make sure the service exists (use debug:container) and that it's public.
Listing 4-15
// this exception ultimately generates a 500 status error
throw new \Exception('Something went wrong!');
In every case, an error page is shown to the end user and a full debug error page is shown to the
developer (i.e. when you're using the app_dev.php front controller - see The imports Key: Loading
other Configuration Files).
You'll want to customize the error page your user sees. To do that, see the How to Customize Error Pages
article.
Keep reading for more information about using the Request object.
9. https://github.com/symfony/symfony/blob/3.4/src/Symfony/Bundle/FrameworkBundle/Controller/Controller.php
10. https://github.com/symfony/symfony/blob/3.4/src/Symfony/Component/HttpKernel/Exception/NotFoundHttpException.php
11. https://github.com/symfony/symfony/blob/3.4/src/Symfony/Component/HttpKernel/Exception/HttpException.php
Stored attributes remain in the session for the remainder of that user's session.
Flash Messages
You can also store special messages, called "flash" messages, on the user's session. By design, flash
messages are meant to be used exactly once: they vanish from the session automatically as soon as you
retrieve them. This feature makes "flash" messages particularly great for storing user notifications.
For example, imagine you're processing a form submission:
12. https://github.com/symfony/symfony/blob/3.4/src/Symfony/Component/HttpFoundation/Session/SessionInterface.php
New in version 3.3: The app.flashes() Twig function was introduced in Symfony 3.3. Prior, you had
to use app.session.flashBag().
It's common to use notice, warning and error as the keys of the different types of flash
messages, but you can use any key that fits your needs.
You can use the peek()13 method instead to retrieve the message while keeping it in the bag.
13. https://github.com/symfony/symfony/blob/3.4/src/Symfony/Component/HttpFoundation/Session/Flash/FlashBagInterface.php
The Request class has several public properties and methods that return any information you need
about the request.
Like the Request, the Response object has also a public headers property. This is a
ResponseHeaderBag14 that has some nice methods for getting and setting response headers. The
header names are normalized so that using Content-Type is equivalent to content-type or even
content_type.
The only requirement for a controller is to return a Response object. The Response15 class is an
abstraction around the HTTP response - the text-based message filled with headers and content that's
sent back to the client:
There are special classes that make certain kinds of responses easier:
Now that you know the basics you can continue your research on Symfony Request and Response object in the
HttpFoundation component documentation.
JSON Helper
To return JSON from a controller, use the json() helper method on the base controller. This returns a
special JsonResponse object that encodes the data automatically:
14. https://github.com/symfony/symfony/blob/3.4/src/Symfony/Component/HttpFoundation/ResponseHeaderBag.php
15. https://github.com/symfony/symfony/blob/3.4/src/Symfony/Component/HttpFoundation/Response.php
16. https://github.com/symfony/symfony/blob/3.4/src/Symfony/Component/HttpFoundation/BinaryFileResponse.php
17. https://github.com/symfony/symfony/blob/3.4/src/Symfony/Component/HttpFoundation/StreamedResponse.php
If the serializer service is enabled in your application, contents passed to json() are encoded with it.
Otherwise, the json_encode18 function is used.
File helper
New in version 3.2: The file() helper was introduced in Symfony 3.2.
You can use the file()19 helper to serve a file from inside a controller:
Final Thoughts
Whenever you create a page, you'll ultimately need to write some code that contains the logic for that
page. In Symfony, this is called a controller, and it's a PHP function where you can do anything in order
to return the final Response object that will be returned to the user.
To make life easier, you'll probably extend the base Controller class because this gives access to
shortcut methods (like render() and redirectToRoute()).
In other articles, you'll learn how to use specific services from inside your controller that will help you
persist and fetch objects from a database, process form submissions, handle caching and more.
Keep Going!
Next, learn all about rendering templates with Twig.
18. https://secure.php.net/manual/en/function.json-encode.php
19. https://github.com/symfony/symfony/blob/3.4/src/Symfony/Bundle/FrameworkBundle/Controller/Controller.php
As explained in the previous article, controllers are responsible for handling each request that comes into
a Symfony application and they usually end up rendering a template to generate the response contents.
In reality, the controller delegates most of the heavy work to other places so that code can be tested and
reused. When a controller needs to generate HTML, CSS or any other content, it hands the work off to
the templating engine.
In this article, you'll learn how to write powerful templates that can be used to return content to the
user, populate email bodies, and more. You'll learn shortcuts, clever ways to extend templates and how
to reuse template code.
Templates
A template is simply a text file that can generate any text-based format (HTML, XML, CSV, LaTeX ...).
The most familiar type of template is a PHP template - a text file parsed by PHP that contains a mix of
text and PHP code:
{% ... %}
"Does something": a tag that controls the logic of the template; it is used to execute statements such
as for-loops for example.
{# ... #}
"Comment something": it's the equivalent of the PHP /* comment */ syntax. It's used to add single or
multi-line comments. The content of the comments isn't included in the rendered pages.
Twig also contains filters, which modify content before being rendered. The following makes the title
variable all uppercase before rendering it:
Twig comes with a long list of tags2, filters3 and functions4 that are available by default. You can even add
your own custom filters, functions (and more) via a Twig Extension.
Twig code will look similar to PHP code, with subtle, nice differences. The following example uses a
standard for tag and the cycle() function to print ten div tags, with alternating odd, even classes:
Throughout this article, template examples will be shown in both Twig and PHP.
1. https://twig.symfony.com
2. https://twig.symfony.com/doc/2.x/tags/index.html
3. https://twig.symfony.com/doc/2.x/filters/index.html
4. https://twig.symfony.com/doc/2.x/functions/index.html
This template defines the base HTML skeleton document of a simple two-column page. In this example,
three {% block %} areas are defined (title, sidebar and body). Each block may be overridden by
a child template or left with its default implementation. This template could also be rendered directly.
In that case the title, sidebar and body blocks would simply retain the default values used in this
template.
A child template might look like this:
The key to template inheritance is the {% extends %} tag. This tells the templating engine to first
evaluate the base template, which sets up the layout and defines several blocks. The child template is
then rendered, at which point the title and body blocks of the parent are replaced by those from the
child. Depending on the value of blog_entries, the output might look like this:
Notice that since the child template didn't define a sidebar block, the value from the parent template
is used instead. Content within a {% block %} tag in a parent template is always used by default.
When working with template inheritance, here are some tips to keep in mind:
• If you use {% extends %} in a template, it must be the first tag in that template;
• The more {% block %} tags you have in your base templates, the better. Remember, child
templates don't have to define all parent blocks, so create as many blocks in your base templates
as you want and give each a sensible default. The more blocks your base templates have, the more
flexible your layout will be;
• If you find yourself duplicating content in a number of templates, it probably means you should
move that content to a {% block %} in a parent template. In some cases, a better solution may be
to move the content to a new template and include it (see Including other Templates);
• If you need to get the content of a block from the parent template, you can use the {{ parent()
}} function. This is useful if you want to add to the contents of a parent block instead of completely
overriding it:
vendor/path/to/CoolBundle/Resources/views/
Each third party bundle houses its templates in its Resources/views/ directory (and subdirectories).
When you plan to share your bundle, you should put the templates in the bundle instead of the app/
directory.
Most of the templates you'll use live in the app/Resources/views/ directory. The path you'll use
will be relative to this directory. For example, to render/extend app/Resources/views/
base.html.twig, you'll use the base.html.twig path and to render/extend app/Resources/
views/blog/index.html.twig, you'll use the blog/index.html.twig path.
Assuming that the AcmeBlogBundle lives at src/Acme/BlogBundle, the final path to the layout
would be src/Acme/BlogBundle/Resources/views/Blog/index.html.twig.
• @AcmeBlog/layout.html.twig: This syntax refers to a base template that's specific to the
AcmeBlogBundle. Since the middle, "directory", portion is missing (e.g. Blog), the template lives at
Resources/views/layout.html.twig inside AcmeBlogBundle.
In the How to Override Templates from Third-Party Bundles section, you'll find out how each template
living inside the AcmeBlogBundle, for example, can be overridden by placing a template of the same
name in the app/Resources/AcmeBlogBundle/views/ directory. This gives the power to override
templates from any vendor bundle.
Template Suffix
Every template name also has two extensions that specify the format and engine for that template.
By default, any Symfony template can be written in either Twig or PHP, and the last part of the extension
(e.g. .twig or .php) specifies which of these two engines should be used. The first part of the extension,
(e.g. .html, .css, etc) is the final format that the template will generate. Unlike the engine, which
determines how Symfony parses the template, this is simply an organizational tactic used in case the same
resource needs to be rendered as HTML (index.html.twig), XML (index.xml.twig), or any other
format. For more information, read the How to Work with Different Output Formats in Templates section.
The template is included using the {{ include() }} function. Notice that the template name follows
the same typical convention. The article_details.html.twig template uses an article variable,
which we pass to it. In this case, you could avoid doing this entirely, as all of the variables available in
list.html.twig are also available in article_details.html.twig (unless you set with_context5
to false).
The {'article': article} syntax is the standard Twig syntax for hash maps (i.e. an array with
named keys). If you needed to pass in multiple elements, it would look like this: {'foo': foo,
'bar': bar}.
Linking to Pages
Creating links to other pages in your application is one of the most common jobs for a template. Instead
of hardcoding URLs in templates, use the path Twig function (or the router helper in PHP) to generate
URLs based on the routing configuration. Later, if you want to modify the URL of a particular page, all
you'll need to do is change the routing configuration: the templates will automatically generate the new
URL.
First, link to the "welcome" page, which is accessible via the following routing configuration:
5. https://twig.symfony.com/doc/2.x/functions/include.html
To link to the page, just use the path() Twig function and refer to the route:
As expected, this will generate the URL /. Now, for a more complicated route:
In this case, you need to specify both the route name (article_show) and a value for the {slug}
parameter. Using this route, revisit the recent_list.html.twig template from the previous section
and link to the articles correctly:
You can also generate an absolute URL by using the url() Twig function:
Linking to Assets
Templates also commonly refer to images, JavaScript, stylesheets and other assets. Of course you could
hard-code the path to these assets (e.g. /images/logo.png), but Symfony provides a more dynamic
option via the asset() Twig function:
The asset() function's main purpose is to make your application more portable. If your application
lives at the root of your host (e.g. http://example.com), then the rendered paths should be
/images/logo.png. But if your application lives in a subdirectory (e.g. http://example.com/
my_app), each asset path should render with the subdirectory (e.g. /my_app/images/logo.png).
The asset() function supports various cache busting techniques via the version, version_format,
and json_manifest_path configuration options.
If you need absolute URLs for assets, use the absolute_url() Twig function as follows:
This section will teach you the philosophy behind including stylesheet and JavaScript assets in
Symfony. Symfony is also compatible with another library, called Assetic, which follows this
philosophy but allows you to do much more interesting things with those assets. For more
information on using Assetic see How to Use Assetic for Asset Management.
Start by adding two blocks to your base template that will hold your assets: one called stylesheets
inside the head tag and another called javascripts just above the closing body tag. These blocks will
contain all of the stylesheets and JavaScripts that you'll need throughout your site:
That's easy enough! But what if you need to include an extra stylesheet or JavaScript from a child
template? For example, suppose you have a contact page and you need to include a contact.css
stylesheet just on that page. From inside that contact page's template, do the following:
The end result is a page that includes main.js and both the main.css and contact.css stylesheets.
Output Escaping
Twig performs automatic "output escaping" when rendering any content in order to protect you from
Cross Site Scripting (XSS) attacks.
Suppose description equals I <3 this product:
Final Thoughts
The templating system is just one of the many tools in Symfony. And its job is simple: allow us to render
dynamic & complex HTML output so that this can ultimately be returned to the user, sent in an email or
something else.
Keep Going!
Before diving into the rest of Symfony, check out the configuration system.
Learn more
PDF brought to you by Chapter 5: Creating and Using Templates | 44
Every Symfony application consists of a collection of bundles that add useful tools (services) to your
project. Each bundle can be customized via configuration files that live - by default - in the app/config
directory.
Configuration: config.yml
The main configuration file is called config.yml:
Most top-level keys - like framework and twig - are configuration for a specific bundle (i.e.
FrameworkBundle and TwigBundle).
The imports key works a lot like the PHP include() function: the contents of parameters.yml,
security.yml and services.yml are read and loaded. You can also load XML files or PHP files.
If your application uses unconventional file extensions (for example, your YAML files have a .res
extension) you can set the file type explicitly with the type option:
You can define whatever parameter names you want under the parameters key of any configuration
file. To reference a parameter, surround its name with two percent signs - e.g. %locale%.
You can also set parameters dynamically, like from environment variables. See How to Set external
Parameters in the Service Container.
For more information about parameters - including how to reference them from inside a controller - see
Service Parameters.
Not surprisingly, these are referenced from inside of config.yml and help to configure DoctrineBundle
and other parts of Symfony:
But the parameters.yml file is special: it defines the values that usually change on each server. For
example, the database credentials on your local development machine might be different from your
workmates. That's why this file is not committed to the shared repository and is only stored on your
machine.
Because of that, parameters.yml is not committed to your version control. In fact, the .gitignore
file that comes with Symfony prevents it from being committed.
However, a parameters.yml.dist file is committed (with dummy values). This file isn't read by
Symfony: it's just a reference so that Symfony knows which parameters need to be defined in the
parameters.yml file. If you add or remove keys to parameters.yml, add or remove them from
parameters.yml.dist too so both files are always in sync.
• While developing, you want your app to log everything and expose nice debugging tools;
• After deploying to production, you want that same app to be optimized for speed and only log
errors.
How can you make one application behave in two different ways? With environments.
You've probably already been using the dev environment without even knowing it. After you deploy,
you'll use the prod environment.
To learn more about how to execute and control each environment, see How to Master and Create new
Environments.
Keep Going!
Congratulations! You've tackled the basics in Symfony. Next, learn about each part of Symfony
individually by following the guides. Check out:
• Forms
• Databases and the Doctrine ORM
• Service Container
• Security
• How to Send an Email
• Logging
Learn more
• How to Organize Configuration Files
• How to Master and Create new Environments
• How to Set external Parameters in the Service Container
• Understanding how the Front Controller, Kernel and Environments Work together
• Building your own Framework with the MicroKernelTrait
• How To Create Symfony Applications with Multiple Kernels
• How to Override Symfony's default Directory Structure
• Using Parameters within a Dependency Injection Class
1. https://github.com/Incenteev/ParameterHandler