From 233d9b027692cad87c970eb660958855daeb8043 Mon Sep 17 00:00:00 2001 From: Claudio Zizza <859964+SenseException@users.noreply.github.com> Date: Mon, 28 Jun 2021 23:23:40 +0200 Subject: [PATCH] Update session examples in docs (#8795) The session examples contained approaches that aren't favorable for an application and needed an overhaul using either scalar values or an DTO instead of the whole entity with detach() and merge(). --- docs/en/cookbook/entities-in-session.rst | 77 ++++++++++++++++-------- 1 file changed, 51 insertions(+), 26 deletions(-) diff --git a/docs/en/cookbook/entities-in-session.rst b/docs/en/cookbook/entities-in-session.rst index b9d9c6656df..25c9779a26a 100644 --- a/docs/en/cookbook/entities-in-session.rst +++ b/docs/en/cookbook/entities-in-session.rst @@ -3,42 +3,69 @@ Entities in the Session There are several use-cases to save entities in the session, for example: -1. User object +1. User data 2. Multi-step forms To achieve this with Doctrine you have to pay attention to some details to get this working. -Merging entity into an EntityManager ------------------------------------- +Updating an entity +------------------ In Doctrine an entity objects has to be "managed" by an EntityManager to be -updateable. Entities saved into the session are not managed in the next request -anymore. This means that you have to register these entities with an -EntityManager again if you want to change them or use them as part of -references between other entities. You can achieve this by calling -``EntityManager#merge()``. +updatable. Entities saved into the session are not managed in the next request +anymore. This means that you have to update the entities with the stored session +data after you fetch the entities from the EntityManager again. -For a representative User object the code to get turn an instance from -the session into a managed Doctrine object looks like this: +For a representative User object the code to get data from the session into a +managed Doctrine object can look like these examples: + +Working with scalars +~~~~~~~~~~~~~~~~~~~~ + +In simpler applications there is no need to work with objects in sessions and you can use +separate session elements. .. code-block:: php merge($user); + if (isset($_SESSION['userId']) && is_int($_SESSION['userId'])) { + $userId = $_SESSION['userId']; + + $em = GetEntityManager(); // creates an EntityManager + $user = $em->find(User::class, $userId); + + $user->setValue($_SESSION['storedValue']); + + $em->flush(); } -.. note:: +Working with custom data transfer objects +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If objects are needed, we discourage the storage of entity objects in the session. It's +preferable to use a `DTO (data transfer object) `_ +instead and merge the DTO data later with the entity. + +.. code-block:: php + + find(User::class, $userDto->getId()); + + $userEntity->populateFromDto($userDto); + + $em->flush(); + } Serializing entity into the session ----------------------------------- @@ -47,22 +74,20 @@ Entities that are serialized into the session normally contain references to other entities as well. Think of the user entity has a reference to their articles, groups, photos or many other different entities. If you serialize this object into the session then you don't want to serialize the related -entities as well. This is why you should call ``EntityManager#detach()`` on this -object or implement the __sleep() magic method on your entity. +entities as well. This is why you shouldn't serialize an entity and use +only the needed values of it. This can happen with the help of a DTO. .. code-block:: php find("User", 1); - $em->detach($user); - $_SESSION['user'] = $user; + $userDto = new UserDto($user->getId(), $user->getFirstName(), $user->getLastName()); + // or "UserDto::createFrom($user);", but don't store an entity in a property. Only its values without relations. -.. note:: + $_SESSION['user'] = $userDto; - When you called detach on your objects they get "unmanaged" with that - entity manager. This means you cannot use them as part of write operations - during ``EntityManager#flush()`` anymore in this request.