diff --git a/book/controller.rst b/book/controller.rst index 4650d9ab948..6089eb7bdd9 100644 --- a/book/controller.rst +++ b/book/controller.rst @@ -202,11 +202,8 @@ Route Parameters as Controller Arguments You already know that the ``_controller`` parameter ``AcmeHelloBundle: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: +passed to that method:: -.. code-block:: php - - Hello '.$name.'!'); + return new Response('Hello '.$name.'!'); } } @@ -375,13 +370,12 @@ itself. Extending the base class is *optional* in Symfony; it contains useful shortcuts but nothing mandatory. You can also extend - ``Symfony\Component\DependencyInjection\ContainerAware``. The service + :class:`Symfony\\Component\\DependencyInjection\\ContainerAware`. The service container object will then be accessible via the ``container`` property. .. note:: - You can also define your :doc:`Controllers as Services - `. + You can also define your :doc:`Controllers as Services`. .. index:: single: Controller; Common tasks @@ -422,9 +416,7 @@ perform a 301 (permanent) redirect, modify the second argument:: .. tip:: The ``redirect()`` method is simply a shortcut that creates a ``Response`` - object that specializes in redirecting the user. It's equivalent to: - - .. code-block:: php + object that specializes in redirecting the user. It's equivalent to:: use Symfony\Component\HttpFoundation\RedirectResponse; diff --git a/book/doctrine.rst b/book/doctrine.rst index 57210da00fb..4ffb9d6abae 100644 --- a/book/doctrine.rst +++ b/book/doctrine.rst @@ -15,9 +15,9 @@ be. Doctrine is totally decoupled from Symfony and using it is optional. This chapter is all about the Doctrine ORM, which aims to let you map - objects to a relational database (such as *MySQL*, *PostgreSQL* or *Microsoft SQL*). - If you prefer to use raw database queries, this is easy, and explained - in the ":doc:`/cookbook/doctrine/dbal`" cookbook entry. + objects to a relational database (such as *MySQL*, *PostgreSQL* or + *Microsoft SQL*). If you prefer to use raw database queries, this is + easy, and explained in the ":doc:`/cookbook/doctrine/dbal`" cookbook entry. You can also persist data to `MongoDB`_ using Doctrine ODM library. For more information, read the ":doc:`/bundles/DoctrineMongoDBBundle/index`" @@ -169,12 +169,6 @@ properties should be *mapped* to the database. This metadata can be specified in a number of different formats including YAML, XML or directly inside the ``Product`` class via annotations: -.. note:: - - A bundle can accept only one metadata definition format. For example, it's - not possible to mix YAML metadata definitions with annotated PHP entity - class definitions. - .. configuration-block:: .. code-block:: php-annotations @@ -251,6 +245,12 @@ in a number of different formats including YAML, XML or directly inside the +.. note:: + + A bundle can accept only one metadata definition format. For example, it's + not possible to mix YAML metadata definitions with annotated PHP entity + class definitions. + .. tip:: The table name is optional and if omitted, will be determined automatically @@ -293,6 +293,7 @@ see the :ref:`book-doctrine-field-types` section. * @IgnoreAnnotation("fn") */ class Product + // ... Generating Getters and Setters ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -316,10 +317,10 @@ doesn't replace your existing methods). With the ``doctrine:generate:entities`` command you can: - * generate getters and setters, + * generate getters and setters; * generate repository classes configured with the - ``@ORM\Entity(repositoryClass="...")`` annotation, + ``@ORM\Entity(repositoryClass="...")`` annotation; * generate the appropriate constructor for 1:n and n:m relations. @@ -420,11 +421,11 @@ of the bundle: Let's walk through this example: * **lines 9-12** In this section, you instantiate and work with the ``$product`` - object like any other, normal PHP object; + object like any other, normal PHP object. * **line 14** This line fetches Doctrine's *entity manager* object, which is responsible for handling the process of persisting and fetching objects - to and from the database; + to and from the database. * **line 15** The ``persist()`` method tells Doctrine to "manage" the ``$product`` object. This does not actually cause a query to be made to the database (yet). @@ -558,9 +559,9 @@ you have a route that maps a product id to an update action in a controller:: Updating an object involves just three steps: -1. fetching the object from Doctrine; -2. modifying the object; -3. calling ``flush()`` on the entity manager +#. fetching the object from Doctrine; +#. modifying the object; +#. calling ``flush()`` on the entity manager Notice that calling ``$em->persist($product)`` isn't necessary. Recall that this method simply tells Doctrine to manage or "watch" the ``$product`` object. @@ -884,7 +885,6 @@ object, you'll want to add a ``$category`` property to the ``Product`` class: // src/Acme/StoreBundle/Entity/Product.php // ... - class Product { // ... diff --git a/book/forms.rst b/book/forms.rst index 6b24d9f1dbb..481689a09db 100644 --- a/book/forms.rst +++ b/book/forms.rst @@ -24,9 +24,7 @@ Creating a Simple Form Suppose you're building a simple todo list application that will need to display "tasks". Because your users will need to edit and create tasks, you're going to need to build a form. But before you begin, first focus on the generic -``Task`` class that represents and stores the data for a single task: - -.. code-block:: php +``Task`` class that represents and stores the data for a single task:: // src/Acme/TaskBundle/Entity/Task.php namespace Acme\TaskBundle\Entity; @@ -742,9 +740,7 @@ Creating Form Classes As you've seen, a form can be created and used directly in a controller. However, a better practice is to build the form in a separate, standalone PHP class, which can then be reused anywhere in your application. Create a new class -that will house the logic for building the task form: - -.. code-block:: php +that will house the logic for building the task form:: // src/Acme/TaskBundle/Form/Type/TaskType.php namespace Acme\TaskBundle\Form\Type; @@ -768,9 +764,7 @@ that will house the logic for building the task form: This new class contains all the directions needed to create the task form (note that the ``getName()`` method should return a unique identifier for this -form "type"). It can be used to quickly build a form object in the controller: - -.. code-block:: php +form "type"). It can be used to quickly build a form object in the controller:: // src/Acme/TaskBundle/Controller/DefaultController.php @@ -1068,7 +1062,7 @@ The ``field_row`` form fragment is used when rendering most fields via the fragment defined above, add the following to the top of the template that renders the form: -.. configuration-block:: php +.. configuration-block:: .. code-block:: html+jinja @@ -1373,7 +1367,7 @@ section. The ``intention`` option is optional but greatly enhances the security of the generated token by making it different for each form. -.. index: +.. index:: single: Forms; With no class Using a Form without a Class @@ -1413,10 +1407,10 @@ By default, a form actually assumes that you want to work with arrays of data, instead of an object. There are exactly two ways that you can change this behavior and tie the form to an object instead: -1. Pass an object when creating the form (as the first argument to ``createFormBuilder`` +#. Pass an object when creating the form (as the first argument to ``createFormBuilder`` or the second argument to ``createForm``); -2. Declare the ``data_class`` option on your form. +#. Declare the ``data_class`` option on your form. If you *don't* do either of these, then the form will return the data as an array. In this example, since ``$defaultData`` is not an object (and @@ -1426,9 +1420,7 @@ an array. .. tip:: You can also access POST values (in this case "name") directly through - the request object, like so: - - .. code-block:: php + the request object, like so:: $this->get('request')->request->get('name'); diff --git a/book/from_flat_php_to_symfony2.rst b/book/from_flat_php_to_symfony2.rst index f624c34eb0d..b825a29848b 100644 --- a/book/from_flat_php_to_symfony2.rst +++ b/book/from_flat_php_to_symfony2.rst @@ -33,7 +33,7 @@ persisted to the database. Writing in flat PHP is quick and dirty: $result = mysql_query('SELECT id, title FROM post', $link); ?> - + List of Posts @@ -70,6 +70,7 @@ to maintain. There are several problems that need to be addressed: way to reuse any part of the application for other "pages" of the blog. .. note:: + Another problem not mentioned here is the fact that the database is tied to MySQL. Though not covered here, Symfony2 fully integrates `Doctrine`_, a library dedicated to database abstraction and mapping. @@ -106,7 +107,7 @@ is primarily an HTML file that uses a template-like PHP syntax: .. code-block:: html+php - + List of Posts @@ -211,6 +212,7 @@ that by creating a new ``layout.php`` file: .. code-block:: html+php + <?php echo $title ?> @@ -366,9 +368,9 @@ on the requested URI: // route the request internally $uri = $_SERVER['REQUEST_URI']; - if ($uri == '/index.php') { + if ('/index.php' == $uri) { list_action(); - } elseif ($uri == '/index.php/show' && isset($_GET['id'])) { + } elseif ('/index.php/show' == $uri && isset($_GET['id'])) { show_action($_GET['id']); } else { header('Status: 404 Not Found'); @@ -466,9 +468,9 @@ the HTTP response being returned. Use them to improve the blog: $request = Request::createFromGlobals(); $uri = $request->getPathInfo(); - if ($uri == '/') { + if ('/' == $uri) { $response = list_action(); - } elseif ($uri == '/show' && $request->query->has('id')) { + } elseif ('/show' == $uri && $request->query->has('id')) { $response = show_action($request->query->get('id')); } else { $html = '

