Permalink
Browse files

feature #4427 Update most important book articles to follow the best …

…practices (WouterJ)

This PR was merged into the 2.3 branch.

Discussion
----------

Update most important book articles to follow the best practices

| Q   | A
| --- | ---
| Doc fix? | yes
| New docs? | no
| Applies to | all (or 2.6?)
| Fixed ticket | lots of complaints :)

I've decided to do only the most important articles for the first PR, otherwise the diff will be too big to get a nice review. I'll do a seperate PR for the Page Creation article, since that needed quite so rewriting.

Btw, I also couldn't resist to fix other minor things :)

Commits
-------

e56c272 Fixed error
9678b61 Proofread templating
51773f4 Proofread routing article
91c8981 Used annotations for routing
210bb4b Some minor things
4da1bcf Use AppBundle
10b3c7c Other random fixes
a8a75d7 Changed Bundle:Controller:Template to bundle:dir:file
db3086d Moved templates to app and controllers to AppBundle
ab2e2c7 Other fixes
18e3a31 Moved templates to app
c8f5ad5 Updated to use AppBundle
b735642 Fixed some other minor stuff
0ef1c68 Moved templates to app/Resources/views
87b324a Renamed AcmeHelloBundle to AppBundle
  • Loading branch information...
weaverryan committed Nov 7, 2014
2 parents ddd4a3b + e56c272 commit 2c190ed8af7517607931dca6da41b4f7ad987b6c
Showing with 543 additions and 369 deletions.
  1. +2 −0 best_practices/templates.rst
  2. +53 −63 book/controller.rst
  3. +15 −21 book/from_flat_php_to_symfony2.rst
  4. +355 −174 book/routing.rst
  5. +118 −111 book/templating.rst
