Skip to content

Commit

Permalink
feature #4427 Update most important book articles to follow the best …
Browse files Browse the repository at this point in the history
…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 2c190ed
Show file tree
Hide file tree
Showing 5 changed files with 543 additions and 369 deletions.
2 changes: 2 additions & 0 deletions best_practices/templates.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
------------------

Expand Down
116 changes: 53 additions & 63 deletions book/controller.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand All @@ -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>
Expand All @@ -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;
Expand All @@ -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,
Expand All @@ -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
Expand All @@ -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::

Expand All @@ -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
Expand All @@ -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>
Expand All @@ -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',
)));
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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()
{
Expand Down Expand Up @@ -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',
));
Expand All @@ -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::

Expand All @@ -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',
);
Expand Down Expand Up @@ -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
Expand Down
36 changes: 15 additions & 21 deletions book/from_flat_php_to_symfony2.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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') ?>

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 %}

Expand Down
Loading

0 comments on commit 2c190ed

Please sign in to comment.