Slide 1

Slide 1 text

User Group Berlin powered by

Slide 2

Slide 2 text

THE PATTERNS BEHIND DOCTRINE Denis Brumann Draft (that will probably look nothing like the actual talk)

Slide 3

Slide 3 text

DOCTRINE 2 DOCTRINE 3

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

/** @ORM\Entity() */ class Order { /** * @ORM\Id() * @ORM\Column(type="integer") * @ORM\GeneratedValue(strategy="AUTO") */ private $id; /** * @ORM\OneToMany(targetEntity="App\Entity\OrderItem", mappedBy="order") */ private $items; /** * @ORM\Column(type="datetime_immutable") */ private $createdOn; }

Slide 6

Slide 6 text

/** @ORM\Entity() */ class OrderItem { /** * @ORM\Id() * @ORM\Column(type="integer") * @ORM\GeneratedValue(strategy="AUTO") */ private $id; /** * @ORM\ManyToOne(targetEntity="App\Entity\Order", inversedBy="items") * @ORM\JoinColumn(nullable=false) */ private $order; /** @ORM\Column() */ private $name; /** @ORM\Column(length=16) */ private $price; }

Slide 7

Slide 7 text

$item = new OrderItem(); $item->setName('Socks'); $item->setPrice('999'); $manager->persist($item); $manager->flush();

Slide 8

Slide 8 text

No content

Slide 9

Slide 9 text

/** @ORM\Entity() */ class OrderItem { /** * @ORM\Id() * @ORM\Column(type="integer") * @ORM\GeneratedValue(strategy="AUTO") */ private $id; /** * @ORM\ManyToOne(targetEntity="App\Entity\Order", inversedBy="items") * @ORM\JoinColumn(nullable=false) */ private $order; /** @ORM\Column() */ private $name; /** @ORM\Column(length=16) */ private $price; }

Slide 10

Slide 10 text

$item = new OrderItem(); $item->setName('Socks'); $item->setPrice('999'); $manager->persist($item); $order = new Order(); $order->addItem($item); $manager->persist($order); $manager->flush();

Slide 11

Slide 11 text

No content

Slide 12

Slide 12 text

$item = new OrderItem(); $item->setName('Socks'); $item->setPrice('999'); $manager->persist($item); $order = new Order(); $order->addItem($item); $manager->persist($order); $manager->flush();

Slide 13

Slide 13 text

No content

Slide 14

Slide 14 text

Unit Of Work A Unit of Work keeps track of everything you do during a business transaction that can affect the database. When you're done, it figures out everything that needs to be done to alter the database as a result of your work.

Slide 15

Slide 15 text

You usually do not directly interact with a UnitOfWork but with the EntityManager instead. Unit Of Work

Slide 16

Slide 16 text

Unit Of Work What changes to write in what order. Identity Map Change Sets Cascading Operations (Persist, Delete, ...) Associations Commit Order

Slide 17

Slide 17 text

$item = new OrderItem(); $item->setName('Socks'); $item->setPrice('999'); $manager->persist($item); $order = new Order(); $order->addItem($item); $manager->persist($order); $manager->flush();

Slide 18

Slide 18 text

export XDEBUG_CONFIG="idekey=PHPSTORM"; php -d xdebug.remote_enable=1 bin/console …

Slide 19

Slide 19 text

export XDEBUG_CONFIG="idekey=PHPSTORM"; php -d xdebug.remote_enable=1 bin/console …

Slide 20

Slide 20 text

$oid = spl_object_hash($entity) This function returns a unique identifier for the object. This id can be used as a hash key for storing objects, or for identifying an object, as long as the object is not destroyed. Once the object is destroyed, its hash may be reused for other objects.

Slide 21

Slide 21 text

$oid = "00000000600cd8330000000053755686"

Slide 22

Slide 22 text

$item1 = new OrderItem(); $item1->setName('Socks'); $item1->setPrice('999'); $item2 = new OrderItem(); $item2->setName('Socks'); $item2->setPrice('999'); $manager->persist($item1); $manager->persist($item2);

Slide 23

Slide 23 text

$item1 == $item2 ! true $item1 === $item2 ! false

Slide 24

Slide 24 text

Unit Of Work uses object hashes to identify entities, not their id (most of the time)

Slide 25

Slide 25 text

Change Sets Computes all the changes that have been done to entities and collections since the last commit and stores these changes in the $entityChangeSet map temporarily for access by the persisters, until the UoW commit is finished.

Slide 26

Slide 26 text

No content

Slide 27

Slide 27 text

{ "00000000085bc321000000004502eb13": { "createdOn": [ null,
 {
 "date": "2018-12-20 20:49:32.824391",
 "timezone_type": 3,
 "timezone": "Europe\/Berlin"
 }
 ] } }

Slide 28

Slide 28 text

No content

Slide 29

Slide 29 text

No content

Slide 30

Slide 30 text

No content

Slide 31

Slide 31 text

No content

