Slide 1

Slide 1 text

DOCTRINE 2 & ZF2 +

Slide 2

Slide 2 text

Doctrine core team Zf2 contributor Modules developer time waster - MARCO PIVETTA @Ocramius Ocramius

Slide 3

Slide 3 text

MAIN LIBRARIES , , , , , , , , , , BjyAuthorize AssetManager ZeffMu ZfrRest OcraDiCompiler OcraServiceManager OcraCachedViewResolver DoctrineModule DoctrineORMModule DoctrineMongoODMModule VersionEyeModule

Slide 4

Slide 4 text

DOCTRINE PROJECT An incubator for persistence-oriented libraries

Slide 5

Slide 5 text

WHAT IS DOCTRINE ORM? Doctrine ORM is an Object Relational Mapper It is inspired by Hibernate and the JPA (JSR-317) It is based on a DBAL (DataBase Abstraction Layer) Allows developers to save and load POPO with SQL

Slide 6

Slide 6 text

An ORM gives you the impression that you are working with a "virtual" database (graph) composed by objects

Slide 7

Slide 7 text

Simply put: FORGET THE DATABASE!

Slide 8

Slide 8 text

THE MODULES! DoctrineModule basic common functionality DoctrineORMModule ORM/SQL Connection DoctrineMongoODMModule ODM/MongoDB Connection

Slide 9

Slide 9 text

No content

Slide 10

Slide 10 text

INSTALLATION!

Slide 11

Slide 11 text

p h p c o m p o s e r . p h a r r e q u i r e d o c t r i n e / d o c t r i n e - o r m - m o d u l e : 0 . 7 . *

Slide 12

Slide 12 text

No content

Slide 13

Slide 13 text

No content

Slide 14

Slide 14 text

p h p c o m p o s e r . p h a r r e q u i r e z e n d f r a m e w o r k / z e n d - d e v e l o p e r - t o o l s : d e v - m a s t e r

Slide 15

Slide 15 text

No content

Slide 16

Slide 16 text

No content

Slide 17

Slide 17 text

c p v e n d o r / z e n d f r a m e w o r k / z e n d - d e v e l o p e r - t o o l s / c o n f i g / z e n d d e v e l o p e r t o o l s . l o c a l . p h p . d i s t c o n f i g / a u t o l o a d / z d t . l o c a l . p h p

Slide 18

Slide 18 text

ENABLING THE MODULES c o n f i g / a p p l i c a t i o n . c o n f i g . p h p r e t u r n a r r a y ( ' m o d u l e s ' = > a r r a y ( ' Z e n d D e v e l o p e r T o o l s ' , ' D o c t r i n e M o d u l e ' , ' D o c t r i n e O R M M o d u l e ' , ' A p p l i c a t i o n ' , ) , / / [ . . . ] ) ;

Slide 19

Slide 19 text

You should see:

Slide 20

Slide 20 text

WRITE YOUR FIRST ENTITY m o d u l e / A p p l i c a t i o n / s r c / A p p l i c a t i o n / E n t i t y / U s e r n a m e s p a c e A p p l i c a t i o n \ E n t i t y ; u s e D o c t r i n e \ O R M \ M a p p i n g a s O R M ; / * * @ O R M \ E n t i t y * / c l a s s U s e r { / * * * @ O R M \ I d * @ O R M \ G e n e r a t e d V a l u e ( s t r a t e g y = " A U T O " ) * @ O R M \ C o l u m n ( t y p e = " i n t e g e r " ) * / p r o t e c t e d $ i d ; / * * @ O R M \ C o l u m n ( t y p e = " s t r i n g " ) * / p r o t e c t e d $ f u l l N a m e ; / / g e t t e r s / s e t t e r s }

Slide 21

Slide 21 text

