Skip to content

Commit

Permalink
Merge branch '2.8'
Browse files Browse the repository at this point in the history
* 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
  ...
  • Loading branch information
weaverryan committed Jun 28, 2015
2 parents cc87822 + 9cbf3d4 commit 0ef7e1a
Show file tree
Hide file tree
Showing 13 changed files with 1,332 additions and 598 deletions.
539 changes: 13 additions & 526 deletions book/propel.rst

Large diffs are not rendered by default.

97 changes: 77 additions & 20 deletions components/serializer.rst
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,12 @@ You can install the component in 2 different ways:
* :doc:`Install it via Composer </components/using_components>` (``symfony/serializer`` on `Packagist`_);
* Use the official Git repository (https://github.com/symfony/Serializer).


.. include:: /components/require_autoload.rst.inc

To use the ``ObjectNormalizer``, the :doc:`PropertyAccess component </components/property_access/index>`
must also be installed.

Usage
-----

Expand All @@ -45,18 +49,18 @@ which Encoders and Normalizer are going to be available::
use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Serializer\Encoder\XmlEncoder;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;

$encoders = array(new XmlEncoder(), new JsonEncoder());
$normalizers = array(new GetSetMethodNormalizer());
$normalizers = array(new ObjectNormalizer());

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

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

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

Deserializing in an Existing Object
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The serializer can also be used to update an existing object::

$person = new Acme\Person();
$person->setName('bar');
$person->setAge(99);
$person->setSportsman(true);

$data = <<<EOF
<person>
<name>foo</name>
<age>69</age>
</person>
EOF;

$serializer->deserialize($data, 'Acme\Person', 'xml', array('object_to_populate' => $person));
// $obj2 = Acme\Person(name: 'foo', age: '99', sportsman: true)

This is a common need when working with an ORM.

.. _component-serializer-attributes-groups:

Attributes Groups
-----------------

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

.. _component-serializer-attributes-groups-annotations:

Then, create your groups definition:

.. configuration-block::
Expand Down Expand Up @@ -285,8 +315,13 @@ You are now able to serialize only attributes in the groups you want::
Ignoring Attributes
-------------------

.. note::

Using attribute groups instead of the :method:`Symfony\\Component\\Serializer\\Normalizer\\AbstractNormalizer::setIgnoredAttributes`
method is considered best practice.

.. versionadded:: 2.3
The :method:`Symfony\\Component\\Serializer\\Normalizer\\GetSetMethodNormalizer::setIgnoredAttributes`
The :method:`Symfony\\Component\\Serializer\\Normalizer\\AbstractNormalizer::setIgnoredAttributes`
method was introduced in Symfony 2.3.

.. versionadded:: 2.7
Expand All @@ -295,14 +330,14 @@ Ignoring Attributes

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

use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;

$normalizer = new GetSetMethodNormalizer();
$normalizer = new ObjectNormalizer();
$normalizer->setIgnoredAttributes(array('age'));
$encoder = new JsonEncoder();

Expand Down Expand Up @@ -359,11 +394,11 @@ including :class:`Symfony\\Component\\Serializer\\Normalizer\\GetSetMethodNormal
and :class:`Symfony\\Component\\Serializer\\Normalizer\\PropertyNormalizer`::

use Symfony\Component\Serializer\Encoder\JsonEncoder
use Symfony\Component\Serializer\Normalizer\PropertyNormalizer;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use Symfony\Component\Serializer\Serializer;

$nameConverter = new OrgPrefixNameConverter();
$normalizer = new PropertyNormalizer(null, $nameConverter);
$normalizer = new ObjectNormalizer(null, $nameConverter);

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

Expand Down Expand Up @@ -394,9 +429,9 @@ snake_case and CamelCased styles during serialization and deserialization
processes::

use Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter;
use Symfony\Component\Serializer\Normalizer\GetSetMethodNormalizer;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;

$normalizer = new GetSetMethodNormalizer(null, new CamelCaseToSnakeCaseNameConverter());
$normalizer = new ObjectNormalizer(null, new CamelCaseToSnakeCaseNameConverter());

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

The ``ObjectNormalizer`` also takes care of methods starting with ``has``, ``add``
and ``remove``.

Using Callbacks to Serialize Properties with Object Instances
-------------------------------------------------------------

Expand Down Expand Up @@ -463,23 +501,42 @@ Normalizers

There are several types of normalizers available:

:class:`Symfony\\Component\\Serializer\\Normalizer\\ObjectNormalizer`
This normalizer leverages the :doc:`PropertyAccess Component </components/property_access/index>`
to read and write in the object. It means that it can access to properties
directly and through getters, setters, hassers, adders and removers. It supports
calling the constructor during the denormalization process.

Objects are normalized to a map of property names (method name stripped of
the "get"/"set"/"has"/"remove" prefix and converted to lower case) to property
values.

The ``ObjectNormalizer`` is the most powerful normalizer. It is a configured
by default when using the Symfony Standard Edition with the serializer enabled.

:class:`Symfony\\Component\\Serializer\\Normalizer\\GetSetMethodNormalizer`
This normalizer reads the content of the class by calling the "getters"
(public methods starting with "get"). It will denormalize data by calling
the constructor and the "setters" (public methods starting with "set").

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

:class:`Symfony\\Component\\Serializer\\Normalizer\\PropertyNormalizer`
This normalizer directly reads and writes public properties as well as
**private and protected** properties. Objects are normalized to a map of
property names to property values.
**private and protected** properties. It supports calling the constructor
during the denormalization process.

Objects are normalized to a map of property names to property values.

.. versionadded:: 2.6 The
:class:`Symfony\\Component\\Serializer\\Normalizer\\PropertyNormalizer`
.. versionadded:: 2.6
The :class:`Symfony\\Component\\Serializer\\Normalizer\\PropertyNormalizer`
class was introduced in Symfony 2.6.

.. versionadded:: 2.7
The :class:`Symfony\\Component\\Serializer\\Normalizer\\ObjectNormalizer`
class was introduced in Symfony 2.7.

Handling Circular References
----------------------------

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

$encoder = new JsonEncoder();
$normalizer = new GetSetMethodNormalizer();
$normalizer = new ObjectNormalizer();

$normalizer->setCircularReferenceHandler(function ($object) {
return $object->getName();
Expand Down
5 changes: 5 additions & 0 deletions contributing/code/standards.rst
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,10 @@ Structure

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

* Use `Yoda conditions`_ when checking a variable against an expression to avoid
an accidental assignment inside the condition statement (this applies to ``==``,
``!=``, ``===``, and ``!==``);

* Add a comma after each array item in a multi-line array, even after the
last one;

Expand Down Expand Up @@ -189,3 +193,4 @@ License
.. _`PSR-2`: http://www.php-fig.org/psr/psr-2/
.. _`PSR-4`: http://www.php-fig.org/psr/psr-4/
.. _`identical comparison`: https://php.net/manual/en/language.operators.comparison.php
.. _`Yoda conditions`: https://en.wikipedia.org/wiki/Yoda_conditions
26 changes: 18 additions & 8 deletions cookbook/request/load_balancer_reverse_proxy.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,14 @@ an AWS Elastic Load Balancer) or a reverse proxy (e.g. Varnish for

For the most part, this doesn't cause any problems with Symfony. But, when
a request passes through a proxy, certain request information is sent using
special ``X-Forwarded-*`` headers. For example, instead of reading the ``REMOTE_ADDR``
header (which will now be the IP address of your reverse proxy), the user's
true IP will be stored in an ``X-Forwarded-For`` header.
either the standard ``Forwarded`` header or non-standard special ``X-Forwarded-*``
headers. For example, instead of reading the ``REMOTE_ADDR`` header (which
will now be the IP address of your reverse proxy), the user's true IP will be
stored in a standard ``Forwarded: for="..."`` header or a non standard
``X-Forwarded-For`` header.

.. versionadded:: 2.7
``Forwarded`` header support was introduced in Symfony 2.7.

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

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

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

Most reverse proxies store information on specific ``X-Forwarded-*`` headers.
But if your reverse proxy uses non-standard header names, you can configure
Although `RFC 7239`_ recently defined a standard ``Forwarded`` header to disclose
all proxy information, most reverse proxies store information in non-standard
``X-Forwarded-*`` headers.

But if your reverse proxy uses other non-standard header names, you can configure
these (see ":doc:`/components/http_foundation/trusting_proxies`").

The code for doing this will need to live in your front controller (e.g. ``web/app.php``).

.. _`security groups`: http://docs.aws.amazon.com/ElasticLoadBalancing/latest/DeveloperGuide/using-elb-security-groups.html
.. _`RFC 7239`: http://tools.ietf.org/html/rfc7239
60 changes: 60 additions & 0 deletions cookbook/security/impersonating_user.rst
Original file line number Diff line number Diff line change
Expand Up @@ -152,3 +152,63 @@ setting:
),
),
));
Events
------

The firewall dispatches the ``security.switch_user`` event right after the impersonation
is completed. The :class:`Symfony\\Component\\Security\\Http\\Event\\SwitchUserEvent` is
passed to the listener, and you can use this to get the user that you are now impersonating.

The cookbook article about
:doc:`Making the Locale "Sticky" during a User's Session </cookbook/session/locale_sticky_session>`
does not update the locale when you impersonate a user. The following code sample will show
how to change the sticky locale:

.. configuration-block::

.. code-block:: yaml
# app/config/services.yml
services:
app.switch_user_listener:
class: AppBundle\EventListener\SwitchUserListener
tags:
- { name: kernel.event_listener, event: security.switch_user, method: onSwitchUser }
.. code-block:: xml
<!-- app/config/services.xml -->
<service id="app.switch_user_listener" class="AppBundle\EventListener\SwitchUserListener">
<tag name="kernel.event_listener" event="security.switch_user" method="onSwitchUser" />
</service>
.. code-block:: php
// app/config/services.php
$container
->register('app.switch_user_listener', 'AppBundle\EventListener\SwitchUserListener')
->addTag('kernel.event_listener', array('event' => 'security.switch_user', 'method' => 'onSwitchUser'))
;
.. caution::

The listener implementation assumes your ``User`` entity has a ``getLocale()`` method.

.. code-block:: php
// src/AppBundle/EventListener/SwitchUserListener.pnp
namespace AppBundle\EventListener;
use Symfony\Component\Security\Http\Event\SwitchUserEvent;
class SwitchUserListener
{
public function onSwitchUser(SwitchUserEvent $event)
{
$event->getRequest()->getSession()->set(
'_locale',
$event->getTargetUser()->getLocale()
);
}
}
Loading

0 comments on commit 0ef7e1a

Please sign in to comment.