Upgrade to Pro — share decks privately, control downloads, hide ads and more …

What to expect when Doctrine 3 comes out

What to expect when Doctrine 3 comes out

Doctrine ORM is probably the most used database abstraction in PHP. With Doctrine 3 on the horizon it's a perfect time to look at how Doctrine has changed and will change and what this means for you as users. This talk looks at some of the already merged features for Doctrine 3 that could have an impact on your code and why the might prevent you from upgrading. I will show approaches for tackling these changes and how your projects might benefit from introducing them already.

Denis Brumann

September 13, 2019
Tweet

More Decks by Denis Brumann

Other Decks in Programming

Transcript

  1. WHAT I WILL COVER… WHAT HAS CHANGED? HOW HAS IT

    CHANGED? HOW TO ADAPT FOR THE CHANGE? @dbrumann / [email protected] 5
  2. ROADMAP MAPPING UUID GENERATOR NAMED QUERIES NAMESPACE ALIASES PROXY OBJECTS

    CLASS METADATA ENTITY MANAGER SECOND LEVEL CACHE @dbrumann / [email protected] 10
  3. YAML-MAPPING IS DEPRECATED IN 2.6 WILL BE REMOVED IN DOCTRINE

    3 SYMFONY BEST PRACTICES: ANNOTATIONS @dbrumann / [email protected] 15
  4. /** @ORM\Entity */ class Customer { /** * @ORM\Id *

    @ORM\Column(type="guid") * @ORM\GeneratedValue(strategy="UUID") */ private $id; … @dbrumann / [email protected] 19
  5. /** @ORM\Entity */ class Customer { /** * @ORM\Id *

    @ORM\Column(type="uuid") * @ORM\GeneratedValue(strategy="NONE") */ private $id; public function __construct() { $this->id = Uuid::uuid4(); } public function getId(): string { return (string) $this->id; } @dbrumann / [email protected] 21
  6. 24

  7. 25

  8. class AddressController extends AbstractController { public function index(EntityManagerInterface $entityManager): Response

    { $repository = $entityManager->getRepository(Address::class); $addresses = $repository->createNativeNamedQuery('findAll') ->getResult(); return $this->render('addresses/index.html.twig', [ 'addresses' => $addresses, ]); } } @dbrumann / [email protected] 26
  9. WORKS FOR NOW WILL BE REMOVED IN DOCTRINE 3 MOVE

    LOGIC (E.G. TO REPOSITORY) NAMED QUERIES @dbrumann / [email protected] 29
  10. POPULAR IN SYMFONY APPS < 3.x WILL BE REMOVED IN

    DOCTRINE 3! USE FULLY QUALIFIED CLASS NAME ::CLASS NAMESPACE ALIASES @dbrumann / [email protected] 34
  11. /** @ORM\Entity(…) */ class Customer { … /** * @ORM\OneToMany(targetEntity="App\Entity\Address",

    mappedBy="customer") */ private $addresses; … public function getAddresses() { return this->addresses; } } @dbrumann / [email protected] 36
  12. A proxy object is an object that is put in

    place or used instead of the "real" object. A proxy object can add behavior to the object being proxied without that object being aware of it. In Doctrine 2, proxy objects are used to realize several features but mainly for transparent lazy-loading. https://www.doctrine-project.org/projects/doctrine-orm/en/2.6/reference/advanced-configuration.html#proxy-objects PROXY OBJECTS @dbrumann / [email protected] 41
  13. <?php namespace Proxies\__CG__\App\Entity; /** * DO NOT EDIT THIS FILE

    - IT WAS CREATED BY DOCTRINE'S PROXY GENERATOR */ class Order extends \App\Entity\Order implements \Doctrine\ORM\Proxy\Proxy { /** * @var \Closure the callback responsible for loading properties in the proxy object. This callback is called with * three parameters, being respectively the proxy object to be initialized, the method that triggered the * initialization process and an array of ordered parameters that were passed to that method. * * @see \Doctrine\Common\Persistence\Proxy::__setInitializer */ public $__initializer__; /** * @var \Closure the callback responsible of loading properties that need to be copied in the cloned object * * @see \Doctrine\Common\Persistence\Proxy::__setCloner */ public $__cloner__; /** * @var boolean flag indicating if this object was already initialized * * @see \Doctrine\Common\Persistence\Proxy::__isInitialized */ public $__isInitialized__ = false; /** * @var array properties to be lazy loaded, with keys being the property * names and values being their default values * * @see \Doctrine\Common\Persistence\Proxy::__getLazyProperties */ 43
  14. /** * * @return array */ public function __sleep() {

    if ($this->__isInitialized__) { return ['__isInitialized__', '' . "\0" . 'App\\Entity\\Order' . "\0" . 'id', '' . "\0" . 'App\\Entity\\Order' . "\0" . 'items', '' . "\0" . 'App\\Entity\\Order' . "\0" . 'createdOn']; } return ['__isInitialized__', '' . "\0" . 'App\\Entity\\Order' . "\0" . 'id', '' . "\0" . 'App\\Entity\\Order' . "\0" . 'items', '' . "\0" . 'App\\Entity\\Order' . "\0" . 'createdOn']; } /** * */ public function __wakeup() { if ( ! $this->__isInitialized__) { $this->__initializer__ = function (Order $proxy) { $proxy->__setInitializer(null); $proxy->__setCloner(null); $existingProperties = get_object_vars($proxy); foreach ($proxy->__getLazyProperties() as $property => $defaultValue) { if ( ! array_key_exists($property, $existingProperties)) { $proxy->$property = $defaultValue; } } }; } } /** * */ 44
  15. final METHODS ARE NOW ALLOWED __clone NO LONGER CALLED BY

    ORM __wakeup NO LONGER CALLED BY ORM serialize() ⚠ RECURSIVE INITIALIZATION ACCESSING PRIVATE STATE WITH REFLECTION TRIGGERS LAZY-LOADING LAZY LOADING @dbrumann / [email protected] 47
  16. Quoting is now always called. Implement your own Doctrine\ORM\Mapping\NamingStrategy to

    manipulate your schema, tables and column names to your custom desired naming convention. @dbrumann / [email protected] 50
  17. The Second Level Cache is designed to reduce the amount

    of necessary database access. It sits between your application and the database to avoid the number of database hits as much as possible. SECOND LEVEL CACHE @dbrumann / [email protected] 63
  18. The second level cache functionality is marked as experimental for

    now. It is a very complex feature and we cannot guarantee yet that it works stable in all cases. SECOND LEVEL CACHE @dbrumann / [email protected] 64
  19. DATA IS STORED IN DIFFERENT CACHE REGIONS EACH REGION HAS

    SPECIFIC NAMESPACE AND LIFETIME CACHE FOR QUERIES/COLLECTIONS ONLY CONTAINS IDENTIFIERS CACHE REGIONS @dbrumann / [email protected] 67
  20. CACHES ARE NOT AWARE OF CHANGES TO PERSISTENT STORE BY

    OTHER APPLICATIONS PAGINATION COUNT QUERIES ARE NOT CACHED NOT ALL CACHES WORK IN DISTRIBUTED ENVS LIMITATIONS @dbrumann / [email protected] 69
  21. RECAP MAPPING UUID GENERATOR NAMED QUERIES NAMESPACE ALIASES PROXY OBJECTS

    CLASS METADATA ENTITY MANAGER SECOND LEVEL CACHE @dbrumann / [email protected] 73