@@ -22,6 +22,8 @@ In addition, Twig is the only template format with guaranteed support in Symfony
3.0. As a matter of fact, PHP may be removed from the officially supported
template engines.
.. _best_practices-template-location:
Template Locations
------------------
@@ -91,10 +91,9 @@ or a ``Closure``), in Symfony, a controller is usually a single method inside
a controller object. Controllers are also called *actions*.
.. code-block:: php
:linenos:
// src/Acme/HelloBundle/Controller/HelloController.php
namespace Acme\HelloBundle\Controller;
// src/AppBundle/Controller/HelloController.php
namespace AppBundle\Controller;
use Symfony\Component\HttpFoundation\Response;
@@ -151,7 +150,7 @@ to the controller:
# app/config/routing.yml
hello:
path: /hello/{name}
defaults: { _controller: AcmeHelloBundle:Hello:index }
defaults: { _controller: AppBundle:Hello:index }
.. code-block:: xml
@@ -163,7 +162,7 @@ to the controller:
http://symfony.com/schema/routing/routing-1.0.xsd">
<route id="hello" path="/hello/{name}">
<default key="_controller">AcmeHelloBundle:Hello:index</default>
<default key="_controller">AppBundle:Hello:index</default>
</route>
</routes>
@@ -175,7 +174,7 @@ to the controller:
$collection = new RouteCollection();
$collection->add('hello', new Route('/hello/{name}', array(
'_controller' => 'AcmeHelloBundle:Hello:index',
'_controller' => 'AppBundle:Hello:index',
)));
return $collection;
@@ -184,10 +183,10 @@ Going to ``/hello/ryan`` now executes the ``HelloController::indexAction()``
controller and passes in ``ryan`` for the ``$name`` variable. Creating a
"page" means simply creating a controller method and associated route.
Notice the syntax used to refer to the controller: ``AcmeHelloBundle:Hello:index``.
Notice the syntax used to refer to the controller: ``AppBundle:Hello:index``.
Symfony uses a flexible string notation to refer to different controllers.
This is the most common syntax and tells Symfony to look for a controller
class called ``HelloController`` inside a bundle named ``AcmeHelloBundle``. The
class called ``HelloController`` inside a bundle named ``AppBundle``. The
method ``indexAction()`` is then executed.
For more details on the string format used to reference different controllers,
@@ -202,7 +201,8 @@ see :ref:`controller-string-syntax`.
.. tip::
You can learn much more about the routing system in the :doc:`Routing chapter </book/routing>`.
You can learn much more about the routing system in the
:doc:`Routing chapter </book/routing>`.
.. index::
single: Controller; Controller arguments
@@ -212,29 +212,29 @@ see :ref:`controller-string-syntax`.
Route Parameters as Controller Arguments
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
You already know that the ``_controller`` parameter ``AcmeHelloBundle:Hello:index``
You already know that the ``_controller`` parameter ``AppBundle:Hello:index``
refers to a ``HelloController::indexAction()`` method that lives inside the
``AcmeHelloBundle`` bundle. What's more interesting is the arguments that are
passed to that method::
``AppBundle`` bundle. What's more interesting is the arguments that are passed
to that method::
// src/Acme/HelloBundle/Controller/HelloController.php
namespace Acme\HelloBundle\Controller;
// src/AppBundle/Controller/HelloController.php
namespace AppBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class HelloController extends Controller
{
public function indexAction($name)
{
// ...
// ...
}
}
The controller has a single argument, ``$name``, which corresponds to the
``{name}`` parameter from the matched route (``ryan`` in the example). In
fact, when executing your controller, Symfony matches each argument of
the controller with a parameter from the matched route. Take the following
example:
the controller with a parameter from the matched route by its name. Take the
following example:
.. configuration-block::
@@ -243,7 +243,7 @@ example:
# app/config/routing.yml
hello:
path: /hello/{firstName}/{lastName}
defaults: { _controller: AcmeHelloBundle:Hello:index, color: green }
defaults: { _controller: AppBundle:Hello:index, color: green }
.. code-block:: xml
@@ -255,7 +255,7 @@ example:
http://symfony.com/schema/routing/routing-1.0.xsd">
<route id="hello" path="/hello/{firstName}/{lastName}">
<default key="_controller">AcmeHelloBundle:Hello:index</default>
<default key="_controller">AppBundle:Hello:index</default>
<default key="color">green</default>
</route>
</routes>
@@ -268,7 +268,7 @@ example:
$collection = new RouteCollection();
$collection->add('hello', new Route('/hello/{firstName}/{lastName}', array(
'_controller' => 'AcmeHelloBundle:Hello:index',
'_controller' => 'AppBundle:Hello:index',
'color' => 'green',
)));
@@ -377,8 +377,8 @@ you can take advantage of several helper methods.
Add the ``use`` statement atop the ``Controller`` class and then modify the
``HelloController`` to extend it::
// src/Acme/HelloBundle/Controller/HelloController.php
namespace Acme\HelloBundle\Controller;
// src/AppBundle/Controller/HelloController.php
namespace AppBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;
@@ -422,15 +422,17 @@ Common Controller Tasks
Though a controller can do virtually anything, most controllers will perform
the same basic tasks over and over again. These tasks, such as redirecting,
forwarding, rendering templates and accessing core services, are very easy
to manage in Symfony.
to manage in Symfony when you're extending the base ``Controller`` class.
.. index::
single: Controller; Redirecting
Redirecting
~~~~~~~~~~~
If you want to redirect the user to another page, use the ``redirect()`` method::
If you want to redirect the user to another page, use the
:method:`Symfony\\Bundle\\FrameworkBundle\\Controller\\Controller::redirect`
method::
public function indexAction()
{
@@ -472,7 +474,7 @@ object that's returned from that controller::
public function indexAction($name)
{
$response = $this->forward('AcmeHelloBundle:Hello:fancy', array(
$response = $this->forward('AppBundle:Something:fancy', array(
'name' => $name,
'color' => 'green',
));
@@ -484,22 +486,22 @@ object that's returned from that controller::
Notice that the ``forward()`` method uses the same string representation of
the controller used in the routing configuration. In this case, the target
controller class will be ``HelloController`` inside some ``AcmeHelloBundle``.
The array passed to the method becomes the arguments on the resulting controller.
This same interface is used when embedding controllers into templates (see
:ref:`templating-embedding-controller`). The target controller method should
look something like the following::
controller class will be ``SomethingController::fancyAction()`` inside the
``AppBundle``. The array passed to the method becomes the arguments on the
resulting controller. This same interface is used when embedding controllers
into templates (see :ref:`templating-embedding-controller`). The target
controller method should look something like the following::
public function fancyAction($name, $color)
{
// ... create and return a Response object
}
And just like when creating a controller for a route, the order of the arguments
to ``fancyAction`` doesn't matter. Symfony matches the index key names
(e.g. ``name``) with the method argument names (e.g. ``$name``). If you
change the order of the arguments, Symfony will still pass the correct
value to each variable.
Just like when creating a controller for a route, the order of the arguments of
``fancyAction`` doesn't matter. Symfony matches the index key names (e.g.
``name``) with the method argument names (e.g. ``$name``). If you change the
order of the arguments, Symfony will still pass the correct value to each
variable.
.. tip::
@@ -512,7 +514,7 @@ value to each variable.
use Symfony\Component\HttpKernel\HttpKernelInterface;
$path = array(
'_controller' => 'AcmeHelloBundle:Hello:fancy',
'_controller' => 'AppBundle:Something:fancy',
'name' => $name,
'color' => 'green',
);
@@ -540,57 +542,45 @@ content from the template can be used to create a ``Response`` object::
use Symfony\Component\HttpFoundation\Response;
$content = $this->renderView(
'AcmeHelloBundle:Hello:index.html.twig',
array('name' => $name)
);
$content = $this->renderView('Hello/index.html.twig', array('name' => $name));
return new Response($content);
This can even be done in just one step with the ``render()`` method, which
returns a ``Response`` object containing the content from the template::
return $this->render(
'AcmeHelloBundle:Hello:index.html.twig',
array('name' => $name)
);
return $this->render('Hello/index.html.twig', array('name' => $name));
In both cases, the ``Resources/views/Hello/index.html.twig`` template inside
the ``AcmeHelloBundle`` will be rendered.
In both cases, the ``app/Resources/views/Hello/index.html.twig`` template will
be rendered.
The Symfony templating engine is explained in great detail in the
:doc:`Templating </book/templating>` chapter.
.. sidebar:: Referencing Templates that Live inside the Bundle
.. tip::
You can also put templates in the ``Resources/views`` directory of a
bundle. You can then reference is with the
``BundleName:DirectoryName:FileName`` syntax. E.g.
``AppBundle:Hello:index.html.twig`` would refer to the template located in
``src/AppBundle/Resources/views/Hello/index.html.twig``.
You can even avoid calling the ``render`` method by using the ``@Template``
annotation. See the
:doc:`FrameworkExtraBundle documentation </bundles/SensioFrameworkExtraBundle/annotations/view>`
more details.
The Symfony templating engine is explained in great detail in the
:doc:`Templating </book/templating>` chapter.
.. tip::
The ``renderView`` method is a shortcut to direct use of the ``templating``
service. The ``templating`` service can also be used directly::
$templating = $this->get('templating');
$content = $templating->render(
'AcmeHelloBundle:Hello:index.html.twig',
array('name' => $name)
);
$content = $templating->render('Hello/index.html.twig', array('name' => $name));
.. note::
It is possible to render templates in deeper subdirectories as well, however
be careful to avoid the pitfall of making your directory structure unduly
elaborate::
$templating->render(
'AcmeHelloBundle:Hello/Greetings:index.html.twig',
array('name' => $name)
);
// index.html.twig found in Resources/views/Hello/Greetings
// is rendered.
$templating->render('Hello/Greetings/index.html.twig', array('name' => $name));
// renders app/Resources/views/Hello/Greetings/index.html.twig
.. index::
single: Controller; Accessing services
@@ -547,8 +547,8 @@ from scratch, you could at least use Symfony's standalone `Routing`_ and
Instead of re-solving common problems, you can let Symfony take care of
them for you. Here's the same sample application, now built in Symfony::
// src/Acme/BlogBundle/Controller/BlogController.php
namespace Acme\BlogBundle\Controller;
// src/AppBundle/Controller/BlogController.php
namespace AppBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
@@ -561,40 +561,34 @@ them for you. Here's the same sample application, now built in Symfony::
->createQuery('SELECT p FROM AcmeBlogBundle:Post p')
->execute();
return $this->render(
'AcmeBlogBundle:Blog:list.html.php',
array('posts' => $posts)
);
return $this->render('Blog/list.html.php', array('posts' => $posts));
}
public function showAction($id)
{
$post = $this->get('doctrine')
->getManager()
->getRepository('AcmeBlogBundle:Post')
->getRepository('AppBundle:Post')
->find($id);
if (!$post) {
// cause the 404 page not found to be displayed
throw $this->createNotFoundException();
}
return $this->render(
'AcmeBlogBundle:Blog:show.html.php',
array('post' => $post)
);
return $this->render('Blog/show.html.php', array('post' => $post));
}
}
The two controllers are still lightweight. Each uses the :doc:`Doctrine ORM library </book/doctrine>`
to retrieve objects from the database and the Templating component to
render a template and return a ``Response`` object. The list template is
now quite a bit simpler:
The two controllers are still lightweight. Each uses the
:doc:`Doctrine ORM library </book/doctrine>` to retrieve objects from the
database and the Templating component to render a template and return a
``Response`` object. The list template is now quite a bit simpler:
.. code-block:: html+php
<!-- src/Acme/BlogBundle/Resources/views/Blog/list.html.php -->
<?php $view->extend('::layout.html.php') ?>
<!-- app/Resources/views/Blog/list.html.php -->
<?php $view->extend('layout.html.php') ?>
<?php $view['slots']->set('title', 'List of Posts') ?>
@@ -644,11 +638,11 @@ A routing configuration map provides this information in a readable format:
# app/config/routing.yml
blog_list:
path: /blog
defaults: { _controller: AcmeBlogBundle:Blog:list }
defaults: { _controller: AppBundle:Blog:list }
blog_show:
path: /blog/show/{id}
defaults: { _controller: AcmeBlogBundle:Blog:show }
defaults: { _controller: AppBundle:Blog:show }
Now that Symfony is handling all the mundane tasks, the front controller
is dead simple. And since it does so little, you'll never have to touch
@@ -716,8 +710,8 @@ for example, the list template written in Twig:
.. code-block:: html+jinja
{# src/Acme/BlogBundle/Resources/views/Blog/list.html.twig #}
{% extends "::layout.html.twig" %}
{# app/Resources/views/Blog/list.html.twig #}
{% extends "layout.html.twig" %}
{% block title %}List of Posts{% endblock %}
Oops, something went wrong.

0 comments on commit 2c190ed

Please sign in to comment.