data data serialization serialization with with symfony
play

Data Data Serialization Serialization with with Symfony Symfony - PowerPoint PPT Presentation

Data Data Serialization Serialization with with Symfony Symfony & & Drupal Drupal SensioLabs Hugo Hamon Hugo Hamon Head of training at SensioLabs Book author Speaker at Conferences Symfony contributor Travel lover @hhamon


  1. XML XML Deserializa eserialization tion $data = <<<DATA <?xml version="1.0"?> <response> <id/> <title>Seven</title> <slug>seven</slug> <description>A … thriller!</description> <duration>130</duration> <releaseDate>1996-01-31</releaseDate> <storageKey/> </response> DATA; $movie = $serializer->deserialize($data, 'Movie', 'xml'); print_r($movie);

  2. String String Deserializa eserialization tion Movie Object ( [id:Movie:private] => [title:Movie:private] => Seven [slug:Movie:private] => seven [description:Movie:private] => A … thriller! [duration:Movie:private] => 130 [releaseDate:Movie:private] => 1996-01-31 [storageKey:Movie:private] => )

  3. Construc onstructor or Initializa Initialization tion class Movie class Movie { // ... function function __construct($id = null null, $title = null null, $slug = null null) { $this->id = $id; $this->title = $title; $this->slug = $slug; } } Constructor arguments must match properties names. ¡

  4. Going Further with the Serializer

  5. Getter, Hasser & Isser Methods Normalizer

  6. // Setup the normalizers $normalizers normalizers[] = [] = new new Normalizer Normalizer\ObjectNormalizer ObjectNormalizer(); (); $normalizers normalizers[] = [] = new new Normalizer Normalizer\GetSetMethodNormalizer GetSetMethodNormalizer(); (); $normalizers[] = new new Normalizer\PropertyNormalizer(); // Setup the encoders $encoders[] = new new Encoder\JsonEncoder(); $encoders[] = new new Encoder\XmlEncoder(); // Setup the serializer $serializer = new new Serializer($normalizers, $encoders); // Use the serializer $serializer->serialize($object, 'json'); $serializer->deserialize($data, 'Acme\User','json'); The object normalizer can invoke « hasser » methods. ¡

  7. class class Movie Movie { The normalizer invokes public public function function getId() { getter & isser methods. ¡ return return $this->id; } public public function function getTitle() { return return $this->title; } public public function function hasGenre() { return return false; } // ... public public function function isReleased() { return new return new \DateTime DateTime($this->releaseDate) <= new new \DateTime DateTime(); } }

  8. JSON JSON Serializa erialization tion { "id":null, "title":"Seven", "slug":"seven", "description":"A … thriller!", "duration":130, "releaseDate":"1996-01-31", "storageKey":null, "genre" genre":false :false, , " "released released":true true, , }

  9. XML XML Serializa erialization tion <?xml version="1.0"?> <response> <id/> <title>Seven</title> <slug>seven</slug> <description>A … thriller!</description> <duration>130</duration> <releaseDate>1996-01-31</releaseDate> <storageKey/> <genre>0</genre> <genre>0</genre> < <released released>1</ >1</released released> > </response>

  10. Ignoring Attributes

  11. $normalizer = new new GetSetMethodNormalizer(); $normalizer->setIgnoredAttributes([ 'storageKey' ]); <?xml version="1.0"?> <response> <id/> <title>Seven</title> <slug>seven</slug> <description>A … thriller!</description> <duration>130</duration> <releaseDate>1996-01-31</releaseDate> <released>1</released> </response>

  12. Converting properties names to underscore case.

  13. $converter = new new CamelCaseToSnakeCaseNameConverter(); $normalizer = new new GetSetMethodNormalizer(null, $converter); <?xml version="1.0"?> <response> <id/> <title>Seven</title> <slug>seven</slug> <description>A … thriller!</description> <duration>130</duration> <release_date release_date>1996-01-31</ >1996-01-31</release_date release_date> > <released>1</released> </response>

  14. Customizing all serialized properties names.

  15. class class PrefixNameConverter PrefixNameConverter implements implements NameConverterInterface { private private $prefix; public public function function __construct($prefix) { $this->prefix = $prefix; } public public function function normalize($propertyName) { return return $this->prefix.'_'.$propertyName; } public public function function denormalize($propertyName) { if if ($this->prefix.'_' === substr($propertyName, 0, count($this->prefix))) { return return substr($propertyName, count($this->prefix)); } return return $propertyName; } } The NameConverterInterface has been introduced in 2.7. ¡

  16. $converter = new new PrefixNameConverter('movie'); $normalizer = new new GetSetMethodNormalizer(null, $converter); <?xml version="1.0"?> <response> <movie_id/> <movie_title>Seven</movie_title> <movie_slug>seven</movie_slug> <movie_description>A … thriller!</movie_description> <movie_duration>130</movie_duration> <movie_release_date>1996-01-31</movie_release_date> <movie_released>1</movie_released> </response>

  17. Changing the XML root name.

  18. $serializer->serialize($movie, 'xml', [ 'xml_root_node_name' => 'movie', ]); <?xml version="1.0"?> <movie> <id/> <title>Seven</title> ... </movie>

  19. Deserializing into an existing object.

  20. $data = <<<DATA <?xml version="1.0"?> <movie> <duration>130</duration> <releaseDate>1996-01-31</releaseDate> </movie> DATA; $movie1 = new new Movie(1234, 'Seven', 'seven'); $movie2 = $serializer->deserialize($data, 'Movie', 'xml', [ 'xml_root_node_name' => 'movie', 'object_to_populate' => $movie1, ]);

  21. Movie Object ( [id:Movie:private id:Movie:private] => 1234 ] => 1234 [ [title:Movie:private title:Movie:private] => ] => Seven Seven [ [slug:Movie:private slug:Movie:private] => ] => seven seven [description:Movie:private] => [duration:Movie:private duration:Movie:private] => 130 ] => 130 [ [releaseDate:Movie:private releaseDate:Movie:private] => 1996-01-31 ] => 1996-01-31 [storageKey:Movie:private] => [genre:Movie:private] => ) The « description » property remains empty while « duration » and « releaseDate » properties are set. ¡

  22. Serializer Advanced Features

  23. Serializing More Complex Object Graphs.

  24. class class Movie Movie { /** @var Genre */ private private $genre; /** @var Directors[] */ private private $directors; /** * Each role keeps a reference to that Movie object * and a reference to an Actor object playing that * role in the movie. * * @var Role[] */ private private $roles; }

  25. One to One Unidirectional Relationship

  26. $genre = new new Genre(42, 'Thriller', 'thriller'); $movie = new new Movie(1234, 'Seven', 'seven'); $movie->setGenre($genre); $movie->setStorageKey('movie-42-1234'); $movie->setDuration(130); $movie->setDescription('A brilliant thriller!'); $movie->setReleaseDate('1996-01-31'); echo echo $serializer->serialize($movie, 'xml', [ 'xml_root_node_name' => 'movie', ]);

  27. <?xml version="1.0"?> <movie movie> > <genre> <genre> <id> <id>42</id> </id> <slug> <slug>thriller</slug> </slug> <title < title>Thriller</ </title title> > </genre> </genre> <id> <id>1234</id> </id> < <title title>Seven</ </title title> > <duration> <duration>130</duration> </duration> < <released released>1</ </released released> > <slug> <slug>seven</slug> </slug> <description> <description>A brilliant thriller!</description> </description> < <release_date release_date>1996-01-31</ </release_date release_date> > </ </movie movie>

  28. { "genre":{ "id":42, "slug":"thriller", "title":"Thriller" }, "id":1234, "title":"Seven", "duration":130, "released":true, "slug":"seven", "description":"A brilliant thriller!", "release_date":"1996-01-31" }

  29. One to Many Unidirectional Relationship

  30. $fincher = new new Director(); $fincher->setId(973463); $fincher->setName('David Fincher'); $fincher->setBirthday('1962-05-10'); $kopelson = new new Director(); $kopelson->setId(783237); $kopelson->setName('Arnold Kopelson'); $kopelson->setBirthday('1935-02-14'); $movie = new new Movie(1234, 'Seven', 'seven'); $movie->addDirector($fincher); $movie->addDirector($kopelson);

  31. <?xml version="1.0"?> <movie movie> > <!-- ... --> <!-- ... --> < <directors directors> > <id> <id>973463</id> </id> < <name name>David Fincher</ </name name> > < <birthday birthday>1962-05-10</ </birthday birthday> > < <deathday deathday/> /> </ </directors directors> > < <directors directors> > <id> <id>783237</id> </id> < <name name>Arnold Kopelson</ </name name> > <birthday < birthday>1935-02-14</ </birthday birthday> > < <deathday deathday/> /> </ </directors directors> > </ </movie movie>

  32. { "genre":{ "id":42, "slug":"thriller", "title":"Thriller" }, "id":1234, "title":"Seven", "duration":130, "released":true, "slug":"seven", "description":"A brilliant thriller!", "release_date":"1996-01-31", "directors":[ { "id":973463, "name":"David Fincher", "birthday":"1962-05-10", "deathday":null }, { "id":783237, "name":"Arnold Kopelson", "birthday":"1935-02-14", "deathday":null } ] }

  33. Many to Many Bidirectional Relationship

  34. class class Role Role { private private $id; private private $character; private private $movie; private private $actor; function function __construct($id, Movie $movie, Actor $actor, $character) { $this->id = $id; $this->movie = $movie; $this->actor = $actor; $this->character = $character; } } The « Role » instance keeps a reference to the « Movie » that also keeps references to « roles » played by actors. ¡

  35. $movie = new new Movie(1234, 'Seven', 'seven'); // ... $pitt = new new Actor(); $pitt->setId(328470); $pitt->setName('Brad Pitt'); $pitt->setBirthday('1963-12-18'); $freeman = new new Actor(); $freeman->setId(329443); $freeman->setName('Morgan Freeman'); $freeman->setBirthday('1937-06-01'); $mills = new new Role(233, $movie, $pitt, 'David Mills'); $sommerset = new new Role(328, $movie, $freeman, 'William Sommerset'); $movie->addRole($mills); $movie->addRole($sommerset); $serializer->serialize($movie, 'json');

  36. PHP Fatal PHP Fatal error error: Uncaught exception 'Symfony\Component\Serializer \Exception \CircularReferenceException' with message 'A circular reference has been detected (configured limit: 1).' in /Volumes/Development/Sites/ Serializer/vendor/symfony/serializer/ Normalizer/AbstractNormalizer.php:221

  37. Handling Circular References

  38. Handling Handling Cir Circular ular Ref Refer erenc ences es $normalizer = new new ObjectNormalizer(null null, $converter); $normalizer->setIgnoredAttributes([ 'storageKey' ]); // Return the object unique identifier instead of the // instance to stop a potential infinite serialization loop. $normalizer->setCircularReferenceHandler(function function ($object) { return return $object->getId(); }); Circular references support has been introduced in Symfony 2.6. ¡

  39. { ... "roles":[ { "actor":{ "id":328470, "name":"Brad Pitt", "birthday":"1963-12-18", "deathday":null }, "character":"David Mills", "id":233163, "movie":1234 "movie":1234 }, ... ] }

  40. Using Callback Normalizers.

  41. Actors, Directors and Movies now stores date representations as « DateTime » objects. These instance must be serialized too. ¡ $movie = new new Movie(1234, 'Seven', 'seven'); $movie->setReleaseDate(new \DateTime('1996-01-31')); $pitt = new new Actor(); $pitt->setBirthday(new \DateTime('1963-12-18')); $fincher = new new Director(); $fincher->setBirthday(new \DateTime('1962-05-10')); $serializer->serialize($movie, 'json');

  42. Without custom serializer to handle « DateTime » instance, the Serializer serializes any date object as follows: ¡ <release_date release_date> > <last_errors < last_errors> > < <warning_count warning_count>0</ </warning_count warning_count> > <warnings/> <warnings/> < <error_count error_count>0</ </error_count error_count> > <errors < errors/> /> </last_errors </ last_errors> > < <timezone timezone> > < <name name>Europe/Paris</ </name name> > <location> <location> <country_code < country_code>FR</ </country_code country_code> > <latitude> <latitude>48.86666</latitude> </latitude> <longitude> <longitude>2.33333</longitude> </longitude> < <comments comments></ ></comments comments> > </location> </location> </ </timezone timezone> > <offset> <offset>3600</offset> </offset> < <timestamp timestamp>823042800</ </timestamp timestamp> > </ </release_date release_date>

  43. The built-in normalizers allow to set PHP callbacks to handle custom serialization steps. ¡ $normalizer = new new Normalizer\ObjectNormalizer(... ...); $callback = function function ($dateTime) { return return $dateTime instanceof \DateTime ? $dateTime->format(\DateTime::ISO8601) : ''; }; $normalizer->setCallbacks([ 'releaseDate' => $callback, 'birthday' => $callback, 'deathday' => $callback, ]);

  44. <?xml version="1.0"?> <movie movie> > <!-- ... --> <!-- ... --> <release_date < release_date>1996-01-31T00:00:00+0100</ </release_date release_date> > < <directors directors> > <id> <id>973463</id> </id> < <name name>David Fincher</ </name name> > < <birthday birthday>1962-05-10T00:00:00+0100</ </birthday birthday> > < <deathday deathday/> /> </ </directors directors> > < <directors directors> > <id> <id>783237</id> </id> < <name name>Arnold Kopelson</ </name name> > < <birthday birthday>1935-02-14T00:00:00+0000</ </birthday birthday> > < <deathday deathday/> /> </ </directors directors> > </ </movie movie>

  45. { "genre":{ "id":42, "slug":"thriller", "title":"Thriller" }, "id":1234, "title":"Seven", "duration":130, "released":true, "slug":"seven", "description":"A brilliant thriller!", "release_date":"1996-01-31T00:00:00+0000", "release_date":"1996-01-31T00:00:00+0000", "directors":[ { "id":973463, "name":"David Fincher", "birthday":"1962-05-10T00:00:00+0000", "birthday":"1962-05-10T00:00:00+0000", "deathday":null }, { "id":783237, "name":"Arnold Kopelson", "birthday":"1935-02-14T00:00:00+0000", "birthday":"1935-02-14T00:00:00+0000", "deathday":null } ] }

  46. Using the Custom Normalizer.

  47. Adding dding the C the Cust ustom om Normaliz ormalizer er The built-in « Custom » normalizer is responsible for automatically calling the « normalize() » and « denormalize() » methods of your objects if they implement the corresponding interface. ¡ $normalizers[] = new new Normalizer\CustomNormalizer();

  48. use use Symfony\Component\Serializer\Normalizer\NormalizableInterface; use use Symfony\Component\Serializer\Normalizer\NormalizerInterface; class class Role Role implements implements NormalizableInterface { private private $id; private private $character; private private $movie; private private $actor; function function normalize(NormalizerInterface $normalizer, $format = null null, array array $context = []) { return return [ 'id' => $this->id, 'character' => $this->character, 'actor' => $this->actor, ]; } }

  49. Serialization Groups

  50. Annota Annotation C tion Configura onfiguration tion use use Symfony\Component\Serializer\Annotation\Groups; class Movie class Movie { /** @Groups({"admins"}) */ private private $id; /** @Groups({"admins", "publishers", "users" }) */ private private $title; /** @Groups({"admins", "publishers" }) */ private private $slug; /** @Groups({"admins", "publishers", "users" }) */ private private $releaseDate; /** @Groups({ "admins", "publishers", "users" }) */ public public function function isReleased() { return return new new $this->releaseDate <= new new \DateTime(); } }

  51. YAML C ML Configura onfiguration tion Movie: attributes: id: groups: [ admins ] title: groups: [ admins, publishers, users ] slug: groups: [ admins, publishers ] releaseDate: groups: [ admins, publishers, users ] released: groups: [ admins, publishers, users ]

  52. XML C XML Configura onfiguration tion <?xml version="1.0" ?> <serializer serializer ...> <class <class name="Movie"> <attribute <attribute name="id"> <group> <group>admins</group> </group> </ </attribute attribute> <attribute attribute name="title"> <group> <group>admins</group> </group> <group> <group>publishers</group> </group> <group> <group>users</group> </group> </ </attribute attribute> <attribute attribute name="slug"> <group> <group>admins</group> </group> <group> <group>publishers</group> </group> </ </attribute attribute> </class> </class> </ </serializer serializer>

  53. Load oad Gr Groups oups Metada Metadata ta use Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader; use use Symfony\Component\Serializer\Mapping\Loader\XmlFileLoader; use use use Symfony\Component\Serializer\Mapping\Loader\YamlFileLoader; use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory; use use use Doctrine\Common\Annotations\AnnotationReader; use use Doctrine\Common\Cache\ArrayCache; // Setup a loader $loader = new new AnnotationLoader(new new AnnotationReader()); $loader = new new YamlFileLoader(__DIR__.'/config/serializer.yml'); $loader = new new XmlFileLoader(__DIR__.'/config/serializer.xml'); $cache = new new ArrayCache(); // Setup the normalizers $factory = new new ClassMetadataFactory($loader, $cache); $normalizer = new new Normalizer\ObjectNormalizer($factory, $converter); // ...

  54. Serializa erialization tion Gr Groups oups $serializer->serialize($movie, 'xml', [ 'xml_root_node_name' => 'movie', 'groups' => [ 'users' ], ]); $serializer->deserialize($movie, 'Movie', 'xml', [ 'xml_root_node_name' => 'movie', 'groups' => [ 'users' ], ]);

  55. Serializer Integration into Drupal 8

  56. The « Serialization » Core module integrates the Symfony Serializer into Drupal. »

  57. core core/modules/ /modules/serialization serialization/ / ├── serialization.info.yml ├── serialization.module ├── serialization.services.yml serialization.services.yml ├── src/ │ ├── Encoder/ Encoder/ │ ├── EntityResolver EntityResolver/ / │ ├── Normalizer Normalizer/ / │ ├── RegisterEntityResolversCompilerPass.php │ ├── RegisterSerializationClassesCompilerPass.php │ ├── SerializationServiceProvider.php │ └── Tests/ └── tests/ ├── modules/ ├── serialization_test/ └── src/

  58. Built Built-in -in Normaliz ormalizers ers core/modules/serialization/src/Normalizer/ ├─ ComplexDataNormalizer.php (default) (default) ├─ ConfigEntityNormalizer.php ├─ ContentEntityNormalizer.php ├─ EntityNormalizer.php ├─ ListNormalizer.php ├─ NormalizerBase.php ├─ NullNormalizer.php └─ TypedDataNormalizer.php

Download Presentation
Download Policy: The content available on the website is offered to you 'AS IS' for your personal information and use only. It cannot be commercialized, licensed, or distributed on other websites without prior consent from the author. To download a presentation, simply click this link. If you encounter any difficulties during the download process, it's possible that the publisher has removed the file from their server.

Recommend


More recommend