diff --git a/book/doctrine.rst b/book/doctrine.rst index 2e2037df5c2..24248043376 100644 --- a/book/doctrine.rst +++ b/book/doctrine.rst @@ -953,8 +953,8 @@ To relate the ``Category`` and ``Product`` entities, start by creating a products: targetEntity: Product mappedBy: category - # don't forget to init the collection in the __construct() method - # of the entity + # Don't forget to initialize the collection in + # the __construct() method of the entity .. code-block:: xml @@ -1096,7 +1096,7 @@ table, and ``product.category_id`` column, and new foreign key: .. note:: - This task should only be really used during development. For a more robust + This command should only be used during development. For a more robust method of systematically updating your production database, read about `migrations`_. @@ -1187,7 +1187,7 @@ You can also query in the other direction:: // ... } -In this case, the same things occurs: you first query out for a single ``Category`` +In this case, the same things occur: you first query out for a single ``Category`` object, and then Doctrine makes a second query to retrieve the related ``Product`` objects, but only once/if you ask for them (i.e. when you call ``->getProducts()``). The ``$products`` variable is an array of all ``Product`` objects that relate diff --git a/book/forms.rst b/book/forms.rst index b7b362c4761..f2738655ea2 100644 --- a/book/forms.rst +++ b/book/forms.rst @@ -223,8 +223,8 @@ Handling Form Submissions The second job of a form is to translate user-submitted data back to the properties of an object. To make this happen, the submitted data from the -user must be written into the form. Add the following functionality to your -controller:: +user must be written into the Form object. Add the following functionality to +your controller:: // ... use Symfony\Component\HttpFoundation\Request; @@ -694,9 +694,14 @@ the documentation for each type. The most common option is the ``required`` option, which can be applied to any field. By default, the ``required`` option is set to ``true``, meaning that HTML5-ready browsers will apply client-side validation if the field - is left blank. If you don't want this behavior, either set the ``required`` - option on your field to ``false`` or - :ref:`disable HTML5 validation `. + is left blank. If you don't want this behavior, either + :ref:`disable HTML5 validation ` + or set the ``required`` option on your field to ``false``:: + + ->add('dueDate', 'date', array( + 'widget' => 'single_text', + 'required' => false + )) Also note that setting the ``required`` option to ``true`` will **not** result in server-side validation to be applied. In other words, if a @@ -935,7 +940,7 @@ specify it: Some field types have additional rendering options that can be passed to the widget. These options are documented with each type, but one common -options is ``attr``, which allows you to modify attributes on the form element. +option is ``attr``, which allows you to modify attributes on the form element. The following would add the ``task_field`` class to the rendered input text field: diff --git a/book/templating.rst b/book/templating.rst index b9822b9200e..2d5b37f90c4 100644 --- a/book/templating.rst +++ b/book/templating.rst @@ -201,7 +201,7 @@ First, build a base layout file: - + {% block title %}Test Application{% endblock %} @@ -226,7 +226,7 @@ First, build a base layout file: - + <?php $view['slots']->output('title', 'Test Application') ?> @@ -311,7 +311,7 @@ output might look like this: - + My cool blog posts diff --git a/contributing/code/patches.rst b/contributing/code/patches.rst index b4f0b2ba4fa..6ed509e4d63 100644 --- a/contributing/code/patches.rst +++ b/contributing/code/patches.rst @@ -116,8 +116,7 @@ work: * ``2.3``, if you are fixing a bug for an existing feature (you may have to choose a higher branch if the feature you are fixing was introduced in a later version); -* ``2.8``, if you are adding a new feature which is backward compatible; -* ``master``, if you are adding a new and backward incompatible feature. +* ``master``, if you are adding a new feature. .. note:: diff --git a/cookbook/assetic/asset_management.rst b/cookbook/assetic/asset_management.rst index 8c319727943..8ec6ee43c0c 100644 --- a/cookbook/assetic/asset_management.rst +++ b/cookbook/assetic/asset_management.rst @@ -11,9 +11,9 @@ Starting from Symfony 2.8, Assetic is no longer included by default in the Symfony Standard Edition. Before using any of its features, install the AsseticBundle executing this console command in your project: - .. code-block:: bash +.. code-block:: bash - $ composer require symfony/assetic-bundle + $ composer require symfony/assetic-bundle Then, enable the bundle in the ``AppKernel.php`` file of your Symfony application:: diff --git a/cookbook/form/dynamic_form_modification.rst b/cookbook/form/dynamic_form_modification.rst index afd199b7da7..ba1f01b4073 100644 --- a/cookbook/form/dynamic_form_modification.rst +++ b/cookbook/form/dynamic_form_modification.rst @@ -374,13 +374,15 @@ you need to register it as a service and tag it with :ref:`form.type addTag('form.type'); - $container->setDefinition( - 'app.form.friend_message', - $definition, - array('security.token_storage') + use Symfony\Component\DependencyInjection\Reference; + + $definition = new Definition( + 'AppBundle\Form\Type\FriendMessageFormType', + array(new Reference('security.token_storage')) ); + $definition->addTag('form.type'); + + $container->setDefinition('app.form.friend_message', $definition); In a controller that extends the :class:`Symfony\\Bundle\\FrameworkBundle\\Controller\\Controller` class, you can simply call:: diff --git a/cookbook/form/form_customization.rst b/cookbook/form/form_customization.rst index 025297bee32..549a5fd38f0 100644 --- a/cookbook/form/form_customization.rst +++ b/cookbook/form/form_customization.rst @@ -264,7 +264,7 @@ directly in the template that's actually rendering the form. .. code-block:: html+twig - {% extends '::base.html.twig' %} + {% extends 'base.html.twig' %} {% form_theme form _self %} @@ -303,7 +303,7 @@ can now re-use the form customization across many templates: .. code-block:: html+twig - {# app/Resources/views/Form/fields.html.twig #} + {# app/Resources/views/form/fields.html.twig #} {% block integer_widget %}
{% set type = type|default('number') %} @@ -319,7 +319,7 @@ tell Symfony to use the template via the ``form_theme`` tag: .. code-block:: html+twig - {% form_theme form 'AppBundle:Form:fields.html.twig' %} + {% form_theme form 'form/fields.html.twig' %} {{ form_widget(form.age) }} @@ -335,13 +335,12 @@ name of all the templates as an array using the ``with`` keyword: .. code-block:: html+twig - {% form_theme form with ['::common.html.twig', ':Form:fields.html.twig', - 'AppBundle:Form:fields.html.twig'] %} + {% form_theme form with ['common.html.twig', 'form/fields.html.twig'] %} {# ... #} -The templates can be located at different bundles and they can even be stored -at the global ``app/Resources/views/`` directory. +The templates can also be located in different bundles, use the functional name +to reference these templates, e.g. ``AcmeFormExtraBundle:form:fields.html.twig``. Child Forms ........... @@ -350,16 +349,16 @@ You can also apply a form theme to a specific child of your form: .. code-block:: html+twig - {% form_theme form.child 'AppBundle:Form:fields.html.twig' %} + {% form_theme form.child 'form/fields.html.twig' %} This is useful when you want to have a custom theme for a nested form that's different than the one of your main form. Just specify both your themes: .. code-block:: html+twig - {% form_theme form 'AppBundle:Form:fields.html.twig' %} + {% form_theme form 'form/fields.html.twig' %} - {% form_theme form.child 'AppBundle:Form:fields_child.html.twig' %} + {% form_theme form.child 'form/fields_child.html.twig' %} .. _cookbook-form-php-theming: @@ -375,9 +374,13 @@ file in order to customize the ``integer_widget`` fragment. .. code-block:: html+php - +
- block($form, 'form_widget_simple', array('type' => isset($type) ? $type : "number")) ?> + block( + $form, + 'form_widget_simple', + array('type' => isset($type) ? $type : "number") + ) ?>
Now that you've created the customized form template, you need to tell Symfony @@ -388,7 +391,7 @@ tell Symfony to use the theme via the ``setTheme`` helper method: .. code-block:: php - setTheme($form, array('AppBundle:Form')); ?> + setTheme($form, array(':form')); ?> widget($form['age']) ?> @@ -401,7 +404,14 @@ method: .. code-block:: php - setTheme($form['child'], 'AppBundle:Form/Child'); ?> + setTheme($form['child'], ':form'); ?> + +.. note:: + + The ``:form`` syntax is based on the functional names for templates: + ``Bundle:Directory``. As the form directory lives in the + ``app/Resources/views`` directory, the ``Bundle`` part is empty, resulting + in ``:form``. .. _cookbook-form-twig-import-base-blocks: @@ -475,8 +485,8 @@ Twig ~~~~ By using the following configuration, any customized form blocks inside the -``AppBundle:Form:fields.html.twig`` template will be used globally when a -form is rendered. +``form/fields.html.twig`` template will be used globally when a form is +rendered. .. configuration-block:: @@ -485,14 +495,14 @@ form is rendered. # app/config/config.yml twig: form_themes: - - 'AppBundle:Form:fields.html.twig' + - 'form/fields.html.twig' # ... .. code-block:: xml - AppBundle:Form:fields.html.twig + form/fields.html.twig @@ -501,7 +511,7 @@ form is rendered. // app/config/config.php $container->loadFromExtension('twig', array( 'form_themes' => array( - 'AppBundle:Form:fields.html.twig', + 'form/fields.html.twig', ), // ... @@ -677,7 +687,7 @@ customize the ``name`` field only: .. code-block:: html+php - setTheme($form, array('AppBundle:Form')); ?> + setTheme($form, array(':form')); ?> widget($form['name']); ?> @@ -735,7 +745,7 @@ You can also override the markup for an entire field row using the same method: .. code-block:: html+php - setTheme($form, array('AppBundle:Form')); ?> + setTheme($form, array(':form')); ?> row($form['name']); ?> diff --git a/cookbook/security/entity_provider.rst b/cookbook/security/entity_provider.rst index 5b435ecf799..c2002d5810b 100644 --- a/cookbook/security/entity_provider.rst +++ b/cookbook/security/entity_provider.rst @@ -422,20 +422,18 @@ both are unique in the database. Unfortunately, the native entity provider is only able to handle querying via a single property on the user. To do this, make your ``UserRepository`` implement a special -:class:`Symfony\\Component\\Security\\Core\\User\\UserProviderInterface`. This -interface requires three methods: ``loadUserByUsername($username)``, -``refreshUser(UserInterface $user)``, and ``supportsClass($class)``:: +:class:`Symfony\\Bridge\\Doctrine\\Security\\User\\UserLoaderInterface`. This +interface only requires one method: ``loadUserByUsername($username)``:: // src/AppBundle/Entity/UserRepository.php namespace AppBundle\Entity; + use Symfony\Bridge\Doctrine\Security\User\UserLoaderInterface; use Symfony\Component\Security\Core\User\UserInterface; - use Symfony\Component\Security\Core\User\UserProviderInterface; use Symfony\Component\Security\Core\Exception\UsernameNotFoundException; - use Symfony\Component\Security\Core\Exception\UnsupportedUserException; use Doctrine\ORM\EntityRepository; - class UserRepository extends EntityRepository implements UserProviderInterface + class UserRepository extends EntityRepository implements UserLoaderInterface { public function loadUserByUsername($username) { @@ -456,30 +454,12 @@ interface requires three methods: ``loadUserByUsername($username)``, return $user; } - - public function refreshUser(UserInterface $user) - { - $class = get_class($user); - if (!$this->supportsClass($class)) { - throw new UnsupportedUserException( - sprintf( - 'Instances of "%s" are not supported.', - $class - ) - ); - } - - return $this->find($user->getId()); - } - - public function supportsClass($class) - { - return $this->getEntityName() === $class - || is_subclass_of($class, $this->getEntityName()); - } } -For more details on these methods, see :class:`Symfony\\Component\\Security\\Core\\User\\UserProviderInterface`. +.. versionadded:: 2.8 + The :class:`Symfony\\Bridge\\Doctrine\\Security\\User\\UserLoaderInterface` + was introduced in 2.8. Prior to Symfony 2.8, you had to implement + ``Symfony\Component\Security\Core\User\UserProviderInterface``. .. tip:: diff --git a/create_framework/dependency-injection.rst b/create_framework/dependency_injection.rst similarity index 99% rename from create_framework/dependency-injection.rst rename to create_framework/dependency_injection.rst index 725a8c019e1..59ad411c1e7 100644 --- a/create_framework/dependency-injection.rst +++ b/create_framework/dependency_injection.rst @@ -7,7 +7,6 @@ empty class, you might be tempted to move some code from the front controller to it:: // example.com/src/Simplex/Framework.php - namespace Simplex; use Symfony\Component\Routing; @@ -33,7 +32,6 @@ to it:: The front controller code would become more concise:: // example.com/web/front.php - require_once __DIR__.'/../vendor/autoload.php'; use Symfony\Component\HttpFoundation\Request; @@ -94,7 +92,6 @@ container: Create a new file to host the dependency injection container configuration:: // example.com/src/container.php - use Symfony\Component\DependencyInjection; use Symfony\Component\DependencyInjection\Reference; @@ -147,7 +144,6 @@ it in other object definitions. The front controller is now only about wiring everything together:: // example.com/web/front.php - require_once __DIR__.'/../vendor/autoload.php'; use Symfony\Component\HttpFoundation\Request; @@ -165,7 +161,6 @@ As all the objects are now created in the dependency injection container, the framework code should be the previous simple version:: // example.com/src/Simplex/Framework.php - namespace Simplex; use Symfony\Component\HttpKernel\HttpKernel; diff --git a/create_framework/event-dispatcher.rst b/create_framework/event_dispatcher.rst similarity index 99% rename from create_framework/event-dispatcher.rst rename to create_framework/event_dispatcher.rst index d2b062e415b..3964cf5ae46 100644 --- a/create_framework/event-dispatcher.rst +++ b/create_framework/event_dispatcher.rst @@ -34,7 +34,6 @@ To make it work, the framework must dispatch an event just before returning the Response instance:: // example.com/src/Simplex/Framework.php - namespace Simplex; use Symfony\Component\HttpFoundation\Request; @@ -46,9 +45,9 @@ the Response instance:: class Framework { - protected $matcher; - protected $resolver; - protected $dispatcher; + private $matcher; + private $resolver; + private $dispatcher; public function __construct(EventDispatcher $dispatcher, UrlMatcherInterface $matcher, ControllerResolverInterface $resolver) { @@ -85,7 +84,6 @@ Each time the framework handles a Request, a ``ResponseEvent`` event is now dispatched:: // example.com/src/Simplex/ResponseEvent.php - namespace Simplex; use Symfony\Component\HttpFoundation\Request; @@ -118,7 +116,6 @@ The last step is the creation of the dispatcher in the front controller and the registration of a listener for the ``response`` event:: // example.com/web/front.php - require_once __DIR__.'/../vendor/autoload.php'; // ... @@ -197,7 +194,6 @@ the priority to ``-255``:: Let's refactor the code a bit by moving the Google listener to its own class:: // example.com/src/Simplex/GoogleListener.php - namespace Simplex; class GoogleListener @@ -220,7 +216,6 @@ Let's refactor the code a bit by moving the Google listener to its own class:: And do the same with the other listener:: // example.com/src/Simplex/ContentLengthListener.php - namespace Simplex; class ContentLengthListener @@ -259,7 +254,6 @@ information to the dispatcher via the ``getSubscribedEvents()`` method. Have a look at the new version of the ``GoogleListener``:: // example.com/src/Simplex/GoogleListener.php - namespace Simplex; use Symfony\Component\EventDispatcher\EventSubscriberInterface; @@ -277,7 +271,6 @@ look at the new version of the ``GoogleListener``:: And here is the new version of ``ContentLengthListener``:: // example.com/src/Simplex/ContentLengthListener.php - namespace Simplex; use Symfony\Component\EventDispatcher\EventSubscriberInterface; diff --git a/create_framework/front-controller.rst b/create_framework/front_controller.rst similarity index 99% rename from create_framework/front-controller.rst rename to create_framework/front_controller.rst index 3ef47eb618b..212fbb47599 100644 --- a/create_framework/front-controller.rst +++ b/create_framework/front_controller.rst @@ -6,7 +6,6 @@ spice things up a little bit, let's go crazy and add another page that says goodbye:: // framework/bye.php - require_once __DIR__.'/vendor/autoload.php'; use Symfony\Component\HttpFoundation\Request; @@ -26,7 +25,6 @@ The PHP way of doing the refactoring would probably be the creation of an include file:: // framework/init.php - require_once __DIR__.'/vendor/autoload.php'; use Symfony\Component\HttpFoundation\Request; @@ -38,7 +36,6 @@ include file:: Let's see it in action:: // framework/index.php - require_once __DIR__.'/init.php'; $input = $request->get('name', 'World'); @@ -49,7 +46,6 @@ Let's see it in action:: And for the "Goodbye" page:: // framework/bye.php - require_once __DIR__.'/init.php'; $response->setContent('Goodbye!'); @@ -76,7 +72,6 @@ routing all client requests to a single PHP script. Such a script might look like the following:: // framework/front.php - require_once __DIR__.'/vendor/autoload.php'; use Symfony\Component\HttpFoundation\Request; @@ -103,7 +98,6 @@ Such a script might look like the following:: And here is for instance the new ``hello.php`` script:: // framework/hello.php - $input = $request->get('name', 'World'); $response->setContent(sprintf('Hello %s', htmlspecialchars($input, ENT_QUOTES, 'UTF-8'))); @@ -194,7 +188,6 @@ the ``setContent()`` directly from the front controller script:: And the ``hello.php`` script can now be converted to a template:: - get('name', 'World') ?> Hello @@ -202,7 +195,6 @@ And the ``hello.php`` script can now be converted to a template:: We have the first version of our framework:: // example.com/web/front.php - require_once __DIR__.'/../vendor/autoload.php'; use Symfony\Component\HttpFoundation\Request; diff --git a/create_framework/http-foundation.rst b/create_framework/http_foundation.rst similarity index 97% rename from create_framework/http-foundation.rst rename to create_framework/http_foundation.rst index fcaa6c005b2..9a87109bcec 100644 --- a/create_framework/http-foundation.rst +++ b/create_framework/http_foundation.rst @@ -18,7 +18,6 @@ Even if the "application" we wrote in the previous chapter was simple enough, it suffers from a few problems:: // framework/index.php - $input = $_GET['name']; printf('Hello %s', $input); @@ -27,7 +26,6 @@ First, if the ``name`` query parameter is not defined in the URL query string, you will get a PHP warning; so let's fix it:: // framework/index.php - $input = isset($_GET['name']) ? $_GET['name'] : 'World'; printf('Hello %s', $input); @@ -60,7 +58,6 @@ snippet of PHP code is not natural and feels ugly. Here is a tentative PHPUnit unit test for the above code:: // framework/test.php - class IndexTest extends \PHPUnit_Framework_TestCase { public function testHello() @@ -147,7 +144,6 @@ Now, let's rewrite our application by using the ``Request`` and the ``Response`` classes:: // framework/index.php - require_once __DIR__.'/vendor/autoload.php'; use Symfony\Component\HttpFoundation\Request; @@ -227,7 +223,7 @@ With the ``Response`` class, you can easily tweak the response:: .. tip:: - To debug a Response, cast it to a string; it will return the HTTP + To debug a response, cast it to a string; it will return the HTTP representation of the response (headers and content). Last but not the least, these classes, like every other class in the Symfony @@ -239,7 +235,7 @@ framework? Even something as simple as getting the client IP address can be insecure:: - if ($myIp == $_SERVER['REMOTE_ADDR']) { + if ($myIp === $_SERVER['REMOTE_ADDR']) { // the client is a known one, so give it some more privilege } @@ -248,7 +244,7 @@ production servers; at this point, you will have to change your code to make it work on both your development machine (where you don't have a proxy) and your servers:: - if ($myIp == $_SERVER['HTTP_X_FORWARDED_FOR'] || $myIp == $_SERVER['REMOTE_ADDR']) { + if ($myIp === $_SERVER['HTTP_X_FORWARDED_FOR'] || $myIp === $_SERVER['REMOTE_ADDR']) { // the client is a known one, so give it some more privilege } @@ -258,7 +254,7 @@ chained proxies):: $request = Request::createFromGlobals(); - if ($myIp == $request->getClientIp()) { + if ($myIp === $request->getClientIp()) { // the client is a known one, so give it some more privilege } @@ -271,7 +267,7 @@ explicitly trust your reverse proxies by calling ``setTrustedProxies()``:: Request::setTrustedProxies(array('10.0.0.1')); - if ($myIp == $request->getClientIp(true)) { + if ($myIp === $request->getClientIp(true)) { // the client is a known one, so give it some more privilege } diff --git a/create_framework/http-kernel-controller-resolver.rst b/create_framework/http_kernel_controller_resolver.rst similarity index 99% rename from create_framework/http-kernel-controller-resolver.rst rename to create_framework/http_kernel_controller_resolver.rst index 202c7769f63..c0cf260cf0b 100644 --- a/create_framework/http-kernel-controller-resolver.rst +++ b/create_framework/http_kernel_controller_resolver.rst @@ -50,6 +50,7 @@ a Request object. All controller resolvers implement the following interface:: namespace Symfony\Component\HttpKernel\Controller; + // ... interface ControllerResolverInterface { function getController(Request $request); @@ -151,7 +152,6 @@ method is not defined, an argument has no matching attribute, ...). Let's conclude with the new version of our framework:: // example.com/web/front.php - require_once __DIR__.'/../vendor/autoload.php'; use Symfony\Component\HttpFoundation\Request; diff --git a/create_framework/http-kernel-httpkernel-class.rst b/create_framework/http_kernel_httpkernel_class.rst similarity index 98% rename from create_framework/http-kernel-httpkernel-class.rst rename to create_framework/http_kernel_httpkernel_class.rst index ab0663dcbce..be2a2c7a09f 100644 --- a/create_framework/http-kernel-httpkernel-class.rst +++ b/create_framework/http_kernel_httpkernel_class.rst @@ -23,7 +23,6 @@ feedback when a problem arises. Here is the new framework code:: // example.com/src/Simplex/Framework.php - namespace Simplex; use Symfony\Component\HttpKernel\HttpKernel; @@ -35,7 +34,6 @@ Here is the new framework code:: And the new front controller:: // example.com/web/front.php - require_once __DIR__.'/../vendor/autoload.php'; use Symfony\Component\HttpFoundation\Request; @@ -79,13 +77,14 @@ thrown ``Exception`` instance to ease exception manipulation and display. It can take any valid controller as an exception handler, so you can create an ErrorController class instead of using a Closure:: - $listener = new HttpKernel\EventListener\ExceptionListener('Calendar\\Controller\\ErrorController::exceptionAction'); + $listener = new HttpKernel\EventListener\ExceptionListener( + 'Calendar\\Controller\\ErrorController::exceptionAction' + ); $dispatcher->addSubscriber($listener); The error controller reads as follows:: // example.com/src/Calendar/Controller/ErrorController.php - namespace Calendar\Controller; use Symfony\Component\HttpFoundation\Response; @@ -148,7 +147,6 @@ is to convert the controller return value to a proper Response instance, but only if needed:: // example.com/src/Simplex/StringResponseListener.php - namespace Simplex; use Symfony\Component\EventDispatcher\EventSubscriberInterface; diff --git a/create_framework/http-kernel-httpkernelinterface.rst b/create_framework/http_kernel_httpkernelinterface.rst similarity index 89% rename from create_framework/http-kernel-httpkernelinterface.rst rename to create_framework/http_kernel_httpkernelinterface.rst index f229b5578b0..8f64dd41376 100644 --- a/create_framework/http-kernel-httpkernelinterface.rst +++ b/create_framework/http_kernel_httpkernelinterface.rst @@ -8,12 +8,17 @@ goal by making our framework implement ``HttpKernelInterface``:: namespace Symfony\Component\HttpKernel; + // ... interface HttpKernelInterface { /** * @return Response A Response instance */ - function handle(Request $request, $type = self::MASTER_REQUEST, $catch = true); + public function handle( + Request $request, + $type = self::MASTER_REQUEST, + $catch = true + ); } ``HttpKernelInterface`` is probably the most important piece of code in the @@ -26,15 +31,17 @@ Update your framework so that it implements this interface:: // example.com/src/Framework.php // ... - use Symfony\Component\HttpKernel\HttpKernelInterface; class Framework implements HttpKernelInterface { // ... - public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true) - { + public function handle( + Request $request, + $type = HttpKernelInterface::MASTER_REQUEST, + $catch = true + ) { // ... } } @@ -47,9 +54,11 @@ PHP; it implements ``HttpKernelInterface`` and wraps another ``HttpKernelInterface`` instance:: // example.com/web/front.php - $framework = new Simplex\Framework($dispatcher, $matcher, $resolver); - $framework = new HttpKernel\HttpCache\HttpCache($framework, new HttpKernel\HttpCache\Store(__DIR__.'/../cache')); + $framework = new HttpKernel\HttpCache\HttpCache( + $framework, + new HttpKernel\HttpCache\Store(__DIR__.'/../cache') + ); $framework->handle($request)->send(); @@ -61,6 +70,7 @@ to cache a response for 10 seconds, use the ``Response::setTtl()`` method:: // example.com/src/Calendar/Controller/LeapYearController.php + // ... public function indexAction(Request $request, $year) { $leapyear = new LeapYear(); @@ -130,6 +140,7 @@ early as possible:: if ($response->isNotModified($request)) { return $response; } + $response->setContent('The computed content of the response'); return $response; @@ -138,7 +149,9 @@ Using HTTP caching is great, but what if you cannot cache the whole page? What if you can cache everything but some sidebar that is more dynamic that the rest of the content? Edge Side Includes (`ESI`_) to the rescue! Instead of generating the whole content in one go, ESI allows you to mark a region of a -page as being the content of a sub-request call:: +page as being the content of a sub-request call: + +.. code-block:: text This is the content of your page @@ -166,7 +179,12 @@ When using complex HTTP caching strategies and/or many ESI include tags, it can be hard to understand why and when a resource should be cached or not. To ease debugging, you can enable the debug mode:: - $framework = new HttpCache($framework, new Store(__DIR__.'/../cache'), new Esi(), array('debug' => true)); + $framework = new HttpKernel\HttpCache\HttpCache( + $framework, + new HttpKernel\HttpCache\Store(__DIR__.'/../cache'), + new HttpKernel\HttpCache\Esi(), + array('debug' => true) + ); The debug mode adds a ``X-Symfony-Cache`` header to each response that describes what the cache layer did: diff --git a/create_framework/index.rst b/create_framework/index.rst index b6a70f5e264..342a95960ec 100644 --- a/create_framework/index.rst +++ b/create_framework/index.rst @@ -4,14 +4,14 @@ Create your own PHP Framework .. toctree:: introduction - http-foundation - front-controller + http_foundation + front_controller routing templating - http-kernel-controller-resolver - separation-of-concerns - unit-testing - event-dispatcher - http-kernel-httpkernelinterface - http-kernel-httpkernel-class - dependency-injection + http_kernel_controller_resolver + separation_of_concerns + unit_testing + event_dispatcher + http_kernel_httpkernelinterface + http_kernel_httpkernel_class + dependency_injection diff --git a/create_framework/introduction.rst b/create_framework/introduction.rst index 31c03ed3c6d..70aeeda2ce3 100644 --- a/create_framework/introduction.rst +++ b/create_framework/introduction.rst @@ -104,7 +104,6 @@ Instead of creating our framework from scratch, we are going to write the same start with the simplest web application we can think of in PHP:: // framework/index.php - $input = $_GET['name']; printf('Hello %s', $input); @@ -116,8 +115,10 @@ You can use the PHP built-in server to test this great application in a browser $ php -S 127.0.0.1:4321 -In the next chapter, we are going to introduce the HttpFoundation Component -and see what it brings us. +Otherwise, you can always use your own server (Apache, Nginx, etc.). + +In the :doc:`next chapter `, we are going to +introduce the HttpFoundation Component and see what it brings us. .. _`Symfony`: http://symfony.com/ .. _`Silex`: http://silex.sensiolabs.org/ diff --git a/create_framework/map.rst.inc b/create_framework/map.rst.inc index 574c0f5e769..0f3bc41cbab 100644 --- a/create_framework/map.rst.inc +++ b/create_framework/map.rst.inc @@ -1,12 +1,12 @@ * :doc:`/create_framework/introduction` -* :doc:`/create_framework/http-foundation` -* :doc:`/create_framework/front-controller` +* :doc:`/create_framework/http_foundation` +* :doc:`/create_framework/front_controller` * :doc:`/create_framework/routing` * :doc:`/create_framework/templating` -* :doc:`/create_framework/http-kernel-controller-resolver` -* :doc:`/create_framework/separation-of-concerns` -* :doc:`/create_framework/unit-testing` -* :doc:`/create_framework/event-dispatcher` -* :doc:`/create_framework/http-kernel-httpkernelinterface` -* :doc:`/create_framework/http-kernel-httpkernel-class` -* :doc:`/create_framework/dependency-injection` +* :doc:`/create_framework/http_kernel_controller_resolver` +* :doc:`/create_framework/separation_of_concerns` +* :doc:`/create_framework/unit_testing` +* :doc:`/create_framework/event_dispatcher` +* :doc:`/create_framework/http_kernel_httpkernelinterface` +* :doc:`/create_framework/http_kernel_httpkernel_class` +* :doc:`/create_framework/dependency_injection` diff --git a/create_framework/routing.rst b/create_framework/routing.rst index 2d994b4d8f0..ed0ffc43375 100644 --- a/create_framework/routing.rst +++ b/create_framework/routing.rst @@ -5,7 +5,6 @@ Before we start diving into the Routing component, let's refactor our current framework just a little to make templates even more readable:: // example.com/web/front.php - require_once __DIR__.'/../vendor/autoload.php'; use Symfony\Component\HttpFoundation\Request; @@ -34,7 +33,6 @@ As we now extract the request query parameters, simplify the ``hello.php`` template as follows:: - Hello Now, we are in good shape to add new features. @@ -43,13 +41,7 @@ One very important aspect of any website is the form of its URLs. Thanks to the URL map, we have decoupled the URL from the code that generates the associated response, but it is not yet flexible enough. For instance, we might want to support dynamic paths to allow embedding data directly into the URL -instead of relying on a query string: - - # Before - /hello?name=Fabien - - # After - /hello/Fabien +(e.g. ``/hello/Fabien``) instead of relying on a query string (e.g. ``/hello?name=Fabien``). To support this feature, add the Symfony Routing component as a dependency: @@ -102,21 +94,27 @@ The ``match()`` method takes a request path and returns an array of attributes ``_route`` attribute):: print_r($matcher->match('/bye')); + /* Gives: array ( '_route' => 'bye', ); + */ print_r($matcher->match('/hello/Fabien')); + /* Gives: array ( 'name' => 'Fabien', '_route' => 'hello', ); + */ print_r($matcher->match('/hello')); + /* Gives: array ( 'name' => 'World', '_route' => 'hello', ); + */ .. note:: @@ -132,7 +130,6 @@ The URL matcher throws an exception when none of the routes match:: With this knowledge in mind, let's write the new version of our framework:: // example.com/web/front.php - require_once __DIR__.'/../vendor/autoload.php'; use Symfony\Component\HttpFoundation\Request; @@ -169,15 +166,11 @@ There are a few new things in the code: * Request attributes are extracted to keep our templates simple:: - Hello -* Route configuration has been moved to its own file: - - .. code-block:: php +* Route configuration has been moved to its own file:: // example.com/src/app.php - use Symfony\Component\Routing; $routes = new Routing\RouteCollection(); diff --git a/create_framework/separation-of-concerns.rst b/create_framework/separation_of_concerns.rst similarity index 93% rename from create_framework/separation-of-concerns.rst rename to create_framework/separation_of_concerns.rst index 8eba278c6da..9340e3b6519 100644 --- a/create_framework/separation-of-concerns.rst +++ b/create_framework/separation_of_concerns.rst @@ -16,7 +16,6 @@ Let's create our very own namespace for our framework: ``Simplex``. Move the request handling logic into its own ``Simplex\\Framework`` class:: // example.com/src/Simplex/Framework.php - namespace Simplex; use Symfony\Component\HttpFoundation\Request; @@ -60,7 +59,6 @@ And update ``example.com/web/front.php`` accordingly:: // example.com/web/front.php // ... - $request = Request::createFromGlobals(); $routes = include __DIR__.'/../src/app.php'; @@ -79,27 +77,22 @@ To wrap up the refactoring, let's move everything but routes definition from For the classes defined under the ``Simplex`` and ``Calendar`` namespaces to be autoloaded, update the ``composer.json`` file: -.. code-block:: javascript +.. code-block:: json { - "require": { - "symfony/http-foundation": "2.5.*", - "symfony/routing": "2.5.*", - "symfony/http-kernel": "2.5.*" - }, + "...": "...", "autoload": { - "psr-0": { "Simplex\\": "src/", "Calendar\\": "src/" } + "psr-4": { "": "src/" } } } .. note:: - For the Composer autoloader to be updated, run ``composer update``. + For the Composer autoloader to be updated, run ``composer dump-autoload``. -Move the controller to ``Calendar\\Controller\\LeapYearController``:: +Move the controller to ``Calendar\Controller\LeapYearController``:: // example.com/src/Calendar/Controller/LeapYearController.php - namespace Calendar\Controller; use Symfony\Component\HttpFoundation\Request; @@ -122,7 +115,6 @@ Move the controller to ``Calendar\\Controller\\LeapYearController``:: And move the ``is_leap_year()`` function to its own class too:: // example.com/src/Calendar/Model/LeapYear.php - namespace Calendar\Model; class LeapYear diff --git a/create_framework/templating.rst b/create_framework/templating.rst index 5fa4b4bc468..21dd890979e 100644 --- a/create_framework/templating.rst +++ b/create_framework/templating.rst @@ -17,7 +17,6 @@ Change the template rendering part of the framework to read as follows:: // example.com/web/front.php // ... - try { $request->attributes->add($matcher->match($request->getPathInfo())); $response = call_user_func('render_template', $request); @@ -101,7 +100,6 @@ you can even pass additional arguments to the template:: Here is the updated and improved version of our framework:: // example.com/web/front.php - require_once __DIR__.'/../vendor/autoload.php'; use Symfony\Component\HttpFoundation\Request; @@ -144,7 +142,6 @@ framework does not need to be modified in any way, just create a new ``app.php`` file:: // example.com/src/app.php - use Symfony\Component\Routing; use Symfony\Component\HttpFoundation\Response; @@ -153,7 +150,7 @@ framework does not need to be modified in any way, just create a new $year = date('Y'); } - return 0 == $year % 400 || (0 == $year % 4 && 0 != $year % 100); + return 0 === $year % 400 || (0 === $year % 4 && 0 !== $year % 100); } $routes = new Routing\RouteCollection(); diff --git a/create_framework/unit-testing.rst b/create_framework/unit_testing.rst similarity index 93% rename from create_framework/unit-testing.rst rename to create_framework/unit_testing.rst index 323dfee6ab7..580b1d7e428 100644 --- a/create_framework/unit-testing.rst +++ b/create_framework/unit_testing.rst @@ -14,17 +14,12 @@ using `PHPUnit`_. Create a PHPUnit configuration file in .. code-block:: xml - - @@ -45,7 +40,6 @@ such interfaces for core objects like the URL matcher and the controller resolver. Modify the framework to make use of them:: // example.com/src/Simplex/Framework.php - namespace Simplex; // ... @@ -70,7 +64,6 @@ resolver. Modify the framework to make use of them:: We are now ready to write our first test:: // example.com/tests/Simplex/Tests/FrameworkTest.php - namespace Simplex\Tests; use Simplex\Framework; @@ -88,7 +81,7 @@ We are now ready to write our first test:: $this->assertEquals(404, $response->getStatusCode()); } - protected function getFrameworkForException($exception) + private function getFrameworkForException($exception) { $matcher = $this->getMock('Symfony\Component\Routing\Matcher\UrlMatcherInterface'); $matcher diff --git a/redirection_map b/redirection_map index bea56526ac1..cc69e78c53b 100644 --- a/redirection_map +++ b/redirection_map @@ -52,3 +52,12 @@ /cookbook/configuration/pdo_session_storage /cookbook/doctrine/pdo_session_storage /cookbook/configuration/mongodb_session_storage /cookbook/doctrine/mongodb_session_storage /cookbook/service_container/event_listener /cookbook/event_dispatcher/event_listener +/create_framework/http-foundation /create_framework/http_foundation +/create_framework/front-controller /create_framework/front_controller +/create_framework/http-kernel-controller-resolver /create_framework/http_kernel_controller_resolver +/create_framework/separation-of-concerns /create_framework/separation_of_concerns +/create_framework/unit-testing /create_framework/unit_testing +/create_framework/event-dispatcher /create_framework/event_dispatcher +/create_framework/http-kernel-httpkernelinterface /create_framework/http_kernel_httpkernelinterface +/create_framework/http-kernel-httpkernel-class /create_framework/http_kernel_httpkernel_class +/create_framework/dependency-injection /create_framework/dependency_injection diff --git a/reference/dic_tags.rst b/reference/dic_tags.rst index ebeaee158c1..73a1bbf3eeb 100644 --- a/reference/dic_tags.rst +++ b/reference/dic_tags.rst @@ -572,8 +572,9 @@ kernel.event_listener **Purpose**: To listen to different events/hooks in Symfony -This tag allows you to hook your own classes into Symfony's process at different -points. +During the execution of a Symfony application, different events are triggered +and you can also dispatch custom events. This tag allows you to *hook* your own +classes into any of those events. For a full example of this listener, read the :doc:`/cookbook/event_dispatcher/event_listener` cookbook entry. diff --git a/reference/forms/types/money.rst b/reference/forms/types/money.rst index f97dec52d51..bb9fcc88ce6 100644 --- a/reference/forms/types/money.rst +++ b/reference/forms/types/money.rst @@ -88,7 +88,7 @@ scale **type**: ``integer`` **default**: ``2`` -For some reason, if you need some scale other than 2 decimal places, +If, for some reason, you need some scale other than 2 decimal places, you can modify this value. You probably won't need to do this unless, for example, you want to round to the nearest dollar (set the scale to ``0``).