Skip to content

Commit 0ef7e1a

Browse files
committed
Merge branch '2.8'
* 2.8: (22 commits) Changed PhpStormOpener to PhpStormProtocol [#5402] Being explicit what this applies to (it should not apply to things like >=) [Contributing] [Conventions] Added entry for Yoda conditions Added the "payload" option back Show annotations first Reordered the code blocks to show Annotations, YAML, XML and PHP Fixed the issues reported by @xabbuh Finished the documentation of the new data comparison validators Added information about the new date handling in the comparison constraints and Range Document security.switch_user event [#5332] typo [#5335] Minor tweaks document new Doctrine APC cache service Added some more docs about the remember me feature [Serializer] Updated the cookbook. Fixed a minor grammar issue Fixed a minor grammar issue [Serializer] ObjectNormalizer, object_to_populate doc. Minor enhancements. Added support for standard Forwarded header Added support for standard Forwarded header ...
2 parents cc87822 + 9cbf3d4 commit 0ef7e1a

File tree

13 files changed

+1332
-598
lines changed

13 files changed

+1332
-598
lines changed

Diff for: book/propel.rst

+13-526
Large diffs are not rendered by default.

Diff for: components/serializer.rst

+77-20
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,12 @@ You can install the component in 2 different ways:
3333
* :doc:`Install it via Composer </components/using_components>` (``symfony/serializer`` on `Packagist`_);
3434
* Use the official Git repository (https://github.com./symfony/Serializer).
3535

36+
3637
.. include:: /components/require_autoload.rst.inc
3738

39+
To use the ``ObjectNormalizer``, the :doc:`PropertyAccess component </components/property_access/index>`
40+
must also be installed.
41+
3842
Usage
3943
-----
4044

@@ -45,18 +49,18 @@ which Encoders and Normalizer are going to be available::
4549
use Symfony\Component\Serializer\Serializer;
4650
use Symfony\Component\Serializer\Encoder\XmlEncoder;
4751
use Symfony\Component\Serializer\Encoder\JsonEncoder;
48-
use Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer;
52+
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
4953

5054
$encoders = array(new XmlEncoder(), new JsonEncoder());
51-
$normalizers = array(new GetSetMethodNormalizer());
55+
$normalizers = array(new ObjectNormalizer());
5256

5357
$serializer = new Serializer($normalizers, $encoders);
5458

55-
There are several normalizers available, e.g. the
56-
:class:`Symfony\\Component\\Serializer\\Normalizer\\GetSetMethodNormalizer` or
57-
the :class:`Symfony\\Component\\Serializer\\Normalizer\\PropertyNormalizer`.
59+
The preferred normalizer is the
60+
:class:`Symfony\\Component\\Serializer\\Normalizer\\ObjectNormalizer`, but other
61+
normalizers are available.
5862
To read more about them, refer to the `Normalizers`_ section of this page. All
59-
the examples shown below use the ``GetSetMethodNormalizer``.
63+
the examples shown below use the ``ObjectNormalizer``.
6064

6165
Serializing an Object
6266
---------------------
@@ -147,6 +151,30 @@ needs three parameters:
147151
#. The name of the class this information will be decoded to
148152
#. The encoder used to convert that information into an array
149153

154+
Deserializing in an Existing Object
155+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
156+
157+
The serializer can also be used to update an existing object::
158+
159+
$person = new Acme\Person();
160+
$person->setName('bar');
161+
$person->setAge(99);
162+
$person->setSportsman(true);
163+
164+
$data = <<<EOF
165+
<person>
166+
<name>foo</name>
167+
<age>69</age>
168+
</person>
169+
EOF;
170+
171+
$serializer->deserialize($data, 'Acme\Person', 'xml', array('object_to_populate' => $person));
172+
// $obj2 = Acme\Person(name: 'foo', age: '99', sportsman: true)
173+
174+
This is a common need when working with an ORM.
175+
176+
.. _component-serializer-attributes-groups:
177+
150178
Attributes Groups
151179
-----------------
152180

@@ -200,6 +228,8 @@ like the following::
200228
// For YAML
201229
// $classMetadataFactory = new ClassMetadataFactory(new YamlFileLoader('/path/to/your/definition.yml'));
202230

231+
.. _component-serializer-attributes-groups-annotations:
232+
203233
Then, create your groups definition:
204234

205235
.. configuration-block::
@@ -285,8 +315,13 @@ You are now able to serialize only attributes in the groups you want::
285315
Ignoring Attributes
286316
-------------------
287317

318+
.. note::
319+
320+
Using attribute groups instead of the :method:`Symfony\\Component\\Serializer\\Normalizer\\AbstractNormalizer::setIgnoredAttributes`
321+
method is considered best practice.
322+
288323
.. versionadded:: 2.3
289-
The :method:`Symfony\\Component\\Serializer\\Normalizer\\GetSetMethodNormalizer::setIgnoredAttributes`
324+
The :method:`Symfony\\Component\\Serializer\\Normalizer\\AbstractNormalizer::setIgnoredAttributes`
290325
method was introduced in Symfony 2.3.
291326

292327
.. versionadded:: 2.7
@@ -295,14 +330,14 @@ Ignoring Attributes
295330

296331
As an option, there's a way to ignore attributes from the origin object. To remove
297332
those attributes use the
298-
:method:`Symfony\\Component\\Serializer\\Normalizer\\GetSetMethodNormalizer::setIgnoredAttributes`
333+
:method:`Symfony\\Component\\Serializer\\Normalizer\\AbstractNormalizer::setIgnoredAttributes`
299334
method on the normalizer definition::
300335

301336
use Symfony\Component\Serializer\Serializer;
302337
use Symfony\Component\Serializer\Encoder\JsonEncoder;
303-
use Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer;
338+
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
304339

305-
$normalizer = new GetSetMethodNormalizer();
340+
$normalizer = new ObjectNormalizer();
306341
$normalizer->setIgnoredAttributes(array('age'));
307342
$encoder = new JsonEncoder();
308343

@@ -359,11 +394,11 @@ including :class:`Symfony\\Component\\Serializer\\Normalizer\\GetSetMethodNormal
359394
and :class:`Symfony\\Component\\Serializer\\Normalizer\\PropertyNormalizer`::
360395

361396
use Symfony\Component\Serializer\Encoder\JsonEncoder
362-
use Symfony\Component\Serializer\Normalizer\PropertyNormalizer;
397+
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
363398
use Symfony\Component\Serializer\Serializer;
364399

365400
$nameConverter = new OrgPrefixNameConverter();
366-
$normalizer = new PropertyNormalizer(null, $nameConverter);
401+
$normalizer = new ObjectNormalizer(null, $nameConverter);
367402

368403
$serializer = new Serializer(array($normalizer), array(new JsonEncoder()));
369404

@@ -394,9 +429,9 @@ snake_case and CamelCased styles during serialization and deserialization
394429
processes::
395430

396431
use Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter;
397-
use Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer;
432+
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
398433

399-
$normalizer = new GetSetMethodNormalizer(null, new CamelCaseToSnakeCaseNameConverter());
434+
$normalizer = new ObjectNormalizer(null, new CamelCaseToSnakeCaseNameConverter());
400435

401436
class Person
402437
{
@@ -427,6 +462,9 @@ If you are using isser methods (methods prefixed by ``is``, like
427462
``Acme\Person::isSportsman()``), the Serializer component will automatically
428463
detect and use it to serialize related attributes.
429464

465+
The ``ObjectNormalizer`` also takes care of methods starting with ``has``, ``add``
466+
and ``remove``.
467+
430468
Using Callbacks to Serialize Properties with Object Instances
431469
-------------------------------------------------------------
432470

@@ -463,23 +501,42 @@ Normalizers
463501

464502
There are several types of normalizers available:
465503

504+
:class:`Symfony\\Component\\Serializer\\Normalizer\\ObjectNormalizer`
505+
This normalizer leverages the :doc:`PropertyAccess Component </components/property_access/index>`
506+
to read and write in the object. It means that it can access to properties
507+
directly and through getters, setters, hassers, adders and removers. It supports
508+
calling the constructor during the denormalization process.
509+
510+
Objects are normalized to a map of property names (method name stripped of
511+
the "get"/"set"/"has"/"remove" prefix and converted to lower case) to property
512+
values.
513+
514+
The ``ObjectNormalizer`` is the most powerful normalizer. It is a configured
515+
by default when using the Symfony Standard Edition with the serializer enabled.
516+
466517
:class:`Symfony\\Component\\Serializer\\Normalizer\\GetSetMethodNormalizer`
467518
This normalizer reads the content of the class by calling the "getters"
468519
(public methods starting with "get"). It will denormalize data by calling
469520
the constructor and the "setters" (public methods starting with "set").
470521

471-
Objects are serialized to a map of property names (method name stripped of
522+
Objects are normalized to a map of property names (method name stripped of
472523
the "get" prefix and converted to lower case) to property values.
473524

474525
:class:`Symfony\\Component\\Serializer\\Normalizer\\PropertyNormalizer`
475526
This normalizer directly reads and writes public properties as well as
476-
**private and protected** properties. Objects are normalized to a map of
477-
property names to property values.
527+
**private and protected** properties. It supports calling the constructor
528+
during the denormalization process.
529+
530+
Objects are normalized to a map of property names to property values.
478531

479-
.. versionadded:: 2.6 The
480-
:class:`Symfony\\Component\\Serializer\\Normalizer\\PropertyNormalizer`
532+
.. versionadded:: 2.6
533+
The :class:`Symfony\\Component\\Serializer\\Normalizer\\PropertyNormalizer`
481534
class was introduced in Symfony 2.6.
482535

536+
.. versionadded:: 2.7
537+
The :class:`Symfony\\Component\\Serializer\\Normalizer\\ObjectNormalizer`
538+
class was introduced in Symfony 2.7.
539+
483540
Handling Circular References
484541
----------------------------
485542

@@ -565,7 +622,7 @@ by custom callables. This is especially useful when serializing entities
565622
having unique identifiers::
566623

567624
$encoder = new JsonEncoder();
568-
$normalizer = new GetSetMethodNormalizer();
625+
$normalizer = new ObjectNormalizer();
569626

570627
$normalizer->setCircularReferenceHandler(function ($object) {
571628
return $object->getName();

Diff for: contributing/code/standards.rst

+5
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,10 @@ Structure
102102

103103
* Always use `identical comparison`_ unless you need type juggling;
104104

105+
* Use `Yoda conditions`_ when checking a variable against an expression to avoid
106+
an accidental assignment inside the condition statement (this applies to ``==``,
107+
``!=``, ``===``, and ``!==``);
108+
105109
* Add a comma after each array item in a multi-line array, even after the
106110
last one;
107111

@@ -189,3 +193,4 @@ License
189193
.. _`PSR-2`: http://www.php-fig.org/psr/psr-2/
190194
.. _`PSR-4`: http://www.php-fig.org/psr/psr-4/
191195
.. _`identical comparison`: https://php.net/manual/en/language.operators.comparison.php
196+
.. _`Yoda conditions`: https://en.wikipedia.org/wiki/Yoda_conditions

Diff for: cookbook/request/load_balancer_reverse_proxy.rst

+18-8
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,14 @@ an AWS Elastic Load Balancer) or a reverse proxy (e.g. Varnish for
77

88
For the most part, this doesn't cause any problems with Symfony. But, when
99
a request passes through a proxy, certain request information is sent using
10-
special ``X-Forwarded-*`` headers. For example, instead of reading the ``REMOTE_ADDR``
11-
header (which will now be the IP address of your reverse proxy), the user's
12-
true IP will be stored in an ``X-Forwarded-For`` header.
10+
either the standard ``Forwarded`` header or non-standard special ``X-Forwarded-*``
11+
headers. For example, instead of reading the ``REMOTE_ADDR`` header (which
12+
will now be the IP address of your reverse proxy), the user's true IP will be
13+
stored in a standard ``Forwarded: for="..."`` header or a non standard
14+
``X-Forwarded-For`` header.
15+
16+
.. versionadded:: 2.7
17+
``Forwarded`` header support was introduced in Symfony 2.7.
1318

1419
If you don't configure Symfony to look for these headers, you'll get incorrect
1520
information about the client's IP address, whether or not the client is connecting
@@ -57,9 +62,9 @@ the IP address ``192.0.0.1`` or matches the range of IP addresses that use
5762
the CIDR notation ``10.0.0.0/8``. For more details, see the
5863
:ref:`framework.trusted_proxies <reference-framework-trusted-proxies>` option.
5964

60-
That's it! Symfony will now look for the correct ``X-Forwarded-*`` headers
61-
to get information like the client's IP address, host, port and whether or
62-
not the request is using HTTPS.
65+
That's it! Symfony will now look for the correct headers to get information
66+
like the client's IP address, host, port and whether the request is
67+
using HTTPS.
6368

6469
But what if the IP of my Reverse Proxy Changes Constantly!
6570
----------------------------------------------------------
@@ -93,9 +98,14 @@ other information.
9398
My Reverse Proxy Uses Non-Standard (not X-Forwarded) Headers
9499
------------------------------------------------------------
95100

96-
Most reverse proxies store information on specific ``X-Forwarded-*`` headers.
97-
But if your reverse proxy uses non-standard header names, you can configure
101+
Although `RFC 7239`_ recently defined a standard ``Forwarded`` header to disclose
102+
all proxy information, most reverse proxies store information in non-standard
103+
``X-Forwarded-*`` headers.
104+
105+
But if your reverse proxy uses other non-standard header names, you can configure
98106
these (see ":doc:`/components/http_foundation/trusting_proxies`").
107+
99108
The code for doing this will need to live in your front controller (e.g. ``web/app.php``).
100109

101110
.. _`security groups`: http://docs.aws.amazon.com/ElasticLoadBalancing/latest/DeveloperGuide/using-elb-security-groups.html
111+
.. _`RFC 7239`: http://tools.ietf.org/html/rfc7239

Diff for: cookbook/security/impersonating_user.rst

+60
Original file line numberDiff line numberDiff line change
@@ -152,3 +152,63 @@ setting:
152152
),
153153
),
154154
));
155+
156+
Events
157+
------
158+
159+
The firewall dispatches the ``security.switch_user`` event right after the impersonation
160+
is completed. The :class:`Symfony\\Component\\Security\\Http\\Event\\SwitchUserEvent` is
161+
passed to the listener, and you can use this to get the user that you are now impersonating.
162+
163+
The cookbook article about
164+
:doc:`Making the Locale "Sticky" during a User's Session </cookbook/session/locale_sticky_session>`
165+
does not update the locale when you impersonate a user. The following code sample will show
166+
how to change the sticky locale:
167+
168+
.. configuration-block::
169+
170+
.. code-block:: yaml
171+
172+
# app/config/services.yml
173+
services:
174+
app.switch_user_listener:
175+
class: AppBundle\EventListener\SwitchUserListener
176+
tags:
177+
- { name: kernel.event_listener, event: security.switch_user, method: onSwitchUser }
178+
179+
.. code-block:: xml
180+
181+
<!-- app/config/services.xml -->
182+
<service id="app.switch_user_listener" class="AppBundle\EventListener\SwitchUserListener">
183+
<tag name="kernel.event_listener" event="security.switch_user" method="onSwitchUser" />
184+
</service>
185+
186+
.. code-block:: php
187+
188+
// app/config/services.php
189+
$container
190+
->register('app.switch_user_listener', 'AppBundle\EventListener\SwitchUserListener')
191+
->addTag('kernel.event_listener', array('event' => 'security.switch_user', 'method' => 'onSwitchUser'))
192+
;
193+
194+
.. caution::
195+
196+
The listener implementation assumes your ``User`` entity has a ``getLocale()`` method.
197+
198+
.. code-block:: php
199+
200+
// src/AppBundle/EventListener/SwitchUserListener.pnp
201+
namespace AppBundle\EventListener;
202+
203+
use Symfony\Component\Security\Http\Event\SwitchUserEvent;
204+
205+
class SwitchUserListener
206+
{
207+
public function onSwitchUser(SwitchUserEvent $event)
208+
{
209+
$event->getRequest()->getSession()->set(
210+
'_locale',
211+
$event->getTargetUser()->getLocale()
212+
);
213+
}
214+
}

0 commit comments

Comments
 (0)