Slide 1

Slide 1 text

Doctrine 2 Doctrine 2 — Laravel Austin 1

Slide 2

Slide 2 text

What is Doctrine? An object-relational mapper (ORM) for PHP, that uses the Data Mapper pattern. Doctrine 2 — Laravel Austin 2

Slide 3

Slide 3 text

Entities Objects that have a distinct identity, you also hear these called reference objects Doctrine 2 — Laravel Austin 3

Slide 4

Slide 4 text

Meta Data Doctrine 2 — Laravel Austin 4

Slide 5

Slide 5 text

id; } public function getTitle() { return $this->title; } public function setTitle($title) { $this->title = $title; } } 5

Slide 6

Slide 6 text

# App.Article.dcm.yml App\Article: type: entity table: articles id: id: type: integer generator: strategy: AUTO fields: title: type: string 6

Slide 7

Slide 7 text

// App.Article.dcm.xml 7

Slide 8

Slide 8 text

[ 'type' => 'entity', 'table' => 'articles', 'id' => [ 'id' => [ 'type' => 'integer', 'generator' => [ 'strategy' => 'auto' ] ], ], 'fields' => [ 'title' => [ 'type' => 'string' ] ] ] ]; 8

Slide 9

Slide 9 text

mapField(array( 'id' => true, 'fieldName' => 'id', 'type' => 'integer' )); $metadata->mapField(array( 'fieldName' => 'title', 'type' => 'string' )); } } 9

Slide 10

Slide 10 text

Embeddables An embeddable is an object that can be mapped to a set of columns in a database table. This object will not be mapped to a table by itself, but will be used inside an entity, so its columns will be mapped to the entity's table instead. Doctrine 2 — Laravel Austin 10

Slide 11

Slide 11 text

Slide 12

Slide 12 text

Mapped Superclasses Mapped superclasses allow us to share common state between our entities, without it being an entity itself. Doctrine 2 — Laravel Austin 12

Slide 13

Slide 13 text

Single Table Inheritance An inheritance strategy where all classes are mapped to a single database table Doctrine 2 — Laravel Austin 13

Slide 14

Slide 14 text

Slide 15

Slide 15 text

Class Table Inheritance An inheritance strategy where each class is mapped to several tables: its own, and the parent tables Doctrine 2 — Laravel Austin 15

Slide 16

Slide 16 text

Slide 17

Slide 17 text

Associations Instead of working with foreign keys, you work with references to objects Doctrine 2 — Laravel Austin 17

Slide 18

Slide 18 text

Many-To-One (Unidirectional)

Slide 19

Slide 19 text

One-To-One (Unidirectional)

Slide 20

Slide 20 text

One-To-One (Bidirectional)

Slide 21

Slide 21 text

One-To-One (Self-referencing)

Slide 22

Slide 22 text

One-To-Many (Bidirectional)

Slide 23

Slide 23 text

One-To-Many (Unidirectional with Join Table)

Slide 24

Slide 24 text

One-To-Many (Self-referencing)

Slide 25

Slide 25 text

Many-To-Many (Unidirectional)

Slide 26

Slide 26 text

Many-To-Many (Bidirectional)

Slide 27

Slide 27 text

Many-To-Many (Self-referencing)

Slide 28

Slide 28 text

Entity Manager The central access point to ORM functionality Doctrine 2 — Laravel Austin 28

Slide 29

Slide 29 text

Finding Entities $article = EntityManager::find('App\Article', 1); $article->setTitle('Different title'); $article2 = EntityManager::find('App\Article', 1); if ($article === $article2) { echo "Yes we are the same!"; } Doctrine 2 — Laravel Austin 29

Slide 30

Slide 30 text

Persisting $article = new Article; $article->setTitle('Let\'s learn about persisting'); EntityManager::persist($article); EntityManager::flush(); Doctrine 2 — Laravel Austin 30

Slide 31

Slide 31 text

Flushing // Flush all changes EntityManager::flush(); // Only flush changes of given entity EntityManager::flush($article); Doctrine 2 — Laravel Austin 31

Slide 32

Slide 32 text

Removing EntityManager::remove($article); EntityManager::flush(); Doctrine 2 — Laravel Austin 32

Slide 33

Slide 33 text