CONFIGURE MAPPINGS m o d u l e / A p p l i c a t i o n / c o n f i g / m o d u l e . c o n f i g . p h p r e t u r n a r r a y ( ' d o c t r i n e ' = > a r r a y ( ' d r i v e r ' = > a r r a y ( ' a p p l i c a t i o n _ e n t i t i e s ' = > a r r a y ( ' c l a s s ' = > ' D o c t r i n e \ O R M \ M a p p i n g \ D r i v e r \ A n n o t a t i o n D r i v e r ' ' c a c h e ' = > ' a r r a y ' ' p a t h s ' = > a r r a y ( _ _ D I R _ _ . ' / . . / s r c / A p p l i c a t i o n / E n t i t y ' ) ) , ' o r m _ d e f a u l t ' = > a r r a y ( ' d r i v e r s ' = > a r r a y ( ' A p p l i c a t i o n \ E n t i t y ' = > ' a p p l i c a t i o n _ e n t i t i e s ' ) ) ) ) , / / [ . . . ]

Slide 22

Slide 22 text

You should see:

Slide 23

Slide 23 text

CONFIGURE THE CONNECTION c o n f i g / a u t o l o a d / d o c t r i n e . l o c a l . p h p r e t u r n a r r a y ( ' d o c t r i n e ' = > a r r a y ( ' c o n n e c t i o n ' = > a r r a y ( ' o r m _ d e f a u l t ' = > a r r a y ( ' d r i v e r C l a s s ' = > ' D o c t r i n e \ D B A L \ D r i v e r \ P D O M y S q l \ D r i v e r ' , ' p a r a m s ' = > a r r a y ( ' h o s t ' = > ' l o c a l h o s t ' , ' p o r t ' = > ' 3 3 0 6 ' , ' u s e r ' = > ' u s e r n a m e ' , ' p a s s w o r d ' = > ' p a s s w o r d ' , ' d b n a m e ' = > ' d a t a b a s e ' , ) ) ) ) ) ;

Slide 24

Slide 24 text

VALIDATE MAPPINGS . / v e n d o r / b i n / d o c t r i n e - m o d u l e o r m : v a l i d a t e - s c h e m a

Slide 25

Slide 25 text

GENERATE THE DATABASE

Slide 26

Slide 26 text

. / v e n d o r / b i n / d o c t r i n e - m o d u l e o r m : s c h e m a - t o o l : c r e a t e

Slide 27

Slide 27 text

TEST IT! m o d u l e / A p p l i c a t i o n / s r c / A p p l i c a t i o n / C o n t r o l l e r / I n d e x C o n t r o l l e r . p h p p u b l i c f u n c t i o n i n d e x A c t i o n ( ) { $ o b j e c t M a n a g e r = $ t h i s - > g e t S e r v i c e L o c a t o r ( ) - > g e t ( ' D o c t r i n e \ O R M \ E n t i t y M a n a g e r ' ) ; $ u s e r = n e w \ A p p l i c a t i o n \ E n t i t y \ U s e r ( ) ; $ u s e r - > s e t F u l l N a m e ( ' M a r c o P i v e t t a ' ) ; $ o b j e c t M a n a g e r - > p e r s i s t ( $ u s e r ) ; $ o b j e c t M a n a g e r - > f l u s h ( ) ; d i e ( v a r _ d u m p ( $ u s e r - > g e t I d ( ) ) ) ; / / y e s , I ' m l a z y }

Slide 28

Slide 28 text

EXAMPLES

Slide 29

Slide 29 text

PERSISTING AN OBJECT $ u s e r = n e w U s e r ( ) ; $ u s e r - > s e t F u l l N a m e ( ' M a r c o P i v e t t a ' ) ; $ o b j e c t M a n a g e r - > p e r s i s t ( $ u s e r ) ; / / $ u s e r 1 i s n o w " m a n a g e d " $ o b j e c t M a n a g e r - > f l u s h ( ) ; / / c o m m i t c h a n g e s t o d b v a r _ d u m p ( $ u s e r 1 - > g e t I d ( ) ) ; / / 1

Slide 30

Slide 30 text

PERSISTING MULTIPLE OBJECTS $ u s e r 1 = n e w U s e r ( ) ; $ u s e r 1 - > s e t F u l l N a m e ( ' M a r c o P i v e t t a ' ) ; $ o b j e c t M a n a g e r - > p e r s i s t ( $ u s e r 1 ) ; $ u s e r 2 = n e w U s e r ( ) ; $ u s e r 2 - > s e t F u l l N a m e ( ' M i c h a ë l G a l l e g o ' ) ; $ o b j e c t M a n a g e r - > p e r s i s t ( $ u s e r 2 ) ; $ u s e r 3 = n e w U s e r ( ) ; $ u s e r 3 - > s e t F u l l N a m e ( ' K y l e S p r a g g s ' ) ; $ o b j e c t M a n a g e r - > p e r s i s t ( $ u s e r 3 ) ; $ o b j e c t M a n a g e r - > f l u s h ( ) ;

Slide 31

Slide 31 text

RETRIEVING AN OBJECT $ u s e r 1 = $ o b j e c t M a n a g e r - > f i n d ( ' U s e r ' , 1 ) ; v a r _ d u m p ( $ u s e r 1 - > g e t F u l l N a m e ( ) ) ; / / M a r c o P i v e t t a $ u s e r 2 = $ o b j e c t M a n a g e r - > g e t R e p o s i t o r y ( ' U s e r ' ) - > f i n d O n e B y ( a r r a y ( ' f u l l N a m e ' = > ' M i c h a ë l G a l l e g o ' ) ) ; v a r _ d u m p ( $ u s e r 2 - > g e t F u l l N a m e ( ) ) ; / / M i c h a ë l G a l l e g o

Slide 32

Slide 32 text

UPDATING AN OBJECT $ u s e r = $ o b j e c t M a n a g e r - > f i n d ( ' U s e r ' , 1 ) ; $ u s e r - > s e t F u l l N a m e ( ' G u i l h e r m e B l a n c o ' ) ; $ o b j e c t M a n a g e r - > f l u s h ( ) ;

Slide 33

Slide 33 text

DELETING AN OBJECT $ u s e r = $ o b j e c t M a n a g e r - > f i n d ( ' U s e r ' , 1 ) ; $ o b j e c t M a n a g e r - > r e m o v e ( $ u s e r ) ; $ o b j e c t M a n a g e r - > f l u s h ( ) ;

Slide 34

Slide 34 text

ASSOCIATIONS - USER / * * @ O R M \ E n t i t y * / c l a s s U s e r { / / l i k e b e f o r e / * * @ O R M \ M a n y T o O n e ( t a r g e t E n t i t y = " A d d r e s s " ) * / p r o t e c t e d $ a d d r e s s ; / * * @ O R M \ M a n y T o M a n y ( t a r g e t E n t i t y = " P r o j e c t " ) * / p r o t e c t e d $ p r o j e c t s ; p u b l i c f u n c t i o n _ _ c o n s t r u c t ( ) { $ t h i s - > p r o j e c t s = n e w A r r a y C o l l e c t i o n ( ) ; } / / g e t t e r s / s e t t e r s }

Slide 35

Slide 35 text

ASSOCIATIONS - ADDRESS / * * @ O R M \ E n t i t y * / c l a s s A d d r e s s { / * @ O R M \ I d @ O R M \ C o l u m n ( t y p e = " i n t e g e r " ) @ O R M \ G e n e r a t e d V a l u e ( s t r a t e g y = " A U T O " ) * / p r o t e c t e d $ i d ; / * * @ O R M \ C o l u m n ( t y p e = " s t r i n g " ) * / p r o t e c t e d $ c i t y ; / * * @ O R M \ C o l u m n ( t y p e = " s t r i n g " ) * / p r o t e c t e d $ c o u n t r y ; / / g e t t e r s / s e t t e r s e t c . }

Slide 36

Slide 36 text

ASSOCIATIONS - PROJECTS / * * @ O R M \ E n t i t y * / c l a s s P r o j e c t { / * @ O R M \ I d @ O R M \ C o l u m n ( t y p e = " i n t e g e r " ) @ O R M \ G e n e r a t e d V a l u e ( s t r a t e g y = " A U T O " ) * / p r o t e c t e d $ i d ; / * * @ O R M \ C o l u m n ( t y p e = " s t r i n g " ) * / p r o t e c t e d $ n a m e ; / / g e t t e r s / s e t t e r s }

Slide 37

Slide 37 text

ASSOCIATIONS - PERSISTING ASSOCIATIONS $ u s e r = n e w U s e r ( ) ; $ u s e r - > s e t F u l l N a m e ( ' M a r c o P i v e t t a ' ) ; $ o b j e c t M a n a g e r - > p e r s i s t ( $ u s e r ) ; $ a d d r e s s = n e w A d d r e s s ( ) ; $ a d d r e s s - > s e t C i t y ( ' F r a n k f u r t ' ) $ a d d r e s s - > s e t C o u n t r y ( ' G e r m a n y ' ) ; $ o b j e c t M a n a g e r - > p e r s i s t ( $ a d d r e s s ) ; $ p r o j e c t = n e w P r o j e c t ( ) ; $ p r o j e c t - > s e t N a m e ( ' D o c t r i n e O R M ' ) ; $ o b j e c t M a n a g e r - > p e r s i s t ( $ p r o j e c t ) ; $ u s e r - > s e t A d d r e s s ( $ a d d r e s s ) ; $ u s e r - > g e t P r o j e c t s ( ) - > a d d ( $ p r o j e c t ) ; $ o b j e c t M a n a g e r - > f l u s h ( ) ;

Slide 38

Slide 38 text

ASSOCIATIONS - RETRIEVING ASSOCIATIONS $ u s e r = $ o b j e c t M a n a g e r - > f i n d ( ' U s e r ' , 1 ) ; v a r _ d u m p ( $ u s e r - > g e t A d d r e s s ( ) - > g e t C i t y ( ) ) ; / / F r a n k f u r t v a r _ d u m p ( $ u s e r - > g e t P r o j e c t s ( ) - > f i r s t ( ) - > g e t N a m e ( ) ) / / D o c t r i n e O R M

Slide 39

Slide 39 text

More tutorials at http://marco-pivetta.com/doctrine2-orm-tutorial

Slide 40

Slide 40 text

DOCTRINEMODULE GOODIES

Slide 41

Slide 41 text

EER UML MODEL See what your entities look like in a graph:

Slide 42

Slide 42 text

PAGINATOR ADAPTER u s e D o c t r i n e \ C o m m o n \ C o l l e c t i o n s \ A r r a y C o l l e c t i o n ; u s e D o c t r i n e M o d u l e \ P a g i n a t o r \ A d a p t e r \ C o l l e c t i o n a s A d a p t e r ; u s e Z e n d \ P a g i n a t o r \ P a g i n a t o r ; / / C r e a t e a D o c t r i n e C o l l e c t i o n $ c o l l e c t i o n = n e w A r r a y C o l l e c t i o n ( r a n g e ( 1 , 1 0 1 ) ) ; / / C r e a t e t h e p a g i n a t o r i t s e l f $ p a g i n a t o r = n e w P a g i n a t o r ( n e w A d a p t e r ( $ c o l l e c t i o n ) ) ; $ p a g i n a t o r - > s e t C u r r e n t P a g e N u m b e r ( 1 ) - > s e t I t e m C o u n t P e r P a g e ( 5 ) ;

Slide 43

Slide 43 text

PAGINATOR ADAPTER (ORM) u s e D o c t r i n e O R M M o d u l e \ P a g i n a t o r \ A d a p t e r \ D o c t r i n e P a g i n a t o r ; u s e D o c t r i n e \ O R M \ T o o l s \ P a g i n a t i o n \ P a g i n a t o r a s O R M P a g i n a t o r ; u s e Z e n d \ P a g i n a t o r \ P a g i n a t o r ; / / C r e a t e a D o c t r i n e C o l l e c t i o n $ q u e r y = $ e m - > c r e a t e Q u e r y ( ' S E L E C T f F R O M F o o f J O I N f . b a r b ' ) ; / / C r e a t e t h e p a g i n a t o r i t s e l f $ p a g i n a t o r = n e w P a g i n a t o r ( n e w D o c t r i n e P a g i n a t o r ( n e w O R M P a g i n a t o r ( $ q u e r y ) ) ) ; $ p a g i n a t o r - > s e t C u r r e n t P a g e N u m b e r ( 1 ) - > s e t I t e m C o u n t P e r P a g e ( 5 ) ;

Slide 44

Slide 44 text

OBJECT-EXISTS VALIDATOR $ r e p o s i t o r y = $ o b j e c t M a n a g e r - > g e t R e p o s i t o r y ( ' A p p l i c a t i o n \ E n t i t y \ U s e r ' ) ; $ v a l i d a t o r = n e w \ D o c t r i n e M o d u l e \ V a l i d a t o r \ O b j e c t E x i s t s ( a r r a y ( ' o b j e c t _ r e p o s i t o r y ' = > $ r e p o s i t o r y , ' f i e l d s ' = > a r r a y ( ' e m a i l ' ) ) ) ; v a r _ d u m p ( $ v a l i d a t o r - > i s V a l i d ( ' t e s t @ e x a m p l e . c o m ' ) ) ; v a r _ d u m p ( $ v a l i d a t o r - > i s V a l i d ( a r r a y ( ' e m a i l ' = > ' t e s t @ e x a m p l e . c o m ' ) ) ) ;

Slide 45

Slide 45 text

CACHE ADAPTERS $ z e n d C a c h e = n e w \ Z e n d \ C a c h e \ S t o r a g e \ A d a p t e r \ M e m o r y ( ) ; $ c a c h e = n e w \ D o c t r i n e M o d u l e \ C a c h e \ Z e n d S t o r a g e C a c h e ( $ z e n d C a c h e ) ; $ d o c t r i n e C a c h e = n e w \ D o c t r i n e \ C o m m o n \ C a c h e \ A r r a y C a c h e ( ) ; $ o p t i o n s = n e w \ Z e n d \ C a c h e \ S t o r a g e \ A d a p t e r \ A d a p t e r O p t i o n s ( ) ; $ c a c h e = n e w \ D o c t r i n e M o d u l e \ C a c h e \ D o c t r i n e C a c h e S t o r a g e ( $ o p t i o n s , $ d o c t r i n e C a c h e ) ;

Slide 46

Slide 46 text

HYDRATOR u s e D o c t r i n e M o d u l e \ S t d l i b \ H y d r a t o r \ D o c t r i n e O b j e c t ; $ h y d r a t o r = n e w D o c t r i n e O b j e c t ( $ o b j e c t M a n a g e r , ' A p p l i c a t i o n \ E n t i t y \ C i t y ' ) ; $ c i t y = n e w C i t y ( ) ; $ d a t a = a r r a y ( ' n a m e ' = > ' F r a n k f u r t ' ) ; $ c i t y = $ h y d r a t o r - > h y d r a t e ( $ d a t a , $ c i t y ) ; e c h o $ c i t y - > g e t N a m e ( ) ; / / p r i n t s " F r a n k f u r t " $ d a t a A r r a y = $ h y d r a t o r - > e x t r a c t ( $ c i t y ) ; e c h o $ d a t a A r r a y [ ' n a m e ' ] ; / / p r i n t s " F r a n k f u r t "

Slide 47

Slide 47 text

HYDRATOR (2) u s e D o c t r i n e M o d u l e \ S t d l i b \ H y d r a t o r \ D o c t r i n e O b j e c t ; $ h y d r a t o r = n e w D o c t r i n e O b j e c t ( $ o b j e c t M a n a g e r , ' A p p l i c a t i o n \ E n t i t y \ C i t y ' ) ; $ c i t y = n e w C i t y ( ) ; $ d a t a = a r r a y ( ' c o u n t r y ' = > 1 2 3 ) ; $ c i t y = $ h y d r a t o r - > h y d r a t e ( $ d a t a , $ c i t y ) ; v a r _ d u m p ( $ c i t y - > g e t C o u n t r y ( ) ) ; / / p r i n t s c l a s s C o u n t r y # 1 ( 1 ) { / / p r o t e c t e d $ n a m e = > s t r i n g ( 5 ) " G e r m a n y " / / }

Slide 48

Slide 48 text

FORM ELEMENT $ f o r m - > a d d ( a r r a y ( ' t y p e ' = > ' D o c t r i n e M o d u l e \ F o r m \ E l e m e n t \ O b j e c t S e l e c t ' , ' n a m e ' = > ' u s e r ' , ' o p t i o n s ' = > a r r a y ( ' o b j e c t _ m a n a g e r ' = > $ o b j e c t M a n a g e r , ' t a r g e t _ c l a s s ' = > ' M o d u l e \ E n t i t y \ U s e r ' , ' p r o p e r t y ' = > ' f u l l N a m e ' , ' i s _ m e t h o d ' = > t r u e , ' f i n d _ m e t h o d ' = > a r r a y ( ' n a m e ' = > ' f i n d B y ' , ' p a r a m s ' = > a r r a y ( ' c r i t e r i a ' = > a r r a y ( ' a c t i v e ' = > 1 ) , ' o r d e r B y ' = > a r r a y ( ' l a s t N a m e ' = > ' A S C ' ) , ) , ) , ) , ) ) ;

Slide 49

Slide 49 text

MORE STUFF! Everything works with MongoDB ODM too! CouchDB ODM/PHPCR ODM/OrientDB ODM

Slide 50

Slide 50 text

GOOD PRACTICES

Slide 51

Slide 51 text

KEEP ENTITIES SIMPLE Think of entities as value-objects Don't add logic to entities (hard to change later!) Keep entities aware only of themselves + relations

Slide 52

Slide 52 text

USE DOCTRINE/COMMON API If you stick with using only doctrine/common API, users of your modules can switch between ORM/ MongoDB ODM/CouchDB ODM/ PHPCR ODM/OrientDB ODM

Slide 53

Slide 53 text

USE DOCTRINE/COMMON API Prefer over D o c t r i n e \ C o m m o n \ P e r s i s t e n c e \ O b j e c t M a n a g e r D o c t r i n e \ O R M \ E n t i t y M a n a g e r

Slide 54

Slide 54 text

USE DOCTRINE/COMMON API Prefer over D o c t r i n e \ C o m m o n \ P e r s i s t e n c e \ O b j e c t R e p o s i t o r y D o c t r i n e \ O R M \ E n t i t y R e p o s i t o r y

Slide 55

Slide 55 text

USE COLLECTIONS EXTENSIVELY Doctrine comes with a powerful collections OOP API for array-like data structures API

Slide 56

Slide 56 text

USE THE CRITERIA API Collections provide a Criteria Allows you to filter virtually any kind of data structure API

Slide 57

Slide 57 text

CRITERIA API EXAMPLE u s e D o c t r i n e \ C o m m o n \ C o l l e c t i o n s \ C r i t e r i a ; u s e D o c t r i n e \ C o m m o n \ C o l l e c t i o n s \ A r r a y C o l l e c t i o n ; $ c o l l e c t i o n = n e w A r r a y C o l l e c t i o n ( a r r a y ( $ u s e r 1 , $ u s e r 2 , $ u s e r 3 ) ) ; $ c r i t e r i a = n e w C r i t e r i a ( ) ; $ c r i t e r i a - > a n d W h e r e ( $ c r i t e r i a - > e x p r ( ) - > g t ( ' l a s t L o g i n ' , n e w \ D a t e T i m e ( ' - 1 d a y ' ) ) ) ; $ r e c e n t V i s i t o r s = $ c o l l e c t i o n - > m a t c h i n g ( $ c r i t e r i a ) ; $ r e c e n t V i s i t o r s = $ e m - > g e t R e p o s i t o r y ( ' A p p l i c a t i o n \ E n t i t y \ U s e r s ' ) - > m a t c h i n g ( $ c r i t e r i a ) ;

Slide 58

Slide 58 text

CRITERIA API ADVANTAGES Works in ORM Repositories, Collections, etc... Abstracts the problem of "searching" Same criteria for different storages (ORM, ODM, Memory, ElasticSearch, cache...) Allows you to define your own R e c e n t U s e r s C r i t e r i a or I n a c t i v e U s e r s C r i t e r i a ...

Slide 59

Slide 59 text

INJECT THE OBJECT MANAGER If you fetch the entity manager from within your services, replacing it will become very hard: Inject it instead!

Slide 60

Slide 60 text

INJECT THE OBJECT MANAGER ' f a c t o r i e s ' = > a r r a y ( ' m y _ s e r v i c e ' = > f u n c t i o n ( $ s l ) { $ o b j e c t M a n a g e r = $ s l - > g e t ( ' D o c t r i n e \ O R M \ E n t i t y M a n a g e r ' ) ; r e t u r n n e w M y S e r v i c e ( $ o b j e c t M a n a g e r ) ; } ) , c l a s s M y S e r v i c e { p u b l i c f u n c t i o n _ _ c o n s t r u c t ( O b j e c t M a n a g e r $ o b j e c t M a n a g e r ) { / / [ . . . ] } }

Slide 61

Slide 61 text

KEEP OBJECT MANAGER OUT OF CONTROLLERS

Slide 62

Slide 62 text

DON'T USE PERSISTENCE TO SOLVE APPLICATION PROBLEMS Filtering data when saved to DB Validating data when saved to DB Saving files when records are saved to DB Using DB-level errors to check input validity

Slide 63

Slide 63 text

KEEP YOUR OBJECT GRAPH CONSISTENT An ObjectManager works under the assumption that managed objects are valid! Assign values to your entities only when data is valid!

Slide 64

Slide 64 text

QUESTIONS?

Slide 65

Slide 65 text

FORK IT! You can find these slides on GitHub at https://github.com/Ocramius/doctrine-orm-zf2- tutorial

Slide 66

Slide 66 text

THANKS FOR WATCHING!