From f9f3c3f9fa4cb330d4e39a1f685c824df172db28 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Sun, 7 Dec 2014 10:41:21 -0500 Subject: [PATCH 01/21] Making the channel handler more useful by showing it on the prod environment --- cookbook/logging/channels_handlers.rst | 66 ++++++++++++++++---------- 1 file changed, 40 insertions(+), 26 deletions(-) diff --git a/cookbook/logging/channels_handlers.rst b/cookbook/logging/channels_handlers.rst index 69c4e5002b0..f859c985308 100644 --- a/cookbook/logging/channels_handlers.rst +++ b/cookbook/logging/channels_handlers.rst @@ -4,37 +4,47 @@ How to Log Messages to different Files ====================================== -The Symfony Standard Edition contains a bunch of channels for logging: ``doctrine``, -``event``, ``security`` and ``request``. Each channel corresponds to a logger -service (``monolog.logger.XXX``) in the container and is injected to the -concerned service. The purpose of channels is to be able to organize different -types of log messages. +The Symfony Framework organizes log messages into channels. By default, there +are several channels, including ``doctrine``, ``event``, ``security``, ``request`` +and more. The channel is printed in the log message and can also be used +to direct different channels to different places/files. By default, Symfony logs every message into a single file (regardless of the channel). +.. note:: + + Each channel corresponds to a logger service (``monolog.logger.XXX``) + in the container (use the ``container:debug`` command to see a full list) + and those are injected into different services. + +.. _logging-channel-handler: + Switching a Channel to a different Handler ------------------------------------------ -Now, suppose you want to log the ``doctrine`` channel to a different file. - -To do so, just create a new handler and configure it like this: +Now, suppose you want to log the ``security`` channel to a different file +in the ``prod`` environment. To do this, just create a new handler and configure +it to log only messages from the ``security`` channel: .. configuration-block:: .. code-block:: yaml - # app/config/config.yml + # app/config/config_prod.yml monolog: handlers: - main: + security: + # log all messages (since debug is the lowest level) + level: debug type: stream - path: /var/log/symfony.log - channels: ["!doctrine"] - doctrine: - type: stream - path: /var/log/doctrine.log - channels: [doctrine] + path: "%kernel.logs_dir%/security.log" + channels: [security] + + # an example of *not* logging security channel messages + main: + # ... + # channels: ["!security"] .. code-block:: xml @@ -48,16 +58,18 @@ To do so, just create a new handler and configure it like this: http://symfony.com/schema/dic/monolog/monolog-1.0.xsd" > - + - !doctrine + security - + + @@ -67,19 +79,21 @@ To do so, just create a new handler and configure it like this: // app/config/config.php $container->loadFromExtension('monolog', array( 'handlers' => array( - 'main' => array( + 'security' => array( 'type' => 'stream', - 'path' => '/var/log/symfony.log', + 'path' => '%kernel.logs_dir%/security.log', 'channels' => array( - '!doctrine', + 'security', ), ), - 'doctrine' => array( + 'main' => array( 'type' => 'stream', - 'path' => '/var/log/doctrine.log', + 'path' => '%kernel.logs_dir%/security.log', + /* 'channels' => array( - 'doctrine', + '!security', ), + */ ), ), )); From 78323d844806ef7a3992ece99cb81ed7b3fbad9a Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Fri, 16 Jan 2015 12:53:26 -0500 Subject: [PATCH 02/21] Changing back to config.yml and fixing some code block mistakes thanks to Wouter --- cookbook/logging/channels_handlers.rst | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/cookbook/logging/channels_handlers.rst b/cookbook/logging/channels_handlers.rst index f859c985308..db9a92298c5 100644 --- a/cookbook/logging/channels_handlers.rst +++ b/cookbook/logging/channels_handlers.rst @@ -23,15 +23,15 @@ the channel). Switching a Channel to a different Handler ------------------------------------------ -Now, suppose you want to log the ``security`` channel to a different file -in the ``prod`` environment. To do this, just create a new handler and configure -it to log only messages from the ``security`` channel: +Now, suppose you want to log the ``security`` channel to a different file. +To do this, just create a new handler and configure it to log only messages +from the ``security`` channel: .. configuration-block:: .. code-block:: yaml - # app/config/config_prod.yml + # app/config/config.yml monolog: handlers: security: @@ -41,7 +41,7 @@ it to log only messages from the ``security`` channel: path: "%kernel.logs_dir%/security.log" channels: [security] - # an example of *not* logging security channel messages + # an example of *not* logging security channel messages for this handler main: # ... # channels: ["!security"] @@ -64,12 +64,11 @@ it to log only messages from the ``security`` channel: - - !security - --> @@ -87,13 +86,10 @@ it to log only messages from the ``security`` channel: ), ), 'main' => array( - 'type' => 'stream', - 'path' => '%kernel.logs_dir%/security.log', - /* + // ... 'channels' => array( '!security', ), - */ ), ), )); From 31fd0dbbd677a5c4a0625d0d034eab03431bcc81 Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Thu, 2 Apr 2015 17:25:46 +0200 Subject: [PATCH 03/21] Added a note about the rotating_file monolog handler --- cookbook/logging/monolog.rst | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/cookbook/logging/monolog.rst b/cookbook/logging/monolog.rst index 6093fa85589..5f8bcd0cc97 100644 --- a/cookbook/logging/monolog.rst +++ b/cookbook/logging/monolog.rst @@ -236,6 +236,21 @@ only for a specific handler. generate hundreds of log lines. Consider using tools like the `logrotate`_ Linux command to rotate log files before they become a problem. + In case you cannot use a dedicated tool for rotating log files, consider using + the special ``rotating_file`` handler defined by Monolog. This handler creates + a new log file every day and can also remove old files automatically. To use + it, just set the ``type`` option of your handler to ``rotating_file``: + + .. code-block:: yaml + + # app/config/config_dev.yml + monolog: + handlers: + main: + type: rotating_file # <-- this value is usually 'stream' + path: %kernel.logs_dir%/%kernel.environment%.log + level: debug + A processor is simply a callable receiving the record as its first argument. Processors are configured using the ``monolog.processor`` DIC tag. See the :ref:`reference about it `. From 7345c17107f2a1b4610caffac277167e5f36e1a4 Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Sun, 5 Apr 2015 15:47:22 +0200 Subject: [PATCH 04/21] Added XML and PHP configuration samples --- cookbook/logging/monolog.rst | 49 +++++++++++++++++++++++++++++------- 1 file changed, 40 insertions(+), 9 deletions(-) diff --git a/cookbook/logging/monolog.rst b/cookbook/logging/monolog.rst index 5f8bcd0cc97..b464e6d976e 100644 --- a/cookbook/logging/monolog.rst +++ b/cookbook/logging/monolog.rst @@ -241,15 +241,46 @@ only for a specific handler. a new log file every day and can also remove old files automatically. To use it, just set the ``type`` option of your handler to ``rotating_file``: - .. code-block:: yaml - - # app/config/config_dev.yml - monolog: - handlers: - main: - type: rotating_file # <-- this value is usually 'stream' - path: %kernel.logs_dir%/%kernel.environment%.log - level: debug + .. configuration-block:: + + .. code-block:: yaml + + # app/config/config_dev.yml + monolog: + handlers: + main: + type: rotating_file + path: %kernel.logs_dir%/%kernel.environment%.log + level: debug + + .. code-block:: xml + + + + + + + + + + + .. code-block:: php + + // app/config/config_dev.php + $container->loadFromExtension('monolog', array( + 'handlers' => array( + 'main' => array( + 'type' => 'rotating_file', + 'path' => '%kernel.logs_dir%/%kernel.environment%.log', + 'level' => 'debug', + ), + ), + )); A processor is simply a callable receiving the record as its first argument. Processors are configured using the ``monolog.processor`` DIC tag. See the From 6a90c9b7519d97f5ba7e809d0c81320f966cbd04 Mon Sep 17 00:00:00 2001 From: WouterJ Date: Tue, 10 Mar 2015 11:02:47 +0100 Subject: [PATCH 05/21] Created 'upgrade' cookbook section --- cookbook/index.rst | 2 +- cookbook/map.rst.inc | 5 +- cookbook/upgrade/_update_all_packages.rst.inc | 16 ++ cookbook/upgrade/index.rst | 17 +++ cookbook/upgrade/minor_version.rst | 63 ++++++++ cookbook/upgrade/patch_version.rst | 26 ++++ cookbook/upgrading.rst | 141 ------------------ redirection_map | 1 + 8 files changed, 127 insertions(+), 144 deletions(-) create mode 100644 cookbook/upgrade/_update_all_packages.rst.inc create mode 100644 cookbook/upgrade/index.rst create mode 100644 cookbook/upgrade/minor_version.rst create mode 100644 cookbook/upgrade/patch_version.rst delete mode 100644 cookbook/upgrading.rst diff --git a/cookbook/index.rst b/cookbook/index.rst index 03d29060c7f..2e0de5df7ef 100644 --- a/cookbook/index.rst +++ b/cookbook/index.rst @@ -28,7 +28,7 @@ The Cookbook symfony1 templating/index testing/index - upgrading + upgrade/index validation/index web_server/index web_services/index diff --git a/cookbook/map.rst.inc b/cookbook/map.rst.inc index 6c8e5d59d89..92bc715cee4 100644 --- a/cookbook/map.rst.inc +++ b/cookbook/map.rst.inc @@ -201,9 +201,10 @@ * (email) :doc:`/cookbook/email/testing` * (form) :doc:`/cookbook/form/unit_testing` -* **Upgrading** +* :doc:`/cookbook/upgrading/index` - * :doc:`/cookbook/upgrading` + * :doc:`/cookbook/upgrading/patch_version` + * :doc:`/cookbook/upgrading/minor_version` * :doc:`/cookbook/validation/index` diff --git a/cookbook/upgrade/_update_all_packages.rst.inc b/cookbook/upgrade/_update_all_packages.rst.inc new file mode 100644 index 00000000000..49d82e9fe12 --- /dev/null +++ b/cookbook/upgrade/_update_all_packages.rst.inc @@ -0,0 +1,16 @@ +You may also want to upgrade the rest of your libraries. If you've done a +good job with your `version constraints`_ in ``composer.json``, you can do +this safely by running: + +.. code-block:: bash + + $ composer update + +.. caution:: + + Beware, if you have some bad `version constraints`_ in your + ``composer.json`` (e.g. ``dev-master``), this could upgrade some + non-Symfony libraries to new versions that contain backwards-compatibility + breaking changes. + +.. _`versino constraints`: https://getcomposer.org/doc/01-basic-usage.md#package-versions diff --git a/cookbook/upgrade/index.rst b/cookbook/upgrade/index.rst new file mode 100644 index 00000000000..fe4aeca3b4e --- /dev/null +++ b/cookbook/upgrade/index.rst @@ -0,0 +1,17 @@ +.. index:: + single: Upgrading + +Upgrading +========= + +So a new Symfony release has come out and you want to upgrade, great! Fortunately, +because Symfony protects backwards-compatibility very closely, this *should* +be quite easy. + +There are three types of upgrades, all needing a little different preparation: + +.. toctree:: + :maxdepth: 2 + + /cookbook/upgrade/patch_version + /cookbook/upgrade/minor_version diff --git a/cookbook/upgrade/minor_version.rst b/cookbook/upgrade/minor_version.rst new file mode 100644 index 00000000000..4a5a0fa023e --- /dev/null +++ b/cookbook/upgrade/minor_version.rst @@ -0,0 +1,63 @@ +.. index:: + single: Upgrading; Minor Version + +Upgrading a Minor Version (e.g. 2.5.3 to 2.6.1) +=============================================== + +If you're upgrading a minor version (where the middle number changes), then +you should *not* encounter significant backwards compatibility changes. For +details, see the :doc:`Symfony backwards compatibility promise `. + +However, some backwards-compatibility breaks *are* possible and you'll learn in +a second how to prepare for them. + +There are two steps to upgrading a minor version: + +#. :ref:`Update the Symfony library via Composer `; +#. :ref:`Update your code to work with the new version `. + +.. _`upgrade-minor-symfony-composer`: + +1) Update the Symfony Library via Composer +------------------------------------------ + +First, you need to update Symfony by modifying your ``composer.json`` file +to use the new version: + +.. code-block:: json + + { + "...": "...", + + "require": { + "symfony/symfony": "2.6.*", + }, + "...": "...", + } + +Next, use Composer to download new versions of the libraries: + +.. code-block:: bash + + $ composer update symfony/symfony + +.. include:: /cookbook/upgrade/_update_all_packages.rst.inc + +.. _`upgrade-minor-symfony-code`: + +2) Updating Your Code to Work with the new Version +-------------------------------------------------- + +In theory, you should be done! However, you *may* need to make a few changes +to your code to get everything working. Additionally, some features you're +using might still work, but might now be deprecated. While that's just fine, +if you know about these deprecations, you can start to fix them over time. + +Every version of Symfony comes with an UPGRADE file included in the Symfony +directory that describes these changes. If you follow the instructions in the +document and update your code accordingly, it should be save to update in the +future. + +These documents can also be found in the `Symfony Repository`_. + +.. _`Symfony Repository`: https://github.com/symfony/symfony diff --git a/cookbook/upgrade/patch_version.rst b/cookbook/upgrade/patch_version.rst new file mode 100644 index 00000000000..2968aa22c77 --- /dev/null +++ b/cookbook/upgrade/patch_version.rst @@ -0,0 +1,26 @@ +.. index:: + single: Upgrading; Patch Version + +Upgrading a Patch Version (e.g. 2.6.0 to 2.6.1) +=============================================== + +When a new patch version is released (only the last number changed), it is a +release that only contains bug fixes. This means that upgrading to a new patch +version is *really* easy: + +.. code-block:: bash + + $ composer update symfony/symfony + +That's it! You should not encounter any backwards-compatibility breaks or +need to change anything else in your code. That's because when you started +your project, your ``composer.json`` included Symfony using a constraint +like ``2.6.*``, where only the *last* version number will change when you +update. + +.. tip:: + + It is recommended to update to a new patch version as soon as possible, as + important bugs and security leaks may be fixed in these new releases. + +.. include:: /cookbook/upgrade/_update_all_packages.rst.inc diff --git a/cookbook/upgrading.rst b/cookbook/upgrading.rst deleted file mode 100644 index 0dc36fcd160..00000000000 --- a/cookbook/upgrading.rst +++ /dev/null @@ -1,141 +0,0 @@ -How to Upgrade Your Symfony Project -=================================== - -So a new Symfony release has come out and you want to upgrade, great! Fortunately, -because Symfony protects backwards-compatibility very closely, this *should* -be quite easy. - -There are two types of upgrades, and both are a little different: - -* :ref:`upgrading-patch-version` -* :ref:`upgrading-minor-version` - -.. _upgrading-patch-version: - -Upgrading a Patch Version (e.g. 2.6.0 to 2.6.1) ------------------------------------------------ - -If you're upgrading and only the patch version (the last number) is changing, -then it's *really* easy: - -.. code-block:: bash - - $ composer update symfony/symfony - -That's it! You should not encounter any backwards-compatibility breaks or -need to change anything else in your code. That's because when you started -your project, your ``composer.json`` included Symfony using a constraint -like ``2.6.*``, where only the *last* version number will change when you -update. - -You may also want to upgrade the rest of your libraries. If you've done a -good job with your `version constraints`_ in ``composer.json``, you can do -this safely by running: - -.. code-block:: bash - - $ composer update - -But beware. If you have some bad `version constraints`_ in your ``composer.json``, -(e.g. ``dev-master``), then this could upgrade some non-Symfony libraries -to new versions that contain backwards-compatibility breaking changes. - -.. _upgrading-minor-version: - -Upgrading a Minor Version (e.g. 2.5.3 to 2.6.1) ------------------------------------------------ - -If you're upgrading a minor version (where the middle number changes), then -you should also *not* encounter significant backwards compatibility changes. -For details, see our :doc:`/contributing/code/bc`. - -However, some backwards-compatibility breaks *are* possible, and you'll learn -in a second how to prepare for them. - -There are two steps to upgrading: - -:ref:`upgrade-minor-symfony-composer`; -:ref:`upgrade-minor-symfony-code` - -.. _`upgrade-minor-symfony-composer`: - -1) Update the Symfony Library via Composer -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -First, you need to update Symfony by modifying your ``composer.json`` file -to use the new version: - -.. code-block:: json - - { - "...": "...", - - "require": { - "php": ">=5.3.3", - "symfony/symfony": "2.6.*", - "...": "... no changes to anything else..." - }, - "...": "...", - } - -Next, use Composer to download new versions of the libraries: - -.. code-block:: bash - - $ composer update symfony/symfony - -You may also want to upgrade the rest of your libraries. If you've done a -good job with your `version constraints`_ in ``composer.json``, you can do -this safely by running: - -.. code-block:: bash - - $ composer update - -But beware. If you have some bad `version constraints`_ in your ``composer.json``, -(e.g. ``dev-master``), then this could upgrade some non-Symfony libraries -to new versions that contain backwards-compatibility breaking changes. - -.. _`upgrade-minor-symfony-code`: - -2) Updating Your Code to Work with the new Version -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -In theory, you should be done! However, you *may* need to make a few changes -to your code to get everything working. Additionally, some features you're -using might still work, but might now be deprecated. That's actually ok, -but if you know about these deprecations, you can start to fix them over -time. - -Every version of Symfony comes with an UPGRADE file that describes these -changes. Below are links to the file for each version, which you'll need -to read to see if you need any code changes. - -.. tip:: - - Don't see the version here that you're upgrading to? Just find the - UPGRADE-X.X.md file for the appropriate version on the `Symfony Repository`_. - -Upgrading to Symfony 2.6 -........................ - -First, of course, update your ``composer.json`` file with the ``2.6`` version -of Symfony as described above in :ref:`upgrade-minor-symfony-composer`. - -Next, check the `UPGRADE-2.6`_ document for details about any code changes -that you might need to make in your project. - -Upgrading to Symfony 2.5 -........................ - -First, of course, update your ``composer.json`` file with the ``2.5`` version -of Symfony as described above in :ref:`upgrade-minor-symfony-composer`. - -Next, check the `UPGRADE-2.5`_ document for details about any code changes -that you might need to make in your project. - -.. _`UPGRADE-2.5`: https://github.com/symfony/symfony/blob/2.5/UPGRADE-2.5.md -.. _`UPGRADE-2.6`: https://github.com/symfony/symfony/blob/2.6/UPGRADE-2.6.md -.. _`Symfony Repository`: https://github.com/symfony/symfony -.. _`Composer Package Versions`: https://getcomposer.org/doc/01-basic-usage.md#package-versions -.. _`version constraints`: https://getcomposer.org/doc/01-basic-usage.md#package-versions \ No newline at end of file diff --git a/redirection_map b/redirection_map index 2d782f924fb..e325f7896a9 100644 --- a/redirection_map +++ b/redirection_map @@ -23,3 +23,4 @@ /cookbook/console/generating_urls /cookbook/console/sending_emails /components/yaml /components/yaml/introduction /components/templating /components/templating/introduction +/cookbook/upgrading /cookbook/upgrade/index From 2b0aee32f97638a80301bf1b5ccfa3593bfbc736 Mon Sep 17 00:00:00 2001 From: WouterJ Date: Tue, 10 Mar 2015 11:03:01 +0100 Subject: [PATCH 06/21] Fix little title case mistake --- contributing/code/bc.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contributing/code/bc.rst b/contributing/code/bc.rst index 2d2a5f9cc94..95613bd1763 100644 --- a/contributing/code/bc.rst +++ b/contributing/code/bc.rst @@ -1,4 +1,4 @@ -Our backwards Compatibility Promise +Our Backwards Compatibility Promise =================================== Ensuring smooth upgrades of your projects is our first priority. That's why From 300e8ab381066e2e57c8124190aeacb12c7f9aef Mon Sep 17 00:00:00 2001 From: WouterJ Date: Tue, 10 Mar 2015 11:03:41 +0100 Subject: [PATCH 07/21] Added new recipe on upgrading a major version --- cookbook/map.rst.inc | 7 +- cookbook/upgrade/index.rst | 1 + cookbook/upgrade/major_version.rst | 112 +++++++++++++++++++ images/cookbook/deprecations-in-profiler.png | Bin 0 -> 46418 bytes 4 files changed, 117 insertions(+), 3 deletions(-) create mode 100644 cookbook/upgrade/major_version.rst create mode 100644 images/cookbook/deprecations-in-profiler.png diff --git a/cookbook/map.rst.inc b/cookbook/map.rst.inc index 92bc715cee4..e268cecbe39 100644 --- a/cookbook/map.rst.inc +++ b/cookbook/map.rst.inc @@ -201,10 +201,11 @@ * (email) :doc:`/cookbook/email/testing` * (form) :doc:`/cookbook/form/unit_testing` -* :doc:`/cookbook/upgrading/index` +* :doc:`/cookbook/upgrade/index` - * :doc:`/cookbook/upgrading/patch_version` - * :doc:`/cookbook/upgrading/minor_version` + * :doc:`/cookbook/upgrade/patch_version` + * :doc:`/cookbook/upgrade/minor_version` + * :doc:`/cookbook/upgrade/major_version` * :doc:`/cookbook/validation/index` diff --git a/cookbook/upgrade/index.rst b/cookbook/upgrade/index.rst index fe4aeca3b4e..b943f2ae32a 100644 --- a/cookbook/upgrade/index.rst +++ b/cookbook/upgrade/index.rst @@ -15,3 +15,4 @@ There are three types of upgrades, all needing a little different preparation: /cookbook/upgrade/patch_version /cookbook/upgrade/minor_version + /cookbook/upgrade/major_version diff --git a/cookbook/upgrade/major_version.rst b/cookbook/upgrade/major_version.rst new file mode 100644 index 00000000000..6428c20159f --- /dev/null +++ b/cookbook/upgrade/major_version.rst @@ -0,0 +1,112 @@ +.. index:: + single: Upgrading; Major Version + +Upgrading a Major Version (e.g. 2.7.0 to 3.0.0) +=============================================== + +Every few years, Symfony releases a new major version release (the first number +changes). These releases are the trickiest to upgrade, as they are allowed to +contain BC breaks. However, Symfony tries to make this upgrade process as +smooth as possible. + +This means that you can update most of your code before the major release is +actually released. This is called making your code *future compatible*. + +There are a couple of steps to upgrading a major version: + +#. :ref:`Make your code deprecation free `; +#. :ref:`Update to the new major version via Composer `. +#. :ref:`Update your code to work with the new version ` + +.. _upgrade-major-symfony-deprecations: + +1) Make your Code Deprecation Free +---------------------------------- + +During the lifecycle of a major release, new features are added and method +signatures and public API usages are changed. However, minor versions should +not contain any backwards compatibility changes. It is made sure that there is +a so-called *backwards compatibility layer* (or BC layer). This means that the +old API will still work, while the new feature is used internally. This BC +layer is then marked as *deprecated*, indicating that it will be +removed/changed in the future. + +The major version is the only time all existing BC layers are removed. The last +minor version before a new major version (i.e. 2.7 is the last minor version of +the 2 releases, 3.0 is the next version) will trigger deprecation notices when a +BC layer is used. + +When visiting your application in the +:doc:`dev environment ` in your browser, +these notices are shown in the web dev toolbar: + +.. image:: /images/cookbook/deprecations-in-profiler.png + +Deprecations in PHPUnit +~~~~~~~~~~~~~~~~~~~~~~~ + +By default, PHPUnit will handle deprecation notices as real errors. This means +that all tests are aborted because it uses a BC layer. + +To make sure this doesn't happen, you can install the PHPUnit bridge: + +.. code-block:: bash + + $ composer require symfony/phpunit-bridge + +Now, your tests execute normally and a nice summary of the deprecation notices +is displayed at the end of the test report: + +.. code-block:: text + + $ phpunit + ... + + OK (10 tests, 20 assertions) + + Remaining deprecation notices (6) + + The "request" service is deprecated and will be removed in 3.0. Add a typehint for + Symfony\Component\HttpFoundation\Request to your controller parameters to retrieve the + request instead: 6x + 3x in PageAdminTest::testPageShow from Symfony\Cmf\SimpleCmsBundle\Tests\WebTest\Admin + 2x in PageAdminTest::testPageList from Symfony\Cmf\SimpleCmsBundle\Tests\WebTest\Admin + 1x in PageAdminTest::testPageEdit from Symfony\Cmf\SimpleCmsBundle\Tests\WebTest\Admin + +.. _upgrade-major-symfony-composer: + +2) Update to the New Major Version via Composer +----------------------------------------------- + +If your code is deprecation free, you can update the Symfony library via +Composer by modifying your ``composer.json`` file: + +.. code-block:: json + + { + "...": "...", + + "require": { + "symfony/symfony": "3.0.*", + }, + "...": "...", + } + +Next, use Composer to download new versions of the libraries: + +.. code-block:: bash + + $ composer update symfony/symfony + +.. include:: /cookbook/upgrade/_update_all_packages.rst.inc + +.. _upgrade-major-symfony-after: + +3) Update your Code to Work with the New Version +------------------------------------------------ + +There is a high chance that you're done now! However, the next major version +*may* also contain new BC breaks as a BC layer is not always a possibility. +Make sure you read the ``UPGRADE-X.0.md`` (where X is the new major version) +included in the Symfony repository for any BC break that you need to be aware +of. diff --git a/images/cookbook/deprecations-in-profiler.png b/images/cookbook/deprecations-in-profiler.png new file mode 100644 index 0000000000000000000000000000000000000000..7b32d59cb0532aa85f54612979d2b335ce363cac GIT binary patch literal 46418 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 Sl*5q?P*zZrFM0Ix?f(IHe0d1~ literal 0 HcmV?d00001 From 99c5075a6531f962dce504ed21a7c0fca00cc451 Mon Sep 17 00:00:00 2001 From: WouterJ Date: Tue, 14 Apr 2015 12:13:04 +0200 Subject: [PATCH 08/21] Fix typo --- cookbook/upgrade/_update_all_packages.rst.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook/upgrade/_update_all_packages.rst.inc b/cookbook/upgrade/_update_all_packages.rst.inc index 49d82e9fe12..b309e054327 100644 --- a/cookbook/upgrade/_update_all_packages.rst.inc +++ b/cookbook/upgrade/_update_all_packages.rst.inc @@ -13,4 +13,4 @@ this safely by running: non-Symfony libraries to new versions that contain backwards-compatibility breaking changes. -.. _`versino constraints`: https://getcomposer.org/doc/01-basic-usage.md#package-versions +.. _`version constraints`: https://getcomposer.org/doc/01-basic-usage.md#package-versions From 9fc609dbe2e706d21474cfe0b263595d499fc7f5 Mon Sep 17 00:00:00 2001 From: Brian Gallagher Date: Wed, 20 May 2015 12:49:30 -0400 Subject: [PATCH 09/21] Better illustrate what the "user mistake" is. --- components/options_resolver.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/options_resolver.rst b/components/options_resolver.rst index 7320962fdba..c32ae8d3c6e 100644 --- a/components/options_resolver.rst +++ b/components/options_resolver.rst @@ -96,7 +96,7 @@ the ``Mailer`` class makes a mistake? .. code-block:: php $mailer = new Mailer(array( - 'usernme' => 'johndoe', + 'usernme' => 'johndoe', # usernAme misspelled )); No error will be shown. In the best case, the bug will appear during testing, From 8845da096a365e9a2131cd7c9ab3c65b2a7ff238 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sat, 23 May 2015 09:51:29 +0200 Subject: [PATCH 10/21] [BestPractices] restructured text format for the installation instructions template --- conf.py | 6 ++ cookbook/bundles/best_practices.rst | 112 ++++++++++++++++++++-------- 2 files changed, 87 insertions(+), 31 deletions(-) diff --git a/conf.py b/conf.py index 291205d1d73..ab4e823e384 100644 --- a/conf.py +++ b/conf.py @@ -23,6 +23,8 @@ # adding PhpLexer from sphinx.highlighting import lexers from pygments.lexers.compiled import CLexer +from pygments.lexers.special import TextLexer +from pygments.lexers.text import RstLexer from pygments.lexers.web import PhpLexer # -- General configuration ----------------------------------------------------- @@ -97,14 +99,18 @@ # -- Settings for symfony doc extension --------------------------------------------------- # enable highlighting for PHP code not between ```` by default +lexers['markdown'] = TextLexer() lexers['php'] = PhpLexer(startinline=True) lexers['php-annotations'] = PhpLexer(startinline=True) lexers['php-standalone'] = PhpLexer(startinline=True) lexers['php-symfony'] = PhpLexer(startinline=True) +lexers['rst'] = RstLexer() lexers['varnish3'] = CLexer() lexers['varnish4'] = CLexer() config_block = { + 'markdown': 'Markdown', + 'rst': 'reStructuredText', 'varnish3': 'Varnish 3', 'varnish4': 'Varnish 4' } diff --git a/cookbook/bundles/best_practices.rst b/cookbook/bundles/best_practices.rst index 46389382840..321411673d7 100644 --- a/cookbook/bundles/best_practices.rst +++ b/cookbook/bundles/best_practices.rst @@ -209,52 +209,102 @@ Installation Instructions In order to ease the installation of third-party bundles, consider using the following standardized instructions in your ``README.md`` file. -.. code-block:: text +.. configuration-block:: - Installation - ============ + .. code-block:: markdown - Step 1: Download the Bundle - --------------------------- + Installation + ============ - Open a command console, enter your project directory and execute the - following command to download the latest stable version of this bundle: + Step 1: Download the Bundle + --------------------------- - ```bash - $ composer require "~1" - ``` + Open a command console, enter your project directory and execute the + following command to download the latest stable version of this bundle: - This command requires you to have Composer installed globally, as explained - in the [installation chapter](https://getcomposer.org/doc/00-intro.md) - of the Composer documentation. + ```bash + $ composer require "~1" + ``` - Step 2: Enable the Bundle - ------------------------- + This command requires you to have Composer installed globally, as explained + in the [installation chapter](https://getcomposer.org/doc/00-intro.md) + of the Composer documentation. - Then, enable the bundle by adding the following line in the `app/AppKernel.php` - file of your project: + Step 2: Enable the Bundle + ------------------------- - ```php - \\(), + ); - new \\(), - ); + // ... + } // ... } + ``` - // ... - } - ``` + .. code-block:: rst + + Installation + ============ + + Step 1: Download the Bundle + --------------------------- + + Open a command console, enter your project directory and execute the + following command to download the latest stable version of this bundle: + + .. code-block:: bash + + $ composer require "~1" + + This command requires you to have Composer installed globally, as explained + in the `installation chapter`_ of the Composer documentation. + + Step 2: Enable the Bundle + ------------------------- + + Then, enable the bundle by adding the following line in the ``app/AppKernel.php`` + file of your project: + + .. code-block:: php + + \\(), + ); + + // ... + } + + // ... + } + + .. _`installation chapter`: https://getcomposer.org/doc/00-intro.md This template assumes that your bundle is in its ``1.x`` version. If not, change the ``"~1"`` installation version accordingly (``"~2"``, ``"~3"``, etc.) From 55fcee9a898db5ee8ee382a235a97f9ed1738b67 Mon Sep 17 00:00:00 2001 From: WouterJ Date: Sat, 23 May 2015 10:25:29 +0200 Subject: [PATCH 11/21] Applied comments --- cookbook/upgrade/_update_all_packages.rst.inc | 2 +- cookbook/upgrade/major_version.rst | 10 ++++++---- cookbook/upgrade/minor_version.rst | 2 +- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/cookbook/upgrade/_update_all_packages.rst.inc b/cookbook/upgrade/_update_all_packages.rst.inc index b309e054327..95e1c63f954 100644 --- a/cookbook/upgrade/_update_all_packages.rst.inc +++ b/cookbook/upgrade/_update_all_packages.rst.inc @@ -8,7 +8,7 @@ this safely by running: .. caution:: - Beware, if you have some bad `version constraints`_ in your + Beware, if you have some unspecific `version constraints`_ in your ``composer.json`` (e.g. ``dev-master``), this could upgrade some non-Symfony libraries to new versions that contain backwards-compatibility breaking changes. diff --git a/cookbook/upgrade/major_version.rst b/cookbook/upgrade/major_version.rst index 6428c20159f..67dc641d14f 100644 --- a/cookbook/upgrade/major_version.rst +++ b/cookbook/upgrade/major_version.rst @@ -31,10 +31,12 @@ old API will still work, while the new feature is used internally. This BC layer is then marked as *deprecated*, indicating that it will be removed/changed in the future. -The major version is the only time all existing BC layers are removed. The last -minor version before a new major version (i.e. 2.7 is the last minor version of -the 2 releases, 3.0 is the next version) will trigger deprecation notices when a -BC layer is used. +The major version is the only time all existing BC layers are removed. However, +if you make sure you've fixed all deprecated usages in the last version of the +previous major version, you should be able to upgrade to the new major version +without problems. To help you with this, the last minor releases will trigger +deprecated notices. For example, 2.7 and 2.8 trigger deprecated notices and if +you do not have any notice while using 2.8, you can savely upgrade to 3.0. When visiting your application in the :doc:`dev environment ` in your browser, diff --git a/cookbook/upgrade/minor_version.rst b/cookbook/upgrade/minor_version.rst index 4a5a0fa023e..3fa2d58970a 100644 --- a/cookbook/upgrade/minor_version.rst +++ b/cookbook/upgrade/minor_version.rst @@ -45,7 +45,7 @@ Next, use Composer to download new versions of the libraries: .. _`upgrade-minor-symfony-code`: -2) Updating Your Code to Work with the new Version +2) Updating your Code to Work with the new Version -------------------------------------------------- In theory, you should be done! However, you *may* need to make a few changes From 6094deb4a0b39be2e5643ee08890ad1ab329a1f0 Mon Sep 17 00:00:00 2001 From: Brian Gallagher Date: Sun, 24 May 2015 12:23:11 -0400 Subject: [PATCH 12/21] Changed comment from # to // --- components/options_resolver.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/options_resolver.rst b/components/options_resolver.rst index c32ae8d3c6e..9d4f00285f1 100644 --- a/components/options_resolver.rst +++ b/components/options_resolver.rst @@ -96,7 +96,7 @@ the ``Mailer`` class makes a mistake? .. code-block:: php $mailer = new Mailer(array( - 'usernme' => 'johndoe', # usernAme misspelled + 'usernme' => 'johndoe', // usernAme misspelled )); No error will be shown. In the best case, the bug will appear during testing, From 328e481f98f941bf626077c39af29cd750381014 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 31 Mar 2015 09:18:05 +0200 Subject: [PATCH 13/21] [VarDumper] Add doc for assertDump* assertions --- components/var_dumper/introduction.rst | 47 ++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/components/var_dumper/introduction.rst b/components/var_dumper/introduction.rst index 05eff3e8849..2f125192763 100644 --- a/components/var_dumper/introduction.rst +++ b/components/var_dumper/introduction.rst @@ -122,6 +122,53 @@ original value. You can configure the limits in terms of: +Using the VarDumper Component in your PHPUnit Test Suite +-------------------------------------------------------- + +.. versionadded:: 2.7 + The :class:`Symfony\\Component\\VarDumper\\Test\\VarDumperTestTrait` was + introduced in Symfony 2.7. + +The VarDumper component provides +:class:`a trait ` +that can help writing some of your tests for PHPUnit. + +This will provide you with two new assertions: + +:method:`Symfony\\Component\\VarDumper\\Test\\VarDumperTestTrait::assertDumpEquals` + verifies that the dump of the variable given as the second argument matches + the expected dump provided as a string in the first argument. + +:method:`Symfony\\Component\\VarDumper\\Test\\VarDumperTestTrait::assertDumpMatchesFormat` + is like the previous method but accepts placeholders in the expected dump, + based on the ``assertStringMatchesFormat`` method provided by PHPUnit. + +Example:: + + class ExampleTest extends \PHPUnit_Framework_TestCase + { + use \Symfony\Component\VarDumper\Test\VarDumperTestTrait; + + public function testWithDumpEquals() + { + $testedVar = array(123, 'foo'); + + $expectedDump = << 123 + 1 => "foo" + ] + EOTXT; + + $this->assertDumpEquals($expectedDump, $testedVar); + } + } + +.. tip:: + + If you still use PHP 5.3, you can extend the + :class:`Symfony\\Component\\VarDumper\\Test\\VarDumperTestClass` instead. + Dump Examples and Output ------------------------ From 31999dbab4d15f2fe7ed9f4d85eb05ec8f8c4ac2 Mon Sep 17 00:00:00 2001 From: WouterJ Date: Mon, 25 May 2015 00:01:56 +0200 Subject: [PATCH 14/21] Fixes after review --- cookbook/upgrade/major_version.rst | 34 ++++++++++++++---------------- cookbook/upgrade/minor_version.rst | 9 ++++---- 2 files changed, 21 insertions(+), 22 deletions(-) diff --git a/cookbook/upgrade/major_version.rst b/cookbook/upgrade/major_version.rst index 67dc641d14f..ddc1d271d07 100644 --- a/cookbook/upgrade/major_version.rst +++ b/cookbook/upgrade/major_version.rst @@ -24,23 +24,21 @@ There are a couple of steps to upgrading a major version: ---------------------------------- During the lifecycle of a major release, new features are added and method -signatures and public API usages are changed. However, minor versions should -not contain any backwards compatibility changes. It is made sure that there is -a so-called *backwards compatibility layer* (or BC layer). This means that the -old API will still work, while the new feature is used internally. This BC -layer is then marked as *deprecated*, indicating that it will be -removed/changed in the future. - -The major version is the only time all existing BC layers are removed. However, -if you make sure you've fixed all deprecated usages in the last version of the -previous major version, you should be able to upgrade to the new major version -without problems. To help you with this, the last minor releases will trigger -deprecated notices. For example, 2.7 and 2.8 trigger deprecated notices and if -you do not have any notice while using 2.8, you can savely upgrade to 3.0. - -When visiting your application in the -:doc:`dev environment ` in your browser, -these notices are shown in the web dev toolbar: +signatures and public API usages are changed. However, +:doc:`minor versions ` +in your browser, these notices are shown in the web dev toolbar: .. image:: /images/cookbook/deprecations-in-profiler.png @@ -107,7 +105,7 @@ Next, use Composer to download new versions of the libraries: 3) Update your Code to Work with the New Version ------------------------------------------------ -There is a high chance that you're done now! However, the next major version +There is a good chance that you're done now! However, the next major version *may* also contain new BC breaks as a BC layer is not always a possibility. Make sure you read the ``UPGRADE-X.0.md`` (where X is the new major version) included in the Symfony repository for any BC break that you need to be aware diff --git a/cookbook/upgrade/minor_version.rst b/cookbook/upgrade/minor_version.rst index 3fa2d58970a..55b63bb0580 100644 --- a/cookbook/upgrade/minor_version.rst +++ b/cookbook/upgrade/minor_version.rst @@ -53,11 +53,12 @@ to your code to get everything working. Additionally, some features you're using might still work, but might now be deprecated. While that's just fine, if you know about these deprecations, you can start to fix them over time. -Every version of Symfony comes with an UPGRADE file included in the Symfony -directory that describes these changes. If you follow the instructions in the -document and update your code accordingly, it should be save to update in the -future. +Every version of Symfony comes with an UPGRADE file (e.g. `UPGRADE-2.7.md`_) +included in the Symfony directory that describes these changes. If you follow +the instructions in the document and update your code accordingly, it should be +safe to update in the future. These documents can also be found in the `Symfony Repository`_. .. _`Symfony Repository`: https://github.com/symfony/symfony +.. _`UPGRADE-2.7.md`: https://github.com/symfony/symfony/blob/2.7/UPGRADE-2.7.md From db1e79868f48a013e9c0c2e22277e30ac8dec246 Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Mon, 25 May 2015 10:31:52 +0200 Subject: [PATCH 15/21] Created a new section for rotating log files and explained the max_files configuration option --- cookbook/logging/monolog.rst | 116 +++++++++++++++++++---------------- 1 file changed, 63 insertions(+), 53 deletions(-) diff --git a/cookbook/logging/monolog.rst b/cookbook/logging/monolog.rst index b464e6d976e..7b05f9f9e79 100644 --- a/cookbook/logging/monolog.rst +++ b/cookbook/logging/monolog.rst @@ -222,6 +222,69 @@ easily. Your formatter must implement ), )); +How to Rotate your Log Files +---------------------------- + +Beware that log file sizes can grow very rapidly, leading to disk space exhaustion. +This is specially true in the ``dev`` environment, where a simple request can +generate hundreds of log lines. Consider using tools like the `logrotate`_ +Linux command to rotate log files before they become a problem. + +In case you cannot use a dedicated tool for rotating log files, consider using +the special ``rotating_file`` handler defined by Monolog. This handler creates +a new log file every day and can also remove old files automatically. To use +it, just set the ``type`` option of your handler to ``rotating_file``: + +.. configuration-block:: + + .. code-block:: yaml + + # app/config/config_dev.yml + monolog: + handlers: + main: + type: rotating_file + path: %kernel.logs_dir%/%kernel.environment%.log + level: debug + # max number of log files to keep + # defaults to zero, which means infinite files + max_files: 10 + + .. code-block:: xml + + + + + + + + max_files="10" + /> + + + + .. code-block:: php + + // app/config/config_dev.php + $container->loadFromExtension('monolog', array( + 'handlers' => array( + 'main' => array( + 'type' => 'rotating_file', + 'path' => '%kernel.logs_dir%/%kernel.environment%.log', + 'level' => 'debug', + // max number of log files to keep + // defaults to zero, which means infinite files + 'max_files' => 10, + ), + ), + )); + Adding some extra Data in the Log Messages ------------------------------------------ @@ -229,59 +292,6 @@ Monolog allows you to process the record before logging it to add some extra data. A processor can be applied for the whole handler stack or only for a specific handler. -.. tip:: - - Beware that log file sizes can grow very rapidly, leading to disk space exhaustion. - This is specially true in the ``dev`` environment, where a simple request can - generate hundreds of log lines. Consider using tools like the `logrotate`_ - Linux command to rotate log files before they become a problem. - - In case you cannot use a dedicated tool for rotating log files, consider using - the special ``rotating_file`` handler defined by Monolog. This handler creates - a new log file every day and can also remove old files automatically. To use - it, just set the ``type`` option of your handler to ``rotating_file``: - - .. configuration-block:: - - .. code-block:: yaml - - # app/config/config_dev.yml - monolog: - handlers: - main: - type: rotating_file - path: %kernel.logs_dir%/%kernel.environment%.log - level: debug - - .. code-block:: xml - - - - - - - - - - - .. code-block:: php - - // app/config/config_dev.php - $container->loadFromExtension('monolog', array( - 'handlers' => array( - 'main' => array( - 'type' => 'rotating_file', - 'path' => '%kernel.logs_dir%/%kernel.environment%.log', - 'level' => 'debug', - ), - ), - )); - A processor is simply a callable receiving the record as its first argument. Processors are configured using the ``monolog.processor`` DIC tag. See the :ref:`reference about it `. From 604ccabbc7c7ab849059c87f61f1dafe7d8262a9 Mon Sep 17 00:00:00 2001 From: Wouter J Date: Mon, 25 May 2015 10:44:13 +0200 Subject: [PATCH 16/21] Fix formatting error --- cookbook/upgrade/major_version.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cookbook/upgrade/major_version.rst b/cookbook/upgrade/major_version.rst index ddc1d271d07..10fcafbbf83 100644 --- a/cookbook/upgrade/major_version.rst +++ b/cookbook/upgrade/major_version.rst @@ -25,7 +25,7 @@ There are a couple of steps to upgrading a major version: During the lifecycle of a major release, new features are added and method signatures and public API usages are changed. However, -:doc:`minor versions ` should not contain any backwards compatibility changes. To accomplish this, the "old" (e.g. functions, classes, etc) code still works, but is marked as *deprecated*, indicating that it will be removed/changed in the future and that you should stop using it. From e7c984f94e847fcd1979a851c5b5256e73130ab2 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Mon, 25 May 2015 18:46:53 -0400 Subject: [PATCH 17/21] Slight re-wording of new paragraph with the goal of being as short as possible --- cookbook/logging/monolog.rst | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/cookbook/logging/monolog.rst b/cookbook/logging/monolog.rst index dbdffcaadce..a7c51bd1c38 100644 --- a/cookbook/logging/monolog.rst +++ b/cookbook/logging/monolog.rst @@ -225,15 +225,14 @@ easily. Your formatter must implement How to Rotate your Log Files ---------------------------- -Beware that log file sizes can grow very rapidly, leading to disk space exhaustion. -This is specially true in the ``dev`` environment, where a simple request can -generate hundreds of log lines. Consider using tools like the `logrotate`_ -Linux command to rotate log files before they become a problem. - -In case you cannot use a dedicated tool for rotating log files, consider using -the special ``rotating_file`` handler defined by Monolog. This handler creates -a new log file every day and can also remove old files automatically. To use -it, just set the ``type`` option of your handler to ``rotating_file``: +Over time, log files can grow to be *huge*, both while developing and on +production. One best-practice solution is to use a tool like the `logrotate`_ +Linux command to rotate log files before they become too large. + +Another option is to have Monolog rotate the files for you by using the +``rotating_file`` handler. This handler creates a new log file every day +and can also remove old files automatically. To use it, just set the ``type`` +option of your handler to ``rotating_file``: .. configuration-block:: From ce9456c7a74d06ce70cb9891e9e4332b7fdd58f7 Mon Sep 17 00:00:00 2001 From: Alfonso M Date: Sat, 23 May 2015 18:12:38 +0200 Subject: [PATCH 18/21] Place DQL in front of QueryBuilder --- book/doctrine.rst | 54 +++++++++++++++++++++++------------------------ 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/book/doctrine.rst b/book/doctrine.rst index d354f0f258c..11cab0891df 100644 --- a/book/doctrine.rst +++ b/book/doctrine.rst @@ -722,6 +722,33 @@ instead of querying for rows on a table (e.g. ``product``). When querying in Doctrine, you have two options: writing pure Doctrine queries or using Doctrine's Query Builder. +Querying for Objects with DQL +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Instead of using the ``QueryBuilder``, you can alternatively write the queries +directly using DQL:: + + $em = $this->getDoctrine()->getManager(); + $query = $em->createQuery( + 'SELECT p + FROM AppBundle:Product p + WHERE p.price > :price + ORDER BY p.price ASC' + )->setParameter('price', '19.99'); + + $products = $query->getResult(); + +If you're comfortable with SQL, then DQL should feel very natural. The biggest +difference is that you need to think in terms of "objects" instead of rows +in a database. For this reason, you select *from* the ``AppBundle:Product`` +*object* and then alias it as ``p`` (as you see, this is equal to what you +already did in the previous section). + +The DQL syntax is incredibly powerful, allowing you to easily join between +entities (the topic of :ref:`relations ` will be +covered later), group, etc. For more information, see the official +`Doctrine Query Language`_ documentation. + Querying for Objects Using Doctrine's Query Builder ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -759,33 +786,6 @@ is no result) or ``getOneOrNullResult()``:: For more information on Doctrine's Query Builder, consult Doctrine's `Query Builder`_ documentation. -Querying for Objects with DQL -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Instead of using the ``QueryBuilder``, you can alternatively write the queries -directly using DQL:: - - $em = $this->getDoctrine()->getManager(); - $query = $em->createQuery( - 'SELECT p - FROM AppBundle:Product p - WHERE p.price > :price - ORDER BY p.price ASC' - )->setParameter('price', '19.99'); - - $products = $query->getResult(); - -If you're comfortable with SQL, then DQL should feel very natural. The biggest -difference is that you need to think in terms of "objects" instead of rows -in a database. For this reason, you select *from* the ``AppBundle:Product`` -*object* and then alias it as ``p`` (as you see, this is equal to what you -already did in the previous section). - -The DQL syntax is incredibly powerful, allowing you to easily join between -entities (the topic of :ref:`relations ` will be -covered later), group, etc. For more information, see the official -`Doctrine Query Language`_ documentation. - .. _book-doctrine-custom-repository-classes: Custom Repository Classes From 23352065a0af778aa7df6233926e659a6c7560d6 Mon Sep 17 00:00:00 2001 From: Alfonso M Date: Sat, 23 May 2015 19:24:33 +0200 Subject: [PATCH 19/21] Update doctrine.rst --- book/doctrine.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/book/doctrine.rst b/book/doctrine.rst index 11cab0891df..9f0740b3b82 100644 --- a/book/doctrine.rst +++ b/book/doctrine.rst @@ -725,8 +725,9 @@ or using Doctrine's Query Builder. Querying for Objects with DQL ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Instead of using the ``QueryBuilder``, you can alternatively write the queries -directly using DQL:: +Imagine that you want to query for products, but only return products that +cost more than ``19.99``, ordered from cheapest to most expensive. You can use +Doctrine's native SQL-like language called DQL to do query for this:: $em = $this->getDoctrine()->getManager(); $query = $em->createQuery( @@ -752,9 +753,8 @@ covered later), group, etc. For more information, see the official Querying for Objects Using Doctrine's Query Builder ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Imagine that you want to query for products, but only return products that -cost more than ``19.99``, ordered from cheapest to most expensive. You can use -Doctrine's ``QueryBuilder`` for this:: +Instead of writing a DQL string, you can alternatively use a helpful object called +the ``QueryBuilder`` to build that string for you:: $repository = $this->getDoctrine() ->getRepository('AppBundle:Product'); From 7e7020deac8848acc8d3c6c27f6ef1ac92022fe6 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Mon, 25 May 2015 19:05:05 -0400 Subject: [PATCH 20/21] [#5302] Re-reading sections after moving them, and tweaking some things that did not make sense anymore Also, adding some extra code blocks to show how to query for one result --- book/doctrine.rst | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/book/doctrine.rst b/book/doctrine.rst index 9f0740b3b82..fe2a1c6758f 100644 --- a/book/doctrine.rst +++ b/book/doctrine.rst @@ -727,7 +727,7 @@ Querying for Objects with DQL Imagine that you want to query for products, but only return products that cost more than ``19.99``, ordered from cheapest to most expensive. You can use -Doctrine's native SQL-like language called DQL to do query for this:: +Doctrine's native SQL-like language called DQL to make a query for this:: $em = $this->getDoctrine()->getManager(); $query = $em->createQuery( @@ -738,12 +738,25 @@ Doctrine's native SQL-like language called DQL to do query for this:: )->setParameter('price', '19.99'); $products = $query->getResult(); + // to get just one result: + // $product = $query->setMaxResults(1)->getOneOrNullResult(); If you're comfortable with SQL, then DQL should feel very natural. The biggest difference is that you need to think in terms of "objects" instead of rows in a database. For this reason, you select *from* the ``AppBundle:Product`` -*object* and then alias it as ``p`` (as you see, this is equal to what you -already did in the previous section). +*object* (an optional shortcut for ``AppBundle\Entity\Product``) and then +alias it as ``p``. + +.. tip:: + + Take note of the ``setParameter()`` method. When working with Doctrine, + it's always a good idea to set any external values as "placeholders" + (``:price`` in the example above) as it prevents SQL injection attacks. + +The ``getResult()`` method returns an array of results. To get only one +result, you can use ``getOneOrNullResult()``:: + + $product = $query->setMaxResults(1)->getOneOrNullResult(); The DQL syntax is incredibly powerful, allowing you to easily join between entities (the topic of :ref:`relations ` will be @@ -759,6 +772,8 @@ the ``QueryBuilder`` to build that string for you:: $repository = $this->getDoctrine() ->getRepository('AppBundle:Product'); + // createQueryBuilder automatically selects FROM AppBundle:Product + // and aliases it to "p" $query = $repository->createQueryBuilder('p') ->where('p.price > :price') ->setParameter('price', '19.99') @@ -766,23 +781,13 @@ the ``QueryBuilder`` to build that string for you:: ->getQuery(); $products = $query->getResult(); + // to get just one result: + // $product = $query->setMaxResults(1)->getOneOrNullResult(); The ``QueryBuilder`` object contains every method necessary to build your query. By calling the ``getQuery()`` method, the query builder returns a normal ``Query`` object, which can be used to get the result of the query. -.. tip:: - - Take note of the ``setParameter()`` method. When working with Doctrine, - it's always a good idea to set any external values as "placeholders" - (``:price`` in the example above) as it prevents SQL injection attacks. - -The ``getResult()`` method returns an array of results. To get only one -result, you can use ``getSingleResult()`` (which throws an exception if there -is no result) or ``getOneOrNullResult()``:: - - $product = $query->getOneOrNullResult(); - For more information on Doctrine's Query Builder, consult Doctrine's `Query Builder`_ documentation. From bc79b21cf91637a9f26918c69be6b2a9e75b45ca Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Mon, 25 May 2015 19:22:07 -0400 Subject: [PATCH 21/21] Adding one more note about why we're in config.yml --- cookbook/logging/channels_handlers.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cookbook/logging/channels_handlers.rst b/cookbook/logging/channels_handlers.rst index db9a92298c5..88ce8ed3d33 100644 --- a/cookbook/logging/channels_handlers.rst +++ b/cookbook/logging/channels_handlers.rst @@ -25,7 +25,8 @@ Switching a Channel to a different Handler Now, suppose you want to log the ``security`` channel to a different file. To do this, just create a new handler and configure it to log only messages -from the ``security`` channel: +from the ``security`` channel. You might add this in ``config.yml`` to log +in all environments, or just ``config_prod.yml`` to happen only in ``prod``: .. configuration-block::