Repositories Design pattern abstraction for your persistence layer Doctrine 2 — Laravel Austin 33

Slide 34

Slide 34 text

Ge!ing a Repository $repository = EntityManager::getRepository(Scientist::class); Doctrine 2 — Laravel Austin 34

Slide 35

Slide 35 text

Reusing through Inheritance findBy(['name' => $name]); } } // Then, in one of your ServiceProviders use App\Research\Scientist; class AppServiceProvider { public function register() { $this->app->bind(ScientistRepository::class, function($app) { // This is what Doctrine's EntityRepository needs in its constructor. return new DoctrineScientistRepository( $app['em'], $app['em']->getClassMetaData(Scientist::class) ); }); } } 35

Slide 36

Slide 36 text

Reusing through Composition genericRepository = $genericRepository; } public function find($id) { return $this->genericRepository->find($id); } public function findByName($name) { return $this->genericRepository->findBy(['name' => $name]); } } // Then, in one of your ServiceProviders use App\Research\Scientist; class AppServiceProvider { public function register() { $this->app->bind(ScientistRepository::class, function(){ return new DoctrineScientistRepository( EntityManager::getRepository(Scientist::class) ); }); } } 36

Slide 37

Slide 37 text

Using your custom repository em->createQuery('SELECT u FROM MyDomain\Model\User u WHERE u.status = "admin"') ->getResult(); } } $admins = $em->getRepository('MyDomain\Model\User')->getAllAdminUsers(); Doctrine 2 — Laravel Austin 37

Slide 38

Slide 38 text

DQL Doctrine Query Language, an Object Query Language http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/dql-doctrine-query-language.html 38

Slide 39

Slide 39 text

DQL SELECT clause createQuery('SELECT u FROM MyProject\Model\User u WHERE u.age > :age'); $query->setParameter('age', 20); $users = $query->getResult(); http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/dql-doctrine-query-language.html 39

Slide 40

Slide 40 text

Joins createQuery("SELECT u FROM User u JOIN u.address a WHERE a.city = 'Berlin'"); $query = $em->createQuery("SELECT u, a FROM User u JOIN u.address a WHERE a.city = 'Berlin'"); $users = $query->getResult(); http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/dql-doctrine-query-language.html 40

Slide 41

Slide 41 text

Query Builder An API for conditionally constructing a DQL query http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/query-builder.html 41

Slide 42

Slide 42 text

High level API methods select('u, a') // string 'u' is converted to array internally ->from('User', 'u') ->join('u.address', 'a') ->where($qb->expr()->eq('a.city', '?1')) ->orderBy('u.surname', 'ASC') ->setParameter(1, 'Berlin'); Doctrine 2 — Laravel Austin 42

Slide 43

Slide 43 text

Native SQL Execute native SELECT SQL, mapping the results to Doctrine entities http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/native-sql.html 43

Slide 44

Slide 44 text

ResultSetMapping Example addEntityResult('User', 'u'); $rsm->addFieldResult('u', 'id', 'id'); $rsm->addFieldResult('u', 'name', 'name'); $rsm->addJoinedEntityResult('Address' , 'a', 'u', 'address'); $rsm->addFieldResult('a', 'address_id', 'id'); $rsm->addFieldResult('a', 'street', 'street'); $rsm->addFieldResult('a', 'city', 'city'); $sql = 'SELECT u.id, u.name, a.id AS address_id, a.street, a.city FROM users u ' . 'INNER JOIN address a ON u.address_id = a.id WHERE u.name = ?'; $query = $this->em->createNativeQuery($sql, $rsm); $query->setParameter(1, 'romanb'); $users = $query->getResult(); http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/native-sql.html 44

Slide 45

Slide 45 text

Other Topics — Proxy objects — Reference proxies — Association proxies — Read-Only entities — Extra-Lazy collections Doctrine 2 — Laravel Austin 45

Slide 46

Slide 46 text

Best Practices — Constrain relationships — Use cascades judiciously — Initialize collections in the constructor — Don't map foreign keys to fields — Explicit transaction demarcation Doctrine 2 — Laravel Austin 46

Slide 47

Slide 47 text

DEMO Doctrine 2 — Laravel Austin 47

Slide 48

Slide 48 text

Questions? Doctrine 2 — Laravel Austin 48