diff --git a/book/forms.rst b/book/forms.rst index cc126b80d40..5fc28cc1368 100644 --- a/book/forms.rst +++ b/book/forms.rst @@ -477,14 +477,10 @@ Disabling Validation ~~~~~~~~~~~~~~~~~~~~ .. versionadded:: 2.3 - The ability to set ``validation_groups`` to false was added in Symfony 2.3, - although setting it to an empty array achieved the same result in previous - versions. + The ability to set ``validation_groups`` to false was added in Symfony 2.3. Sometimes it is useful to suppress the validation of a form altogether. For -these cases, you can skip the call to :method:`Symfony\\Component\\Form\\FormInterface::isValid` -in your controller. If this is not possible, you can alternatively set the -``validation_groups`` option to ``false`` or an empty array:: +these cases you can set the ``validation_groups`` option to ``false``:: use Symfony\Component\OptionsResolver\OptionsResolverInterface; @@ -497,9 +493,8 @@ in your controller. If this is not possible, you can alternatively set the Note that when you do that, the form will still run basic integrity checks, for example whether an uploaded file was too large or whether non-existing -fields were submitted. If you want to suppress validation completely, remove -the :method:`Symfony\\Component\\Form\\FormInterface::isValid` call from your -controller. +fields were submitted. If you want to suppress validation, you can use the +:ref:`POST_SUBMIT event ` .. index:: single: Forms; Validation groups based on submitted data diff --git a/book/http_cache.rst b/book/http_cache.rst index 4133ee0d2f9..eae2857dc9f 100644 --- a/book/http_cache.rst +++ b/book/http_cache.rst @@ -301,9 +301,11 @@ The ``Cache-Control`` header is unique in that it contains not one, but various pieces of information about the cacheability of a response. Each piece of information is separated by a comma: - Cache-Control: private, max-age=0, must-revalidate +.. code-block:: text + + Cache-Control: private, max-age=0, must-revalidate - Cache-Control: max-age=3600, must-revalidate + Cache-Control: max-age=3600, must-revalidate Symfony provides an abstraction around the ``Cache-Control`` header to make its creation more manageable:: @@ -385,7 +387,7 @@ header when none is set by the developer by following these rules: * If ``Cache-Control`` is empty (but one of the other cache headers is present), its value is set to ``private, must-revalidate``; -* But if at least one ``Cache-Control`` directive is set, and no 'public' or +* But if at least one ``Cache-Control`` directive is set, and no ``public`` or ``private`` directives have been explicitly added, Symfony2 adds the ``private`` directive automatically (except when ``s-maxage`` is set). @@ -667,7 +669,7 @@ exposing a simple and efficient pattern:: // a database or a key-value store for instance) $article = ...; - // create a Response with a ETag and/or a Last-Modified header + // create a Response with an ETag and/or a Last-Modified header $response = new Response(); $response->setETag($article->computeETag()); $response->setLastModified($article->getPublishedAt()); @@ -679,17 +681,17 @@ exposing a simple and efficient pattern:: if ($response->isNotModified($request)) { // return the 304 Response immediately return $response; - } else { - // do more work here - like retrieving more data - $comments = ...; - - // or render a template with the $response you've already started - return $this->render( - 'MyBundle:MyController:article.html.twig', - array('article' => $article, 'comments' => $comments), - $response - ); } + + // do more work here - like retrieving more data + $comments = ...; + + // or render a template with the $response you've already started + return $this->render( + 'MyBundle:MyController:article.html.twig', + array('article' => $article, 'comments' => $comments), + $response + ); } When the ``Response`` is not modified, the ``isNotModified()`` automatically sets @@ -956,8 +958,9 @@ component cache will only last for 60 seconds. When using a controller reference, the ESI tag should reference the embedded action as an accessible URL so the gateway cache can fetch it independently of the rest of the page. Symfony2 takes care of generating a unique URL for any -controller reference and it is able to route them properly thanks to a -listener that must be enabled in your configuration: +controller reference and it is able to route them properly thanks to the +:class:`Symfony\\Component\\HttpKernel\\EventListener\\FragmentListener` +that must be enabled in your configuration: .. configuration-block:: @@ -1063,10 +1066,10 @@ Here is how you can configure the Symfony2 reverse proxy to support the } $response = new Response(); - if (!$this->getStore()->purge($request->getUri())) { - $response->setStatusCode(Response::HTTP_NOT_FOUND, 'Not purged'); - } else { + if ($this->getStore()->purge($request->getUri())) { $response->setStatusCode(Response::HTTP_OK, 'Purged'); + } else { + $response->setStatusCode(Response::HTTP_NOT_FOUND, 'Not purged'); } return $response; @@ -1104,6 +1107,6 @@ Learn more from the Cookbook .. _`validation model`: http://tools.ietf.org/html/rfc2616#section-13.3 .. _`RFC 2616`: http://tools.ietf.org/html/rfc2616 .. _`HTTP Bis`: http://tools.ietf.org/wg/httpbis/ -.. _`P4 - Conditional Requests`: http://tools.ietf.org/html/draft-ietf-httpbis-p4-conditional-12 -.. _`P6 - Caching: Browser and intermediary caches`: http://tools.ietf.org/html/draft-ietf-httpbis-p6-cache-12 +.. _`P4 - Conditional Requests`: http://tools.ietf.org/html/draft-ietf-httpbis-p4-conditional +.. _`P6 - Caching: Browser and intermediary caches`: http://tools.ietf.org/html/draft-ietf-httpbis-p6-cache .. _`ESI`: http://www.w3.org/TR/esi-lang diff --git a/book/validation.rst b/book/validation.rst index 95002c90285..7a4d4f82251 100644 --- a/book/validation.rst +++ b/book/validation.rst @@ -115,7 +115,7 @@ 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, a non-empty list of errors (class :class:`Symfony\\Component\\Validator\\ConstraintViolationList`) is -returned. Take this simple example from inside a controller: +returned. Take this simple example from inside a controller:: // ... use Symfony\Component\HttpFoundation\Response; diff --git a/cookbook/form/dynamic_form_modification.rst b/cookbook/form/dynamic_form_modification.rst index 5ae656eef90..d05dc32fe59 100644 --- a/cookbook/form/dynamic_form_modification.rst +++ b/cookbook/form/dynamic_form_modification.rst @@ -583,3 +583,35 @@ after the sport is selected. This should be handled by making an AJAX call back to your application. In that controller, you can submit your form, but instead of processing it, simply use the submitted form to render the updated fields. The response from the AJAX call can then be used to update the view. + +.. _cookbook-dynamic-form-modification-suppressing-form-validation: + +Suppressing Form Validation +--------------------------- + +To suppress form validation you can use the ``POST_SUBMIT`` event and prevent +the :class:`Symfony\\Component\\Form\\Extension\\Validator\\EventListener\\ValidationListener` +from being called. + +The reason for needing to do this is that even if you set ``group_validation`` +to ``false`` there are still some integrity checks executed. For example +an uploaded file will still be checked to see if it is too large and the form +will still check to see if non-existing fields were submitted. To disable +all of this, use a listener:: + + use Symfony\Component\Form\FormBuilderInterface; + use Symfony\Component\Form\FormEvents; + + public function buildForm(FormBuilderInterface $builder, array $options) + { + $builder->addEventListener(FormEvents::POST_SUBMIT, function($event) { + $event->stopPropagation(); + }, 900); // Always set a higher priority than ValidationListener + + // ... + } + +.. caution:: + + By doing this, you may accidentally disable something more than just form + validation, since the ``POST_SUBMIT`` event may have other listeners. diff --git a/cookbook/map.rst.inc b/cookbook/map.rst.inc index 64590e38e1d..6986e4b1ca0 100644 --- a/cookbook/map.rst.inc +++ b/cookbook/map.rst.inc @@ -109,6 +109,7 @@ * :doc:`/cookbook/profiler/data_collector` * :doc:`/cookbook/profiler/matchers` + * :doc:`/cookbook/profiler/storage` * :doc:`/cookbook/request/index` diff --git a/cookbook/profiler/index.rst b/cookbook/profiler/index.rst index 3900380f932..7ff3abe1982 100644 --- a/cookbook/profiler/index.rst +++ b/cookbook/profiler/index.rst @@ -6,3 +6,4 @@ Profiler data_collector matchers + storage diff --git a/cookbook/profiler/storage.rst b/cookbook/profiler/storage.rst new file mode 100644 index 00000000000..ca3c5b40c7c --- /dev/null +++ b/cookbook/profiler/storage.rst @@ -0,0 +1,69 @@ +.. index:: + single: Profiling; Storage Configuration + +Switching the Profiler Storage +============================== + +By default the profile stores the collected data in files in the cache directory. +You can control the storage being used through the ``dsn``, ``username``, +``password`` and ``lifetime`` options. For example, the following configuration +uses MySQL as the storage for the profiler with a lifetime of one hour: + +.. configuration-block:: + + .. code-block:: yaml + + # app/config/config.yml + framework: + profiler: + dsn: "mysql:host=localhost;dbname=%database_name%" + username: "%database_user%" + password: "%database_password%" + lifetime: 3600 + + .. code-block:: xml + + + + + + + + + + .. code-block:: php + + // app/config/config.php + + // ... + $container->loadFromExtension('framework', array( + 'profiler' => array( + 'dsn' => 'mysql:host=localhost;dbname=%database_name%', + 'username' => '%database_user', + 'password' => '%database_password%', + 'lifetime' => 3600, + ), + )); + +The :doc:`HttpKernel component ` currently +supports the following profiler storage implementations: + +* :class:`Symfony\\Component\\HttpKernel\\Profiler\\FileProfilerStorage` +* :class:`Symfony\\Component\\HttpKernel\\Profiler\\MemcachedProfilerStorage` +* :class:`Symfony\\Component\\HttpKernel\\Profiler\\MemcacheProfilerStorage` +* :class:`Symfony\\Component\\HttpKernel\\Profiler\\MongoDbProfilerStorage` +* :class:`Symfony\\Component\\HttpKernel\\Profiler\\MysqlProfilerStorage` +* :class:`Symfony\\Component\\HttpKernel\\Profiler\\RedisProfilerStorage` +* :class:`Symfony\\Component\\HttpKernel\\Profiler\\SqliteProfilerStorage` diff --git a/cookbook/security/entity_provider.rst b/cookbook/security/entity_provider.rst index a2ef0f2a6d2..3fb489c819d 100644 --- a/cookbook/security/entity_provider.rst +++ b/cookbook/security/entity_provider.rst @@ -226,7 +226,7 @@ user records and encode their password, see :ref:`book-security-encoding-user-pa .. code-block:: bash - $ mysql> select * from acme_users; + $ mysql> SELECT * FROM acme_users; +----+----------+------+------------------------------------------+--------------------+-----------+ | id | username | salt | password | email | is_active | +----+----------+------+------------------------------------------+--------------------+-----------+ @@ -682,14 +682,14 @@ this: .. code-block:: bash - $ mysql> select * from acme_role; + $ mysql> SELECT * FROM acme_role; +----+-------+------------+ | id | name | role | +----+-------+------------+ | 1 | admin | ROLE_ADMIN | +----+-------+------------+ - $ mysql> select * from user_role; + $ mysql> SELECT * FROM user_role; +---------+---------+ | user_id | role_id | +---------+---------+ diff --git a/cookbook/service_container/scopes.rst b/cookbook/service_container/scopes.rst index 8f6fd9fd34d..59d4cd425a4 100644 --- a/cookbook/service_container/scopes.rst +++ b/cookbook/service_container/scopes.rst @@ -134,6 +134,7 @@ marked as ``synchronized``: class: Acme\HelloBundle\Client\ClientConfiguration scope: client synchronized: true + synthetic: true # ... .. code-block:: xml @@ -151,6 +152,7 @@ marked as ``synchronized``: id="client_configuration" scope="client" synchronized="true" + synthetic="true" class="Acme\HelloBundle\Client\ClientConfiguration" /> @@ -167,6 +169,7 @@ marked as ``synchronized``: ); $definition->setScope('client'); $definition->setSynchronized(true); + $definition->setSynthetic(true); $container->setDefinition('client_configuration', $definition); Now, if you inject this service using setter injection, there are no drawbacks @@ -196,9 +199,9 @@ and everything works without any special code in your service or in your definit } } -Whenever the ``client`` scope is entered or left, the service container will -automatically call the ``setClientConfiguration()`` method with the current -``client_configuration`` instance. +Whenever the ``client`` scope is active, the service container will +automatically call the ``setClientConfiguration()`` method when the +``client_configuration`` service is set in the container. You might have noticed that the ``setClientConfiguration()`` method accepts ``null`` as a valid value for the ``client_configuration`` argument. That's