Slide 1

Slide 1 text

Presentation title here Doctrine internals UnitOfWork

Slide 2

Slide 2 text

Presentation title here About me https://www.facebook.com/yatsenco https://github.com/anyt about me… Andrey Yatsenco ● PHP Developer at Oro Inc. ● 3 years with Symfony ● 6 years with PHP

Slide 3

Slide 3 text

Presentation title here Doctrine Internals. UnitOfWork Introduction ● Doctrine is the bottleneck for many apps ● You know how UnitOfWork is working, you know how doctrine works

Slide 4

Slide 4 text

Presentation title here Doctrine Internals. UnitOfWork UnitOfWork track objects changes and commit them transactionally to the Database. Now you don’t manage object loading from the DataBase. UOW do.

Slide 5

Slide 5 text

Presentation title here Doctrine Internals. UnitOfWork UOW use IdentityMap to track objects changes and to avoid server round trip It simple two level array storage ● First level keys are ClassNames ● Second level keys are object IDs.

Slide 6

Slide 6 text

Presentation title here Doctrine Internals. UnitOfWork Doctrine EntityManager is like all-in-one decorator on ● Repository ● UnitOfWork ● MetadataFactory ● ProxyFactory ● etc.

Slide 7

Slide 7 text

Presentation title here Doctrine Internals. UnitOfWork EntityManager -> EntityRepository ● find ● findOneBy ● findAll ● customFindQueryWithHidration ● etc.

Slide 8

Slide 8 text

Presentation title here Doctrine Internals. UnitOfWork EntityManager->UnitOfWork ● persist ● refresh ● remove ● flush ● etc.

Slide 9

Slide 9 text

Presentation title here Doctrine Internals. UnitOfWork EntityManager->UnitOfWork ● persist ● refresh ● remove ● commit ● etc.

Slide 10

Slide 10 text

Presentation title here Doctrine Internals. UnitOfWork Doctrine flow ● 1) Fetch entities from the database or create new and persist ‘em (Repo|UOW) ● 2) Update some of entities directly or using wrapper like Form (uses PropertyAccess) ● Remove some, if needed (Forms etc.) ● 3) EM->flush() changes (UOW)

Slide 11

Slide 11 text

Presentation title here Doctrine Internals. UnitOfWork 1) Fetching entities from the DB ● One entity: ○ find ○ findOneBy ● Several entities: ○ Lazy/Eager loading ○ Find partial

Slide 12

Slide 12 text

Presentation title here Doctrine Internals. UnitOfWork 1) Persist ● Can be omitted if you fetched entities from doctrine ● Required only for newly created entities

Slide 13

Slide 13 text

Presentation title here Doctrine Internals. UnitOfWork 2) Update Object changes outside Doctrine. ● Direct changes ● Forms (PropertyAccessor) ● etc.

Slide 14

Slide 14 text

Presentation title here Doctrine Internals. UnitOfWork 3) Flush Sync changes with the Database

Slide 15

Slide 15 text

Presentation title here Doctrine Internals. UnitOfWork 3) Flush Flow ● Open DB transaction ● Complute change-sets for update ● Iterate over scheduled inserts, updates, deletes ● Delegate to entity persister SQL generation and execution ● Clear UOW on success ● Close DB transaction

Slide 16

Slide 16 text

Presentation title here Doctrine Internals. UnitOfWork UnitOfWork through Doctrine Events ● fetch ● persist ● remove ● flush

Slide 17

Slide 17 text

Presentation title here Doctrine Internals. UnitOfWork Fetch Repo-> find|refresh|getReference|etc. ● (optional) sync data with DB ● Events::loadClassMetadata ○ If ! Events:onClassMetadataNotFound ● hydrate ● Events:postLoad

Slide 18

Slide 18 text

Presentation title here Doctrine Internals. UnitOfWork Persist ● Events:prePersist ● Entity ID isn’t exist at this time in most cases ● UOW->scheduleForInsert($entity)

Slide 19

Slide 19 text

Presentation title here Doctrine Internals. UnitOfWork Remove ● Events::preRemove ● UOW->scheduleForDelete($entity)

Slide 20

Slide 20 text