Slide 32

Slide 32 text

Entities will be persisted, when they are part of the Change Set, i.e. we explicitly persisted them, or when they are part of a cascaded association.

Slide 33

Slide 33 text

Doctrine does not save unintentionally persisted associations.

Slide 34

Slide 34 text

/** @ORM\Entity() */ class Order { /** * @ORM\Id() * @ORM\Column(type="integer") * @ORM\GeneratedValue(strategy="AUTO") */ private $id; /** * @ORM\OneToMany(..., cascade={"persist"}) */ private $items; /** * @ORM\Column(type="datetime_immutable") */ private $createdOn; }

Slide 35

Slide 35 text

{ "00000000085bc321000000004502eb13": { "createdOn": [
 null,
 {
 "date": "2018-12-20 20:49:32.824391",
 "timezone_type": 3,
 "timezone": "Europe\/Berlin"
 }
 ] }, "00000000085bc37e000000004502eb13": { "status": [null, 0], "name": [null, "Chewing gums"], "price": [null, "249"], "order": [null, {App\Entity\Order}] } }

Slide 36

Slide 36 text

{ "00000000085bc321000000004502eb13": { "createdOn": [
 null,
 {
 "date": "2018-12-20 20:49:32.824391",
 "timezone_type": 3,
 "timezone": "Europe\/Berlin"
 }
 ] }, "00000000085bc37e000000004502eb13": { "status": [null, 0], "name": [null, "Chewing gums"], "price": [null, "249"], "order": [null, {App\Entity\Order}] } } Order OrderItem

Slide 37

Slide 37 text

Entity States A NEW entity instance has no persistent identity, and is not yet associated with an EntityManager and a UnitOfWork (i.e. those just created with the "new" operator).

Slide 38

Slide 38 text

Entity States /** * An entity is new if it has just been instantiated (i.e. using the "new" operator) * and is not (yet) managed by an EntityManager. */ const STATE_NEW = 2;

Slide 39

Slide 39 text

Entity States A MANAGED entity instance is an instance with a persistent identity that is associated with an EntityManager and whose persistence is thus managed.

Slide 40

Slide 40 text

Entity States /** * An entity is in MANAGED state when its persistence is managed by an EntityManager. */ const STATE_MANAGED = 1;

Slide 41

Slide 41 text

Entity States A DETACHED entity instance is an instance with a persistent identity that is not (or no longer) associated with an EntityManager and a UnitOfWork.

Slide 42

Slide 42 text

Entity States /** * A detached entity is an instance with persistent state and identity that is not * (or no longer) associated with an EntityManager (and a UnitOfWork). */ const STATE_DETACHED = 3;

Slide 43

Slide 43 text

Entity States A REMOVED entity instance is an instance with a persistent identity, associated with an EntityManager, that will be removed from the database upon transaction commit.

Slide 44

Slide 44 text

Entity States /** * A removed entity instance is an instance with a persistent identity, * associated with an EntityManager, whose persistent state will be deleted * on commit. */ const STATE_REMOVED = 4;

Slide 45

Slide 45 text

$item = new OrderItem(); $item->setName('Socks'); $item->setPrice('999'); $manager->persist($item); $order = new Order(); $order->addItem($item); $manager->persist($order); $manager->flush();

Slide 46

Slide 46 text

Managed?

Slide 47

Slide 47 text

No content

Slide 48

Slide 48 text

No content

Slide 49

Slide 49 text

No content

Slide 50

Slide 50 text

$order = new Order(); $order->setId(1); $this->entityManager->flush();

Slide 51

Slide 51 text

No content

Slide 52

Slide 52 text

Only entities managed by the Unit Of Work will be inserted/updated/ deleted during flush

Slide 53

Slide 53 text

COMMIT ORDER

Slide 54

Slide 54 text

No content

Slide 55

Slide 55 text

$item = new OrderItem(); $item->setName('Socks'); $item->setPrice('999'); $manager->persist($item); $order = new Order(); $order->addItem($item); $manager->persist($order); $manager->flush();

Slide 56

Slide 56 text

$item = new OrderItem(); $item->setName('Socks'); $item->setPrice('999'); $manager->persist($item); $order = new Order(); $order->addItem($item); $manager->persist($order); $manager->flush();

Slide 57

Slide 57 text

$item = new OrderItem(); $item->setName('Socks'); $item->setPrice('999'); $manager->persist($item); $order = new Order(); $order->addItem($item); $manager->persist($order); $manager->flush();

Slide 58

Slide 58 text

Doctrine will take care of correctly ordering each commit. You can persist your entities in any order you like.

Slide 59

Slide 59 text

New entities either have to be persisted manually or through cascaded associations. An ID does not mean the entity is managed by Doctrine. Operations can be ordered by domain logic, rather than persistence logic. Doctrine will figure out the correct order for insert (update or delete).

Slide 60

Slide 60 text

Merging Objects Fetching Strategies & Lazy Loading Object Hydration