Page Not Found

'; @@ -537,11 +539,8 @@ from scratch, you could at least use Symfony's standalone `Routing`_ and `Templating`_ components, which already solve these problems. Instead of re-solving common problems, you can let Symfony2 take care of -them for you. Here's the same sample application, now built in Symfony2: - -.. code-block:: html+php +them for you. Here's the same sample application, now built in Symfony2:: - get('doctrine') ->getEntityManager() ->getRepository('AcmeBlogBundle:Post') - ->find($id); + ->find($id) + ; if (!$post) { // cause the 404 page not found to be displayed @@ -602,7 +602,7 @@ The layout is nearly identical: .. code-block:: html+php - + <?php echo $view['slots']->output('title', 'Default title') ?> @@ -635,11 +635,8 @@ A routing configuration map provides this information in a readable format: Now that Symfony2 is handling all the mundane tasks, the front controller is dead simple. And since it does so little, you'll never have to touch it once it's created (and if you use a Symfony2 distribution, you won't -even need to create it!): +even need to create it!):: -.. code-block:: html+php - - `, - :doc:`routing`, or rendering :doc:`controllers`. + :doc:`routing`, or rendering :doc:`controllers`; * Symfony2 gives you **access to open source tools** such as Doctrine and the Templating, Security, Form, Validation and Translation components (to name - a few). + a few); * The application now enjoys **fully-flexible URLs** thanks to the ``Routing`` - component. + component; * Symfony2's HTTP-centric architecture gives you access to powerful tools such as **HTTP caching** powered by **Symfony2's internal HTTP cache** or @@ -701,6 +698,7 @@ for example, the list template written in Twig: {# src/Acme/BlogBundle/Resources/views/Blog/list.html.twig #} {% extends "::layout.html.twig" %} + {% block title %}List of Posts{% endblock %} {% block body %} @@ -721,7 +719,7 @@ The corresponding ``layout.html.twig`` template is also easier to write: .. code-block:: html+jinja {# app/Resources/views/layout.html.twig #} - + {% block title %}Default title{% endblock %} diff --git a/book/http_cache.rst b/book/http_cache.rst index e66887e51de..da1fb5f4ca5 100644 --- a/book/http_cache.rst +++ b/book/http_cache.rst @@ -35,26 +35,26 @@ the Symfony2 cache system. For the purposes of learning how to cache with Symfony2, we'll cover the subject in four steps: -* **Step 1**: A :ref:`gateway cache `, or reverse proxy, is - an independent layer that sits in front of your application. The reverse - proxy caches responses as they're returned from your application and answers - requests with cached responses before they hit your application. Symfony2 - provides its own reverse proxy, but any reverse proxy can be used. - -* **Step 2**: :ref:`HTTP cache ` headers are used - to communicate with the gateway cache and any other caches between your - application and the client. Symfony2 provides sensible defaults and a - powerful interface for interacting with the cache headers. - -* **Step 3**: HTTP :ref:`expiration and validation ` - are the two models used for determining whether cached content is *fresh* - (can be reused from the cache) or *stale* (should be regenerated by the - application). - -* **Step 4**: :ref:`Edge Side Includes ` (ESI) allow HTTP - cache to be used to cache page fragments (even nested fragments) independently. - With ESI, you can even cache an entire page for 60 minutes, but an embedded - sidebar for only 5 minutes. +#. A :ref:`gateway cache `, or reverse proxy, is + an independent layer that sits in front of your application. The reverse + proxy caches responses as they're returned from your application and answers + requests with cached responses before they hit your application. Symfony2 + provides its own reverse proxy, but any reverse proxy can be used. + +#. :ref:`HTTP cache ` headers are used + to communicate with the gateway cache and any other caches between your + application and the client. Symfony2 provides sensible defaults and a + powerful interface for interacting with the cache headers. + +#. HTTP :ref:`expiration and validation ` + are the two models used for determining whether cached content is *fresh* + (can be reused from the cache) or *stale* (should be regenerated by the + application). + +#. :ref:`Edge Side Includes ` (ESI) allow HTTP + cache to be used to cache page fragments (even nested fragments) independently. + With ESI, you can even cache an entire page for 60 minutes, but an embedded + sidebar for only 5 minutes. Since caching with HTTP isn't unique to Symfony, many articles already exist on the topic. If you're new to HTTP caching, we *highly* recommend Ryan @@ -100,11 +100,11 @@ different types of caches: * *Browser caches*: Every browser comes with its own local cache that is mainly useful for when you hit "back" or for images and other assets. The browser cache is a *private* cache as cached resources aren't shared - with anyone else. + with anyone else; * *Proxy caches*: A proxy is a *shared* cache as many people can be behind a single one. It's usually installed by large corporations and ISPs to reduce - latency and network traffic. + latency and network traffic; * *Gateway caches*: Like a proxy, it's also a *shared* cache but on the server side. Installed by network administrators, it makes websites more scalable, @@ -168,7 +168,8 @@ from your application and returning them to the client. error_log($kernel->getLog()); The ``AppCache`` object has a sensible default configuration, but it can be -finely tuned via a set of options you can set by overriding the ``getOptions()`` +finely tuned via a set of options you can set by overriding the +:method:`Symfony\\Bundle\\FrameworkBundle\\HttpCache\\HttpCache:getOptions` method:: // app/AppCache.php @@ -303,9 +304,9 @@ information is separated by a comma: Cache-Control: max-age=3600, must-revalidate Symfony provides an abstraction around the ``Cache-Control`` header to make -its creation more manageable: +its creation more manageable:: -.. code-block:: php + // ... $response = new Response(); @@ -355,7 +356,7 @@ This has two very reasonable consequences: * You should *never* change the state of your application when responding to a GET or HEAD request. Even if you don't use a gateway cache, the presence of proxy caches mean that any GET or HEAD request may or may not actually - hit your server. + hit your server; * Don't expect PUT, POST or DELETE methods to cache. These methods are meant to be used when mutating the state of your application (e.g. deleting a @@ -394,7 +395,7 @@ The HTTP specification defines two caching models: * With the `expiration model`_, you simply specify how long a response should be considered "fresh" by including a ``Cache-Control`` and/or an ``Expires`` header. Caches that understand expiration will not make the same request - until the cached version reaches its expiration time and becomes "stale". + until the cached version reaches its expiration time and becomes "stale"; * When pages are really dynamic (i.e. their representation changes often), the `validation model`_ is often necessary. With this model, the @@ -456,7 +457,9 @@ header can be set with the ``setExpires()`` ``Response`` method. It takes a $response->setExpires($date); -The resulting HTTP header will look like this:: +The resulting HTTP header will look like this: + +.. code-block:: text Expires: Thu, 01 Mar 2011 16:00:00 GMT @@ -494,7 +497,9 @@ shared caches:: $response->setSharedMaxAge(600); The ``Cache-Control`` header would take on the following format (it may have -additional directives):: +additional directives): + +.. code-block:: text Cache-Control: max-age=600, s-maxage=600 @@ -559,9 +564,10 @@ md5 of the content:: return $response; } -The ``Response::isNotModified()`` method compares the ``ETag`` sent with -the ``Request`` with the one set on the ``Response``. If the two match, the -method automatically sets the ``Response`` status code to 304. +The :method:`Symfony\\Component\\HttpFoundation\\Response::isNotModified` +method compares the ``ETag`` sent with the ``Request`` with the one set +on the ``Response``. If the two match, the method automatically sets the +``Response`` status code to 304. This algorithm is simple enough and very generic, but you need to create the whole ``Response`` before being able to compute the ETag, which is sub-optimal. @@ -612,15 +618,15 @@ header value:: return $response; } - // do more work to populate the response will the full content + // ... do more work to populate the response will the full content return $response; } -The ``Response::isNotModified()`` method compares the ``If-Modified-Since`` -header sent by the request with the ``Last-Modified`` header set on the -response. If they are equivalent, the ``Response`` will be set to a 304 status -code. +The :method:`Symfony\\Component\\HttpFoundation\\Response::isNotModified` +method compares the ``If-Modified-Since`` header sent by the request with +the ``Last-Modified`` header set on the response. If they are equivalent, +the ``Response`` will be set to a 304 status code. .. note:: @@ -703,7 +709,9 @@ In this case, we need the cache to store both a compressed and uncompressed version of the response for the particular URI and return them based on the request's ``Accept-Encoding`` value. This is done by using the ``Vary`` response header, which is a comma-separated list of different headers whose values -trigger a different representation of the requested resource:: +trigger a different representation of the requested resource: + +.. code-block:: text Vary: Accept-Encoding, User-Agent @@ -750,7 +758,7 @@ the most useful ones:: $response->setNotModified(); Additionally, most cache-related HTTP headers can be set via the single -``setCache()`` method:: +:method:`Symfony\\Component\\HttpFoundation\\Response::setCache` method:: // Set cache settings in one call $response->setCache(array( @@ -785,15 +793,15 @@ as this is the only useful one outside of Akamaï context: .. code-block:: html - + - ... some content + - ... more content + @@ -1012,6 +1020,7 @@ Here is how you can configure the Symfony2 reverse proxy to support the // app/AppCache.php + // ... use Symfony\Bundle\FrameworkBundle\HttpCache\HttpCache; class AppCache extends HttpCache diff --git a/book/http_fundamentals.rst b/book/http_fundamentals.rst index 66b6ad54303..4160d209d12 100644 --- a/book/http_fundamentals.rst +++ b/book/http_fundamentals.rst @@ -179,11 +179,8 @@ Requests and Responses in PHP ----------------------------- So how do you interact with the "request" and create a "response" when using -PHP? In reality, PHP abstracts you a bit from the whole process: +PHP? In reality, PHP abstracts you a bit from the whole process:: -.. code-block:: php - - + AcmeBlogBundle:Main:contact + + + .. code-block:: php + + // app/config/routing.php + use Symfony\Component\Routing\RouteCollection; + use Symfony\Component\Routing\Route; + + $collection = new RouteCollection(); + $collection->add('contact', new Route('/contact', array( + '_controller' => 'AcmeBlogBundle:Main:contact', + ))); + + return $collection; .. note:: @@ -437,10 +454,9 @@ by adding an entry for ``/contact`` to your routing configuration file: When someone visits the ``/contact`` page, this route is matched, and the specified controller is executed. As you'll learn in the :doc:`routing chapter`, the ``AcmeDemoBundle:Main:contact`` string is a short syntax that points to a -specific PHP method ``contactAction`` inside a class called ``MainController``: - -.. code-block:: php +specific PHP method ``contactAction`` inside a class called ``MainController``:: + // src/Acme/DemoBundle/Controller/MainController.php class MainController { public function contactAction() @@ -449,8 +465,9 @@ specific PHP method ``contactAction`` inside a class called ``MainController``: } } -In this very simple example, the controller simply creates a ``Response`` -object with the HTML "

Contact us!

". In the :doc:`controller chapter`, +In this very simple example, the controller simply creates a +:class:`Symfony\\Component\\HttpFoundation\\Response` object with the HTML +"``

Contact us!

"``. In the :doc:`controller chapter`, you'll learn how a controller can render templates, allowing your "presentation" code (i.e. anything that actually writes out HTML) to live in a separate template file. This frees up the controller to worry only about the hard @@ -522,7 +539,7 @@ So then, what *is* the Symfony2 *Framework*? The *Symfony2 Framework* is a PHP library that accomplishes two distinct tasks: #. Provides a selection of components (i.e. the Symfony2 Components) and - third-party libraries (e.g. ``Swiftmailer`` for sending emails); + third-party libraries (e.g. `Swiftmailer`_ for sending emails); #. Provides sensible configuration and a "glue" library that ties all of these pieces together. @@ -548,3 +565,4 @@ sensible defaults. For more advanced users, the sky is the limit. .. _`Validator`: https://github.com/symfony/Validator .. _`Security`: https://github.com/symfony/Security .. _`Translation`: https://github.com/symfony/Translation +.. _`Swiftmailer`: http://swiftmailer.org/ diff --git a/book/installation.rst b/book/installation.rst index 97c8f13660d..7449433fef6 100644 --- a/book/installation.rst +++ b/book/installation.rst @@ -157,9 +157,7 @@ If there are any issues, correct them now before moving on. be group-writable or world-writable (depending if the web server user and the command line user are in the same group or not). To achieve this, put the following line at the beginning of the ``app/console``, - ``web/app.php`` and ``web/app_dev.php`` files: - - .. code-block:: php + ``web/app.php`` and ``web/app_dev.php`` files:: umask(0002); // This will let the permissions be 0775 diff --git a/book/internals.rst b/book/internals.rst index bc4f0134380..cae95a161ac 100644 --- a/book/internals.rst +++ b/book/internals.rst @@ -110,8 +110,7 @@ method returns the Controller (a PHP callable) associated with the given Request. The default implementation (:class:`Symfony\\Component\\HttpKernel\\Controller\\ControllerResolver`) looks for a ``_controller`` request attribute that represents the controller -name (a "class::method" string, like -``Bundle\BlogBundle\PostController:indexAction``). +name (a "class::method" string, like ``Bundle\BlogBundle\PostController:indexAction``). .. tip:: @@ -144,32 +143,33 @@ the Request attributes. Handling Requests ~~~~~~~~~~~~~~~~~ -The ``handle()`` method takes a ``Request`` and *always* returns a ``Response``. -To convert the ``Request``, ``handle()`` relies on the Resolver and an ordered -chain of Event notifications (see the next section for more information about -each Event): +The :method:`Symfony\\Component\\HttpKernel\\HttpKernel::handle` method +takes a ``Request`` and *always* returns a ``Response``. To convert the +``Request``, ``handle()`` relies on the Resolver and an ordered chain of +Event notifications (see the next section for more information about each +Event): -1. Before doing anything else, the ``kernel.request`` event is notified -- if +#. Before doing anything else, the ``kernel.request`` event is notified -- if one of the listeners returns a ``Response``, it jumps to step 8 directly; -2. The Resolver is called to determine the Controller to execute; +#. The Resolver is called to determine the Controller to execute; -3. Listeners of the ``kernel.controller`` event can now manipulate the +#. Listeners of the ``kernel.controller`` event can now manipulate the Controller callable the way they want (change it, wrap it, ...); -4. The Kernel checks that the Controller is actually a valid PHP callable; +#. The Kernel checks that the Controller is actually a valid PHP callable; -5. The Resolver is called to determine the arguments to pass to the Controller; +#. The Resolver is called to determine the arguments to pass to the Controller; -6. The Kernel calls the Controller; +#. The Kernel calls the Controller; -7. If the Controller does not return a ``Response``, listeners of the +#. If the Controller does not return a ``Response``, listeners of the ``kernel.view`` event can convert the Controller return value to a ``Response``; -8. Listeners of the ``kernel.response`` event can manipulate the ``Response`` +#. Listeners of the ``kernel.response`` event can manipulate the ``Response`` (content and headers); -9. The Response is returned. +#. The Response is returned. If an Exception is thrown during processing, the ``kernel.exception`` is notified and listeners are given a chance to convert the Exception to a @@ -206,12 +206,15 @@ Each event thrown by the Kernel is a subclass of :class:`Symfony\\Component\\HttpKernel\\Event\\KernelEvent`. This means that each event has access to the same basic information: -* ``getRequestType()`` - returns the *type* of the request - (``HttpKernelInterface::MASTER_REQUEST`` or ``HttpKernelInterface::SUB_REQUEST``); +* :method:`Symfony\\Component\\HttpKernel\\Event\\KernelEvent::getRequestType` + - returns the *type* of the request (``HttpKernelInterface::MASTER_REQUEST`` + or ``HttpKernelInterface::SUB_REQUEST``); -* ``getKernel()`` - returns the Kernel handling the request; +* :method:`Symfony\\Component\\HttpKernel\\Event\\KernelEvent::getKernel` + - returns the Kernel handling the request; -* ``getRequest()`` - returns the current ``Request`` being handled. +* :method:`Symfony\\Component\\HttpKernel\\Event\\KernelEvent::getRequest` + - returns the current ``Request`` being handled. ``getRequestType()`` .................... @@ -264,9 +267,7 @@ the ``Request`` and determine the Controller name (stored in the *Event Class*: :class:`Symfony\\Component\\HttpKernel\\Event\\FilterControllerEvent` This event is not used by ``FrameworkBundle``, but can be an entry point used -to modify the controller that should be executed: - -.. code-block:: php +to modify the controller that should be executed:: use Symfony\Component\HttpKernel\Event\FilterControllerEvent; @@ -302,7 +303,8 @@ The value returned by the Controller is accessible via the { $val = $event->getControllerResult(); $response = new Response(); - // some how customize the Response from the return value + + // ... some how customize the Response from the return value $event->setResponse($response); } @@ -316,13 +318,12 @@ The value returned by the Controller is accessible via the *Event Class*: :class:`Symfony\\Component\\HttpKernel\\Event\\FilterResponseEvent` The purpose of this event is to allow other systems to modify or replace the -``Response`` object after its creation: - -.. code-block:: php +``Response`` object after its creation:: public function onKernelResponse(FilterResponseEvent $event) { $response = $event->getResponse(); + // ... modify the response object } @@ -358,9 +359,7 @@ forwards the ``Request`` to a given Controller (the value of the ``class::method`` notation). A listener on this event can create and set a ``Response`` object, create -and set a new ``Exception`` object, or do nothing: - -.. code-block:: php +and set a new ``Exception`` object, or do nothing:: use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; use Symfony\Component\HttpFoundation\Response; @@ -466,7 +465,8 @@ HTTP header of the Response:: want to get the token for an Ajax request, use a tool like Firebug to get the value of the ``X-Debug-Token`` HTTP header. -Use the ``find()`` method to access tokens based on some criteria:: +Use the :method:`Symfony\\Component\\HttpKernel\\Profiler\\Profiler::find` +method to access tokens based on some criteria:: // get the latest 10 tokens $tokens = $container->get('profiler')->find('', '', 10); @@ -478,8 +478,9 @@ Use the ``find()`` method to access tokens based on some criteria:: $tokens = $container->get('profiler')->find('127.0.0.1', '', 10); If you want to manipulate profiling data on a different machine than the one -where the information were generated, use the ``export()`` and ``import()`` -methods:: +where the information were generated, use the +:method:`Symfony\\Component\\HttpKernel\\Profiler\\Profiler::export` and +:method:`Symfony\\Component\\HttpKernel\\Profiler\\Profiler::import` methods:: // on the production machine $profile = $container->get('profiler')->loadProfile($token); diff --git a/book/page_creation.rst b/book/page_creation.rst index 02f362aaa20..ba67a5a44e0 100644 --- a/book/page_creation.rst +++ b/book/page_creation.rst @@ -49,8 +49,8 @@ greeted. To create the page, follow the simple two-step process. on this process, see the documentation on the web server you are using. Here's the relevant documentation page for some web server you might be using: - * For Apache HTTP Server, refer to `Apache's DirectoryIndex documentation`_. - * For Nginx, refer to `Nginx HttpCoreModule location documentation`_. + * For Apache HTTP Server, refer to `Apache's DirectoryIndex documentation`_ + * For Nginx, refer to `Nginx HttpCoreModule location documentation`_ Before you begin: Create the Bundle ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -299,9 +299,10 @@ of writing the HTML inside the controller, render a template instead: .. note:: - In order to use the ``render()`` method, your controller must extend the - ``Symfony\Bundle\FrameworkBundle\Controller\Controller`` class (API - docs: :class:`Symfony\\Bundle\\FrameworkBundle\\Controller\\Controller`), + In order to use the :method:`Symfony\\Bundle\\FrameworkBundle\\Controller\\Controller::render` + method, your controller must extend the + :class:`Symfony\\Bundle\\FrameworkBundle\\Controller\\Controller` class + (API docs: :class:`Symfony\\Bundle\\FrameworkBundle\\Controller\\Controller`), which adds shortcuts for tasks that are common inside controllers. This is done in the above example by adding the ``use`` statement on line 4 and then extending ``Controller`` on line 6. @@ -868,9 +869,11 @@ call the ``prod`` front controller instead: Since the ``prod`` environment is optimized for speed; the configuration, routing and Twig templates are compiled into flat PHP classes and cached. When viewing changes in the ``prod`` environment, you'll need to clear these -cached files and allow them to rebuild:: +cached files and allow them to rebuild: - php app/console cache:clear --env=prod --no-debug +.. code-block:: bash + + $ php app/console cache:clear --env=prod --no-debug .. note:: @@ -967,24 +970,24 @@ hopefully discovered how easy and flexible it can be. And while there are *a lot* of features still to come, be sure to keep the following basic points in mind: -* creating a page is a three-step process involving a **route**, a **controller** - and (optionally) a **template**. +* Creating a page is a three-step process involving a **route**, a **controller** + And (optionally) a **template**; -* each project contains just a few main directories: ``web/`` (web assets and - the front controllers), ``app/`` (configuration), ``src/`` (your bundles), - and ``vendor/`` (third-party code) (there's also a ``bin/`` directory that's - used to help updated vendor libraries); +* Each project contains just a few main directories: ``web/`` (web assets and + The front controllers), ``app/`` (configuration), ``src/`` (your bundles), + And ``vendor/`` (third-party code) (there's also a ``bin/`` directory that's + Used to help updated vendor libraries); -* each feature in Symfony2 (including the Symfony2 framework core) is organized - into a *bundle*, which is a structured set of files for that feature; +* Each feature in Symfony2 (including the Symfony2 framework core) is organized + Into a *bundle*, which is a structured set of files for that feature; -* the **configuration** for each bundle lives in the ``Resources/config`` - directory of the bundle and can be specified in YAML, XML or PHP; +* The **configuration** for each bundle lives in the ``Resources/config`` + Directory of the bundle and can be specified in YAML, XML or PHP; -* the global **application configuration** lives in the ``app/config`` - directory; +* The global **application configuration** lives in the ``app/config`` + Directory; -* each **environment** is accessible via a different front controller (e.g. +* Each **environment** is accessible via a different front controller (e.g. ``app.php`` and ``app_dev.php``) and loads a different configuration file. From here, each chapter will introduce you to more and more powerful tools diff --git a/book/performance.rst b/book/performance.rst index cee46849e6d..4a8a4de3a7a 100644 --- a/book/performance.rst +++ b/book/performance.rst @@ -59,9 +59,7 @@ the first time. Symfony comes with a class - ``ApcUniversalClassLoader`` - loader that extends the ``UniversalClassLoader`` and stores the class locations in APC. -To use this class loader, simply adapt your ``autoloader.php`` as follows: - -.. code-block:: php +To use this class loader, simply adapt your ``autoloader.php`` as follows:: // app/autoload.php require __DIR__.'/../vendor/symfony/src/Symfony/Component/ClassLoader/ApcUniversalClassLoader.php'; diff --git a/book/propel.rst b/book/propel.rst index 915f6554270..bcd56b2b932 100644 --- a/book/propel.rst +++ b/book/propel.rst @@ -397,7 +397,6 @@ To add a hook, just add a new method to the object class:: // src/Acme/StoreBundle/Model/Product.php // ... - class Product extends BaseProduct { public function preInsert(\PropelPDO $con = null) diff --git a/book/routing.rst b/book/routing.rst index 61385ff42e0..e2963c1074b 100644 --- a/book/routing.rst +++ b/book/routing.rst @@ -75,9 +75,7 @@ for you to use in your controller (keep reading). The ``_controller`` parameter is a special key that tells Symfony which controller should be executed when a URL matches this route. The ``_controller`` string is called the :ref:`logical name`. It follows a -pattern that points to a specific PHP class and method: - -.. code-block:: php +pattern that points to a specific PHP class and method:: // src/Acme/BlogBundle/Controller/BlogController.php namespace Acme\BlogBundle\Controller; @@ -813,9 +811,7 @@ For example, a ``_controller`` value of ``AcmeBlogBundle:Blog:show`` means: | AcmeBlogBundle | BlogController | showAction | +----------------+------------------+-------------+ -The controller might look like this: - -.. code-block:: php +The controller might look like this:: // src/Acme/BlogBundle/Controller/BlogController.php namespace Acme\BlogBundle\Controller; @@ -849,9 +845,7 @@ Route Parameters and Controller Arguments ----------------------------------------- The route parameters (e.g. ``{slug}``) are especially important because -each is made available as an argument to the controller method: - -.. code-block:: php +each is made available as an argument to the controller method:: public function showAction($slug) { @@ -1076,9 +1070,7 @@ system. Take the ``blog_show`` example route from earlier:: To generate a URL, you need to specify the name of the route (e.g. ``blog_show``) and any wildcards (e.g. ``slug = my-blog-post``) used in the pattern for -that route. With this information, any URL can easily be generated: - -.. code-block:: php +that route. With this information, any URL can easily be generated:: class MainController extends Controller { @@ -1112,9 +1104,7 @@ Generating Absolute URLs By default, the router will generate relative URLs (e.g. ``/blog``). To generate an absolute URL, simply pass ``true`` to the third argument of the ``generate()`` -method: - -.. code-block:: php +method:: $router->generate('blog_show', array('slug' => 'my-blog-post'), true); // http://www.example.com/blog/my-blog-post @@ -1125,9 +1115,7 @@ method: the current ``Request`` object. This is detected automatically based on server information supplied by PHP. When generating absolute URLs for scripts run from the command line, you'll need to manually set the desired - host on the ``RequestContext`` object: - - .. code-block:: php + host on the ``RequestContext`` object:: $router->getContext()->setHost('www.example.com'); diff --git a/book/security.rst b/book/security.rst index 5a8f9d5e1c4..26d281993ad 100644 --- a/book/security.rst +++ b/book/security.rst @@ -24,7 +24,7 @@ Since the best way to learn is to see an example, let's dive right in. .. note:: - Symfony's `security component`_ is available as a standalone PHP library + `Symfony's security component`_ is available as a standalone PHP library for use inside any PHP project. Basic Example: HTTP Authentication @@ -407,9 +407,7 @@ is that the URL of the route (``/login``) matches the ``login_path`` config value, as that's where the security system will redirect users that need to login. -Next, create the controller that will display the login form: - -.. code-block:: php +Next, create the controller that will display the login form:: // src/Acme/SecurityBundle/Controller/SecurityController.php; namespace Acme\SecurityBundle\Controller; @@ -810,9 +808,7 @@ Securing a Controller Protecting your application based on URL patterns is easy, but may not be fine-grained enough in certain cases. When necessary, you can easily force -authorization from inside a controller: - -.. code-block:: php +authorization from inside a controller:: // ... use Symfony\Component\Security\Core\Exception\AccessDeniedException; @@ -829,9 +825,7 @@ authorization from inside a controller: .. _book-security-securing-controller-annotations: You can also choose to install and use the optional ``JMSSecurityExtraBundle``, -which can secure your controller using annotations: - -.. code-block:: php +which can secure your controller using annotations:: // ... use JMS\SecurityExtraBundle\Annotation\Secure; @@ -973,7 +967,7 @@ Loading Users from the Database If you'd like to load your users via the Doctrine ORM, you can easily do this by creating a ``User`` class and configuring the ``entity`` provider. -.. tip: +.. tip:: A high-quality open source bundle is available that allows your users to be stored via the Doctrine ORM or ODM. Read more about the `FOSUserBundle`_ @@ -1178,9 +1172,7 @@ from the hashed password). If you have some sort of registration form for users, you'll need to be able to determine the hashed password so that you can set it on your user. No matter what algorithm you configure for your user object, the hashed password -can always be determined in the following way from a controller: - -.. code-block:: php +can always be determined in the following way from a controller:: $factory = $this->get('security.encoder_factory'); $user = new Acme\UserBundle\Entity\User(); @@ -1194,9 +1186,7 @@ Retrieving the User Object After authentication, the ``User`` object of the current user can be accessed via the ``security.context`` service. From inside a controller, this will -look like: - -.. code-block:: php +look like:: public function indexAction() { @@ -1220,6 +1210,10 @@ method:

Username: {{ app.user.username }}

+ .. code-block:: html+php + +

Username: getUser()->getUsername() ?>

+ Using Multiple User Providers ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -1576,17 +1570,17 @@ Access Control in Controllers ----------------------------- If you want to check if the current user has a role in your controller, use -the ``isGranted`` method of the security context: - -.. code-block:: php +the :method:`Symfony\\Component\\Security\\Core\\SecurityContext::isGranted` +method of the security context:: public function indexAction() { // show different content to admin users if ($this->get('security.context')->isGranted('ROLE_ADMIN')) { - // Load admin content here + // ... load admin content here } - // load other regular content here + + // ... load other regular content here } .. note:: @@ -1638,10 +1632,14 @@ done by activating the ``switch_user`` firewall listener: To switch to another user, just add a query string with the ``_switch_user`` parameter and the username as the value to the current URL: +.. code-block:: text + http://example.com/somewhere?_switch_user=thomas To switch back to the original user, use the special ``_exit`` username: +.. code-block:: text + http://example.com/somewhere?_switch_user=_exit Of course, this feature needs to be made available to a small group of users. @@ -1658,7 +1656,7 @@ setting: security: firewalls: main: - // ... + # ... switch_user: { role: ROLE_ADMIN, parameter: _want_to_be_this_user } .. code-block:: xml @@ -1677,7 +1675,7 @@ setting: $container->loadFromExtension('security', array( 'firewalls' => array( 'main'=> array( - // ... + ..., 'switch_user' => array('role' => 'ROLE_ADMIN', 'parameter' => '_want_to_be_this_user'), ), ), diff --git a/book/service_container.rst b/book/service_container.rst index 27d942834b3..7c0e9d692ca 100644 --- a/book/service_container.rst +++ b/book/service_container.rst @@ -71,9 +71,7 @@ A :term:`Service Container` (or *dependency injection container*) is simply a PHP object that manages the instantiation of services (i.e. objects). For example, suppose we have a simple PHP class that delivers email messages. Without a service container, we must manually create the object whenever -we need it: - -.. code-block:: php +we need it:: use Acme\HelloBundle\Mailer; @@ -491,7 +489,7 @@ invokes the service container extension inside the ``FrameworkBundle``: 'form' => array(), 'csrf-protection' => array(), 'router' => array('resource' => '%kernel.root_dir%/config/routing.php'), - // ... + ..., )); When the configuration is parsed, the container looks for an extension that @@ -780,9 +778,7 @@ it exists and do nothing if it doesn't: In YAML, the special ``@?`` syntax tells the service container that the dependency is optional. Of course, the ``NewsletterManager`` must also be written to -allow for an optional dependency: - -.. code-block:: php +allow for an optional dependency:: public function __construct(Mailer $mailer = null) { diff --git a/book/templating.rst b/book/templating.rst index 363f926b9b9..feee1ee8419 100644 --- a/book/templating.rst +++ b/book/templating.rst @@ -333,18 +333,18 @@ are organized inside a Symfony2 project. 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. + 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. + 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 :ref:`including-templates`). + and ``include`` it (see :ref:`including-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 @@ -354,7 +354,9 @@ When working with template inheritance, here are some tips to keep in mind: {% block sidebar %}

Table of Contents

- ... + + {# ... #} + {{ parent() }} {% endblock %} @@ -569,7 +571,6 @@ template. First, create a controller that renders a certain number of recent articles:: // src/Acme/ArticleBundle/Controller/ArticleController.php - class ArticleController extends Controller { public function recentArticlesAction($max = 3) @@ -619,7 +620,6 @@ syntax for controllers (i.e. **bundle**:**controller**:**action**): {# app/Resources/views/base.html.twig #} {# ... #} - @@ -628,8 +628,7 @@ syntax for controllers (i.e. **bundle**:**controller**:**action**): - {# ... #} - + @@ -821,7 +820,7 @@ stylesheets and Javascripts that you'll need throughout your site: .. code-block:: html+jinja - {# 'app/Resources/views/base.html.twig' #} + {# app/Resources/views/base.html.twig #} {# ... #} @@ -927,7 +926,7 @@ you're actually using the templating engine service. For example:: return $this->render('AcmeArticleBundle:Article:index.html.twig'); -is equivalent to: +is equivalent to:: $engine = $this->container->get('templating'); $content = $engine->render('AcmeArticleBundle:Article:index.html.twig'); @@ -960,8 +959,8 @@ configuration file: // app/config/config.php $container->loadFromExtension('framework', array( - // ... - 'templating' => array( + ..., + 'templating' => array( 'engines' => array('twig'), ), )); @@ -1074,32 +1073,32 @@ covered: would have a template called ``AcmeBlogBundle::layout.html.twig`` that contains only blog section-specific elements; - .. code-block:: html+jinja + .. code-block:: html+jinja - {# src/Acme/BlogBundle/Resources/views/layout.html.twig #} - {% extends '::base.html.twig' %} + {# src/Acme/BlogBundle/Resources/views/layout.html.twig #} + {% extends '::base.html.twig' %} - {% block body %} -

Blog Application

+ {% block body %} +

Blog Application

- {% block content %}{% endblock %} - {% endblock %} + {% block content %}{% endblock %} + {% endblock %} * Create individual templates for each page and make each extend the appropriate section template. For example, the "index" page would be called something close to ``AcmeBlogBundle:Blog:index.html.twig`` and list the actual blog posts. - .. code-block:: html+jinja + .. code-block:: html+jinja - {# src/Acme/BlogBundle/Resources/views/Blog/index.html.twig #} - {% extends 'AcmeBlogBundle::layout.html.twig' %} + {# src/Acme/BlogBundle/Resources/views/Blog/index.html.twig #} + {% extends 'AcmeBlogBundle::layout.html.twig' %} - {% block content %} - {% for entry in blog_entries %} -

{{ entry.title }}

-

{{ entry.body }}

- {% endfor %} - {% endblock %} + {% block content %} + {% for entry in blog_entries %} +

{{ entry.title }}

+

{{ entry.body }}

+ {% endfor %} + {% endblock %} Notice that this template extends the section template -(``AcmeBlogBundle::layout.html.twig``) which in-turn extends the base application layout (``::base.html.twig``). diff --git a/book/testing.rst b/book/testing.rst index 990b75da287..ff4d869d61a 100644 --- a/book/testing.rst +++ b/book/testing.rst @@ -654,7 +654,6 @@ configuration option: # app/config/config_test.yml # ... - swiftmailer: disable_delivery: true @@ -663,7 +662,6 @@ configuration option: - @@ -672,9 +670,8 @@ configuration option: // app/config/config_test.php // ... - $container->loadFromExtension('swiftmailer', array( - 'disable_delivery' => true + 'disable_delivery' => true, )); You can also use a different environment entirely, or override the default @@ -744,6 +741,7 @@ section: .. code-block:: xml + ../src diff --git a/book/translation.rst b/book/translation.rst index cbf522e9b40..a0f481a7267 100644 --- a/book/translation.rst +++ b/book/translation.rst @@ -29,14 +29,14 @@ In this chapter, we'll learn how to prepare an application to support multiple locales and then how to create translations for multiple locales. Overall, the process has several common steps: -1. Enable and configure Symfony's ``Translation`` component; +#. Enable and configure Symfony's ``Translation`` component; -2. Abstract strings (i.e. "messages") by wrapping them in calls to the ``Translator``; +#. Abstract strings (i.e. "messages") by wrapping them in calls to the ``Translator``; -3. Create translation resources for each supported locale that translate +#. Create translation resources for each supported locale that translate each message in the application; -4. Determine, set and manage the user's locale in the session. +#. Determine, set and manage the user's locale in the session. .. index:: single: Translations; Configuration @@ -92,9 +92,7 @@ Translation of text is done through the ``translator`` service (:class:`Symfony\\Component\\Translation\\Translator`). To translate a block of text (called a *message*), use the :method:`Symfony\\Component\\Translation\\Translator::trans` method. Suppose, -for example, that we're translating a simple message from inside a controller: - -.. code-block:: php +for example, that we're translating a simple message from inside a controller:: public function indexAction() { @@ -167,9 +165,7 @@ the appropriate message catalog and returns it (if it exists). Message Placeholders ~~~~~~~~~~~~~~~~~~~~ -Sometimes, a message containing a variable needs to be translated: - -.. code-block:: php +Sometimes, a message containing a variable needs to be translated:: public function indexAction($name) { @@ -182,9 +178,7 @@ However, creating a translation for this string is impossible since the translat will try to look up the exact message, including the variable portions (e.g. "Hello Ryan" or "Hello Fabien"). Instead of writing a translation for every possible iteration of the ``$name`` variable, we can replace the -variable with a "placeholder": - -.. code-block:: php +variable with a "placeholder":: public function indexAction($name) { @@ -235,10 +229,10 @@ is done just as before: As we've seen, creating a translation is a two-step process: -1. Abstract the message that needs to be translated by processing it through +#. Abstract the message that needs to be translated by processing it through the ``Translator``. -2. Create a translation for the message in each locale that you choose to +#. Create a translation for the message in each locale that you choose to support. The second step is done by creating message catalogues that define the translations @@ -256,6 +250,8 @@ catalogue is like a dictionary of translations for a specific locale. For example, the catalogue for the ``fr_FR`` locale might contain the following translation: +.. code-block:: text + Symfony2 is Great => J'aime Symfony2 It's the responsibility of the developer (or translator) of an internationalized @@ -369,9 +365,7 @@ Symfony2 will discover these files and use them when translating either .. sidebar:: Using Real or Keyword Messages This example illustrates the two different philosophies when creating - messages to be translated: - - .. code-block:: php + messages to be translated:: $t = $translator->trans('Symfony2 is great'); @@ -468,9 +462,7 @@ files: * ``navigation.fr.xliff`` When translating strings that are not in the default domain (``messages``), -you must specify the domain as the third argument of ``trans()``: - -.. code-block:: php +you must specify the domain as the third argument of ``trans()``:: $this->get('translator')->trans('Symfony2 is great', array(), 'admin'); @@ -484,9 +476,7 @@ Handling the User's Locale -------------------------- The locale of the current user is stored in the session and is accessible -via the ``session`` service: - -.. code-block:: php +via the ``session`` service:: $locale = $this->get('session')->getLocale(); @@ -571,7 +561,7 @@ by the routing system using the special ``_locale`` parameter: '_controller' => 'AcmeDemoBundle:Contact:index', '_locale' => 'en', ), array( - '_locale' => 'en|fr|de' + '_locale' => 'en|fr|de', ))); return $collection; @@ -606,9 +596,7 @@ all the forms as a string separated by a pipe (``|``):: 'There is one apple|There are %count% apples' To translate pluralized messages, use the -:method:`Symfony\\Component\\Translation\\Translator::transChoice` method: - -.. code-block:: php +:method:`Symfony\\Component\\Translation\\Translator::transChoice` method:: $t = $this->get('translator')->transChoice( 'There is one apple|There are %count% apples', @@ -650,7 +638,7 @@ used to determine which plural form to use. The tags can be any descriptive string that ends with a colon (``:``). The tags also do not need to be the same in the original message as in the translated one. -.. tip: +.. tip:: As tags are optional, the translator doesn't use them (the translator will only get a string based on its position in the string). @@ -795,9 +783,7 @@ Forcing the Translator Locale When translating a message, Symfony2 uses the locale from the user's session or the ``fallback`` locale if necessary. You can also manually specify the -locale to use for translation: - -.. code-block:: php +locale to use for translation:: $this->get('translator')->trans( 'Symfony2 is great', @@ -828,9 +814,7 @@ Translating Constraint Messages The best way to understand constraint translation is to see it in action. To start, suppose you've created a plain-old-PHP object that you need to use somewhere in -your application: - -.. code-block:: php +your application:: // src/Acme/BlogBundle/Entity/Author.php namespace Acme\BlogBundle\Entity; @@ -899,7 +883,7 @@ empty, add the following: public static function loadValidatorMetadata(ClassMetadata $metadata) { $metadata->addPropertyConstraint('name', new NotBlank(array( - 'message' => 'author.name.not_blank' + 'message' => 'author.name.not_blank', ))); } } diff --git a/book/validation.rst b/book/validation.rst index 4b8202f8f0f..bc0461cc407 100644 --- a/book/validation.rst +++ b/book/validation.rst @@ -8,12 +8,13 @@ Validation is a very common task in web applications. Data entered in forms needs to be validated. Data also needs to be validated before it is written into a database or passed to a web service. -Symfony2 ships with a `Validator`_ component that makes this task easy and transparent. -This component is based on the `JSR303 Bean Validation specification`_. What? -A Java specification in PHP? You heard right, but it's not as bad as it sounds. -Let's look at how it can be used in PHP. +Symfony2 ships with a `Validator`_ component that makes this task easy and +transparent. This component is based on the +`JSR303 Bean Validation specification`_. What? A Java specification in PHP? +You heard right, but it's not as bad as it sounds. Let's look at how it +can be used in PHP. -.. index: +.. index:: single: Validation; The basics The Basics of Validation @@ -21,9 +22,7 @@ The Basics of Validation The best way to understand validation is to see it in action. To start, suppose you've created a plain-old-PHP object that you need to use somewhere in -your application: - -.. code-block:: php +your application:: // src/Acme/BlogBundle/Entity/Author.php namespace Acme\BlogBundle\Entity; @@ -117,9 +116,7 @@ on the ``validator`` service (class :class:`Symfony\\Component\\Validator\\Valid The job of the ``validator`` is easy: to read the constraints (i.e. rules) of a class and verify whether or not the data on the object satisfies those constraints. If validation fails, an array of errors is returned. Take this -simple example from inside a controller: - -.. code-block:: php +simple example from inside a controller:: // ... use Symfony\Component\HttpFoundation\Response; @@ -752,15 +749,15 @@ user registers and when a user updates his/her contact information later: public static function loadValidatorMetadata(ClassMetadata $metadata) { $metadata->addPropertyConstraint('email', new Email(array( - 'groups' => array('registration') + 'groups' => array('registration'), ))); $metadata->addPropertyConstraint('password', new NotBlank(array( - 'groups' => array('registration') + 'groups' => array('registration'), ))); $metadata->addPropertyConstraint('password', new MinLength(array( 'limit' => 7, - 'groups' => array('registration') + 'groups' => array('registration'), ))); $metadata->addPropertyConstraint('city', new MinLength(3)); @@ -796,9 +793,9 @@ just want to validate a simple value - like to verify that a string is a valid email address. This is actually pretty easy to do. From inside a controller, it looks like this:: - // add this to the top of your class use Symfony\Component\Validator\Constraints\Email; - + // ... + public function addEmailAction($email) { $emailConstraint = new Email();