Skip to content

Updated the example used to explain page creation #3888

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Aug 16, 2014
Merged
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
149 changes: 76 additions & 73 deletions book/page_creation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -61,19 +61,20 @@ cache.
.. index::
single: Page creation; Example

The "Hello Symfony!" Page
-------------------------
The "Random Number" Page
------------------------

Start by building a spin-off of the classic "Hello World!" application. When
you're finished, the user will be able to get a personal greeting (e.g. "Hello Symfony")
by going to the following URL:
In this chapter, you'll develop an application that can generate random numbers.
When you're finished, the user will be able to get a random number between ``1``
and the upper limit set with the URL:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't [...] set by the URL correct?


.. code-block:: text

http://localhost/app_dev.php/hello/Symfony
http://localhost/app_dev.php/random/100

Actually, you'll be able to replace ``Symfony`` with any other name to be
greeted. To create the page, follow the simple two-step process.
Actually, you'll be able to replace ``100`` with any other number to generate
numbers up to that upper limit. To create the page, follow the simple two-step
process.

.. note::

Expand All @@ -97,15 +98,15 @@ A bundle is nothing more than a directory that houses everything related
to a specific feature, including PHP classes, configuration, and even stylesheets
and JavaScript files (see :ref:`page-creation-bundles`).

To create a bundle called ``AcmeHelloBundle`` (a play bundle that you'll
To create a bundle called ``AcmeWebsiteBundle`` (a play bundle that you'll
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe AcmeNumberBundle covers the case better?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I started with the AcmeNumberBundle name, but switched to AcmeWebsiteBundle Why? Because I find "NumberBundle" too specific. We are builing a web application and the "random number" page is just one of its pages. I don't know if other people agree wth this.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really care because it's not really necessary to understand the example. But, why don't we just stick with AcmeDemoBundle which we use in other parts of the documentation?

Or let me say it in other words: I would like to have one bundle name which we use thoroughly in the docs to not confuse readers.

build in this chapter), run the following command and follow the on-screen
instructions (use all of the default options):

.. code-block:: bash

$ php app/console generate:bundle --namespace=Acme/HelloBundle --format=yml
$ php app/console generate:bundle --namespace=Acme/WebsiteBundle --format=yml

Behind the scenes, a directory is created for the bundle at ``src/Acme/HelloBundle``.
Behind the scenes, a directory is created for the bundle at ``src/Acme/WebsiteBundle``.
A line is also automatically added to the ``app/AppKernel.php`` file so that
the bundle is registered with the kernel::

Expand All @@ -114,7 +115,7 @@ the bundle is registered with the kernel::
{
$bundles = array(
...,
new Acme\HelloBundle\AcmeHelloBundle(),
new Acme\WebsiteBundle\AcmeWebsiteBundle(),
);
// ...

Expand All @@ -132,15 +133,15 @@ located at ``app/config/routing.yml``. Like all configuration in Symfony2,
you can also choose to use XML or PHP out of the box to configure routes.

If you look at the main routing file, you'll see that Symfony already added
an entry when you generated the ``AcmeHelloBundle``:
an entry when you generated the ``AcmeWebsiteBundle``:

.. configuration-block::

.. code-block:: yaml

# app/config/routing.yml
acme_hello:
resource: "@AcmeHelloBundle/Resources/config/routing.yml"
acme_website:
resource: "@AcmeWebsiteBundle/Resources/config/routing.yml"
prefix: /

.. code-block:: xml
Expand All @@ -152,7 +153,7 @@ an entry when you generated the ``AcmeHelloBundle``:
xsi:schemaLocation="http://symfony.com/schema/routing
http://symfony.com/schema/routing/routing-1.0.xsd">

<import resource="@AcmeHelloBundle/Resources/config/routing.xml"
<import resource="@AcmeWebsiteBundle/Resources/config/routing.xml"
prefix="/" />
</routes>

Expand All @@ -164,14 +165,14 @@ an entry when you generated the ``AcmeHelloBundle``:

$collection = new RouteCollection();
$collection->addCollection(
$loader->import('@AcmeHelloBundle/Resources/config/routing.php'),
$loader->import('@AcmeWebsiteBundle/Resources/config/routing.php'),
'/'
);

return $collection;

This entry is pretty basic: it tells Symfony to load routing configuration
from the ``Resources/config/routing.yml`` file that lives inside the ``AcmeHelloBundle``.
from the ``Resources/config/routing.yml`` file that lives inside the ``AcmeWebsiteBundle``.
This means that you place routing configuration directly in ``app/config/routing.yml``
or organize your routes throughout your application, and import them from here.

Expand All @@ -182,45 +183,45 @@ the new route that defines the URL of the page that you're about to create:

.. code-block:: yaml

# src/Acme/HelloBundle/Resources/config/routing.yml
hello:
path: /hello/{name}
defaults: { _controller: AcmeHelloBundle:Hello:index }
# src/Acme/WebsiteBundle/Resources/config/routing.yml
random:
path: /random/{limit}
defaults: { _controller: AcmeWebsiteBundle:Random:index }

.. code-block:: xml

<!-- src/Acme/HelloBundle/Resources/config/routing.xml -->
<!-- src/Acme/WebsiteBundle/Resources/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="hello" path="/hello/{name}">
<default key="_controller">AcmeHelloBundle:Hello:index</default>
<route id="random" path="/random/{limit}">
<default key="_controller">AcmeWebsiteBundle:Random:index</default>
</route>
</routes>

.. code-block:: php

// src/Acme/HelloBundle/Resources/config/routing.php
// src/Acme/WebsiteBundle/Resources/config/routing.php
use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Routing\Route;

$collection = new RouteCollection();
$collection->add('hello', new Route('/hello/{name}', array(
'_controller' => 'AcmeHelloBundle:Hello:index',
$collection->add('random', new Route('/random/{limit}', array(
'_controller' => 'AcmeWebsiteBundle:Random:index',
)));

return $collection;

The routing consists of two basic pieces: the ``path``, which is the URL
that this route will match, and a ``defaults`` array, which specifies the
controller that should be executed. The placeholder syntax in the path
(``{name}``) is a wildcard. It means that ``/hello/Ryan``, ``/hello/Fabien``
or any other similar URL will match this route. The ``{name}`` placeholder
(``{limit}``) is a wildcard. It means that ``/number/10``, ``/number/327``
or any other similar URL will match this route. The ``{limit}`` placeholder
parameter will also be passed to the controller so that you can use its value
to personally greet the user.
to generate the proper random number.

.. note::

Expand All @@ -231,20 +232,20 @@ to personally greet the user.
Step 2: Create the Controller
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

When a URL such as ``/hello/Ryan`` is handled by the application, the ``hello``
route is matched and the ``AcmeHelloBundle:Hello:index`` controller is executed
When a URL such as ``/random/10`` is handled by the application, the ``random``
route is matched and the ``AcmeWebsiteBundle:Random:index`` controller is executed
by the framework. The second step of the page-creation process is to create
that controller.

The controller - ``AcmeHelloBundle:Hello:index`` is the *logical* name of
The controller - ``AcmeWebsiteBundle:Random:index`` is the *logical* name of
the controller, and it maps to the ``indexAction`` method of a PHP class
called ``Acme\HelloBundle\Controller\HelloController``. Start by creating this file
inside your ``AcmeHelloBundle``::
called ``Acme\WebsiteBundle\Controller\RandomController``. Start by creating this
file inside your ``AcmeWebsiteBundle``::

// src/Acme/HelloBundle/Controller/HelloController.php
namespace Acme\HelloBundle\Controller;
// src/Acme/WebsiteBundle/Controller/RandomController.php
namespace Acme\WebsiteBundle\Controller;

class HelloController
class RandomController
{
}

Expand All @@ -254,19 +255,19 @@ to build and prepare the resource being requested. Except in some advanced
cases, the end product of a controller is always the same: a Symfony2 ``Response``
object.

Create the ``indexAction`` method that Symfony will execute when the ``hello``
Create the ``indexAction`` method that Symfony will execute when the ``random``
route is matched::

// src/Acme/HelloBundle/Controller/HelloController.php
namespace Acme\HelloBundle\Controller;
// src/Acme/WebsiteBundle/Controller/RandomController.php
namespace Acme\WebsiteBundle\Controller;

use Symfony\Component\HttpFoundation\Response;

class HelloController
class RandomController
{
public function indexAction($name)
public function indexAction($limit)
{
return new Response('<html><body>Hello '.$name.'!</body></html>');
return new Response('<html><body>Number: '.rand(1, $limit).'</body></html>');
}
}

Expand All @@ -276,11 +277,11 @@ page in this example).

Congratulations! After creating only a route and a controller, you already
have a fully-functional page! If you've setup everything correctly, your
application should greet you:
application should generate a random number for you:

.. code-block:: text

http://localhost/app_dev.php/hello/Ryan
http://localhost/app_dev.php/random/10

.. _book-page-creation-prod-cache-clear:

Expand All @@ -291,7 +292,7 @@ application should greet you:

.. code-block:: text

http://localhost/app.php/hello/Ryan
http://localhost/app.php/random/10

If you get an error, it's likely because you need to clear your cache
by running:
Expand All @@ -318,24 +319,26 @@ of writing the HTML inside the controller, render a template instead:
.. code-block:: php
:linenos:

// src/Acme/HelloBundle/Controller/HelloController.php
namespace Acme\HelloBundle\Controller;
// src/Acme/WebsiteBundle/Controller/RandomController.php
namespace Acme\WebsiteBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;

class HelloController extends Controller
class RandomController extends Controller
{
public function indexAction($name)
public function indexAction($limit)
{
$number = rand(1, $limit);

return $this->render(
'AcmeHelloBundle:Hello:index.html.twig',
array('name' => $name)
'AcmeWebsiteBundle:Random:index.html.twig',
array('number' => $number)
);

// render a PHP template instead
// return $this->render(
// 'AcmeHelloBundle:Hello:index.html.php',
// array('name' => $name)
// 'AcmeWebsiteBundle:Random:index.html.php',
// array('number' => $number)
// );
}
}
Expand All @@ -358,7 +361,7 @@ By default, Symfony2 supports two different templating languages: classic
PHP templates and the succinct but powerful `Twig`_ templates. Don't be
alarmed - you're free to choose either or even both in the same project.

The controller renders the ``AcmeHelloBundle:Hello:index.html.twig`` template,
The controller renders the ``AcmeWebsiteBundle:Random:index.html.twig`` template,
which uses the following naming convention:

**BundleName**:**ControllerName**:**TemplateName**
Expand All @@ -368,27 +371,27 @@ location using the following convention.

**/path/to/BundleName**/Resources/views/**ControllerName**/**TemplateName**

In this case, ``AcmeHelloBundle`` is the bundle name, ``Hello`` is the
In this case, ``AcmeWebsiteBundle`` is the bundle name, ``Random`` is the
controller, and ``index.html.twig`` the template:

.. configuration-block::

.. code-block:: jinja
:linenos:

{# src/Acme/HelloBundle/Resources/views/Hello/index.html.twig #}
{# src/Acme/WebsiteBundle/Resources/views/Random/index.html.twig #}
{% extends '::base.html.twig' %}

{% block body %}
Hello {{ name }}!
Number: {{ number }}
{% endblock %}

.. code-block:: html+php

<!-- src/Acme/HelloBundle/Resources/views/Hello/index.html.php -->
<!-- src/Acme/WebsiteBundle/Resources/views/Random/index.html.php -->
<?php $view->extend('::base.html.php') ?>

Hello <?php echo $view->escape($name) ?>!
Number: <?php echo $view->escape($number) ?>

Step through the Twig template line-by-line:

Expand All @@ -414,7 +417,7 @@ and in the ``app`` directory:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>{% block title %}Welcome!{% endblock %}</title>
<title>{% block title %}Random Number Generator{% endblock %}</title>
{% block stylesheets %}{% endblock %}
<link rel="shortcut icon" href="{{ asset('favicon.ico') }}" />
</head>
Expand All @@ -431,7 +434,7 @@ and in the ``app`` directory:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title><?php $view['slots']->output('title', 'Welcome!') ?></title>
<title><?php $view['slots']->output('title', 'Random Number Generator') ?></title>
<?php $view['slots']->output('stylesheets') ?>
<link rel="shortcut icon" href="<?php echo $view['assets']->getUrl('favicon.ico') ?>" />
</head>
Expand Down Expand Up @@ -509,16 +512,16 @@ use a Kernel class, ``AppKernel``, to bootstrap the application.

.. code-block:: text

http://localhost/app.php/hello/Ryan
http://localhost/app.php/random/10

The front controller, ``app.php``, is executed and the "internal:" URL
``/hello/Ryan`` is routed internally using the routing configuration.
``/random/10`` is routed internally using the routing configuration.
By using Apache ``mod_rewrite`` rules, you can force the ``app.php`` file
to be executed without needing to specify it in the URL:

.. code-block:: text

http://localhost/hello/Ryan
http://localhost/random/10

Though front controllers are essential in handling every request, you'll
rarely need to modify or even think about them. They'll be mentioned again
Expand Down Expand Up @@ -570,9 +573,9 @@ You'll learn more about each of these directories in later chapters.
.. code-block:: text

Class Name:
Acme\HelloBundle\Controller\HelloController
Acme\WebsiteBundle\Controller\RandomController
Path:
src/Acme/HelloBundle/Controller/HelloController.php
src/Acme/WebsiteBundle/Controller/RandomController.php

The Source (``src``) Directory
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Expand Down Expand Up @@ -722,10 +725,10 @@ Bundle Directory Structure

The directory structure of a bundle is simple and flexible. By default, the
bundle system follows a set of conventions that help to keep code consistent
between all Symfony2 bundles. Take a look at ``AcmeHelloBundle``, as it contains
between all Symfony2 bundles. Take a look at ``AcmeWebsiteBundle``, as it contains
some of the most common elements of a bundle:

* ``Controller/`` contains the controllers of the bundle (e.g. ``HelloController.php``);
* ``Controller/`` contains the controllers of the bundle (e.g. ``RandomController.php``);

* ``DependencyInjection/`` holds certain dependency injection extension classes,
which may import service configuration, register compiler passes or more
Expand Down Expand Up @@ -907,14 +910,14 @@ the application via the development front controller:

.. code-block:: text

http://localhost/app_dev.php/hello/Ryan
http://localhost/app_dev.php/random/10

If you'd like to see how your application will behave in the production environment,
call the ``prod`` front controller instead:

.. code-block:: text

http://localhost/app.php/hello/Ryan
http://localhost/app.php/random/10

Since the ``prod`` environment is optimized for speed; the configuration,
routing and Twig templates are compiled into flat PHP classes and cached.
Expand Down