Presentation title here Doctrine Internals. UnitOfWork Flush ● UOW->commit(null|object|array $entity)

Slide 21

Slide 21 text

Presentation title here Doctrine Internals. UnitOfWork Flush (1) ● Events::preFlush ○ $em->flush() can be called safely ● compute insert|update|delete changesets ● If !changes ○ Events::onFlush ○ Events::postFlush ○ return

Slide 22

Slide 22 text

Presentation title here Doctrine Internals. UnitOfWork Flush (2) ● Events::onFlush ○ UOW->getScheduledEntityInsertions() ○ UOW->getScheduledEntityUpdates() ○ UOW->getScheduledEntityDeletions() ○ $em->persist() && UOW- >computeChangeSet() ● connection->beginTransaction

Slide 23

Slide 23 text

Presentation title here Doctrine Internals. UnitOfWork Flush (3) ● Inserts ○ Persister->insert($entity) ○ Events::postPersist ■ entity can’t be updated directly anymore ■ UOW->scheduleExtraUpdate($entity, array $changeset)

Slide 24

Slide 24 text

Presentation title here Doctrine Internals. UnitOfWork Flush (4) ● Updates ○ Events::preUpdate ■ Entity can’t be updated directly, update changeset using PreUpdateEventArgs ■ Relations changes not tracked too ○ UOW->recomputeSingleEntityChangeSet($class, $entity) ○ Persister->update($entity) ○ Events::postUpdate ■ Entity can’t be updated directly anymore ■ UOW->scheduleExtraUpdate($entity, array $changeset) ● UOW->executeExtraUpdates()

Slide 25

Slide 25 text

Presentation title here Doctrine Internals. UnitOfWork Flush (5) ● Deletions ○ Persister->delete($entity) ○ Events::postRemove ■ nothing to update here

Slide 26

Slide 26 text

Presentation title here Doctrine Internals. UnitOfWork Flush (6) ● connection->commit() ● Events::postFlush ○ Never call $em->flush() here ● UOW->clear(); ○ Events::onClear ● in case of errors ○ connection->rollback() That’s it.

Slide 27

Slide 27 text

Presentation title here Doctrine Internals. UnitOfWork Let’s talk a little bit about performance and how to speed-up doctrine

Slide 28

Slide 28 text

Presentation title here Doctrine Internals. UnitOfWork How to speed-up doctrine ● Cache ○ Metadata ○ Query ○ result

Slide 29

Slide 29 text

Presentation title here Doctrine Internals. UnitOfWork How to speed-up doctrine ● Control lazy-loading ○ Never eager load ○ Write select queries with joins to needed

Slide 30

Slide 30 text

Presentation title here Doctrine Internals. UnitOfWork How to speed-up doctrine ● Fetch less ○ getReference ○ {partial}

Slide 31

Slide 31 text

Presentation title here Doctrine Internals. UnitOfWork How to speed-up doctrine ● Hydrate less ○ arrays instead of objects when you don’t need them or performance is important

Slide 32

Slide 32 text

Presentation title here Doctrine Internals. UnitOfWork How to speed-up doctrine ● Make flush cheaper ○ Mark entities as readOnly ○ Chang tracking policy to DEFERRED_EXPLICIT or NOTIFY ○ Provide flush arguments (applies objects and arrays)

Slide 33

Slide 33 text

Presentation title here Doctrine Internals. UnitOfWork How to speed-up doctrine ● Optimize queries

Slide 34

Slide 34 text

Presentation title here Doctrine Internals. UnitOfWork Links: docs ● http://www.doctrine-project.org/api/orm/2.0/class-Doctrine.ORM.UnitOfWork.html ● http://doctrine-orm.readthedocs.io/projects/doctrine-orm/ Patterns ● http://martinfowler.com/eaaCatalog/unitOfWork.html ● http://martinfowler.com/eaaCatalog/identityMap.html Sergey Zhuravel presentation about Doctrine Events ● http://www.slideshare.net/sergeyz/oro-meetups-doctrine-events?qid=7d9177e9-c41c-4642- bdba-e1fa3060bb17&v=&b=&from_search=1

Slide 35

Slide 35 text

Presentation title here ?