Download - Doctrine pro non-doctrine programátory

Transcript

Doctrine pronon-doctrine programátory

Martin Zlámal

@mrtnzlml

Sledujte puntíky…

Toto bude jednoduché a měl bych to znát.

WTF?

Toto bude dobré znát, ale je na to ještě čas…

Integrace do Nette

• Jedna knihovna vládne všem, jedna jim všem káže, jedna všechny přivede, do temnoty sváže.

Kdyby\Doctrine (github.com/Kdyby/Doctrine)

– Filip Procházka

Integrace do Nette

1) composer.json"require": {

"kdyby/doctrine": "~2.3.1

}

2) config.neonextensions:

console: Kdyby\Console\DI\ConsoleExtension

events: Kdyby\Events\DI\EventsExtension

annotations: Kdyby\Annotations\DI\AnnotationsExtension

doctrine: Kdyby\Doctrine\DI\OrmExtension

3) config.local.neondoctrine:

dbname: tada

user: username

ORM – Object-relational mapp(er|ing)

• Doctrine umožňuje pracovat s relační databází objektově

• Hodně věcí se zde točí kolem tzv. entit

„Entita je jakákoliv přesně definovaná množina údajů.“

• Chápete všichni co jsou to entity?

Entity

• Možný je XML nebo YAML mapping

• Doporučuji však použít klasické PHP a anotace:

/**

* @Doctrine\ORM\Mapping\Entity

* @Doctrine\ORM\Mapping\Table(name="posts")

*/

class Post extends Kdyby\Doctrine\Entities\BaseEntity {

//...

Ukázka jednoduché entity

<?php

namespace App;

use Doctrine\ORM\Mapping as ORM;

use Kdyby;

/**

* @ORM\Entity

*/

class User extends Kdyby\Doctrine\Entities\BaseEntity {

use Kdyby\Doctrine\Entities\Attributes\Identifier;

/**

* @ORM\Column(type="string", unique=true)

*/

protected $name;

}

/**

* @ORM\Id

* @ORM\Column(type="integer")

* @ORM\GeneratedValue

* @var integer

*/

private $id;

/**

* @return integer

*/

final public function getId() {

return $this->id;

}

Entity – @anotace

@Column(type=" … ") – unique, nullable, length, options, …

@ManyToOne, @OneToOne(targetEntity="entity_name")

@JoinColumn(name="remote_id", referencedColumnName="id")

@OneToMany, @ManyToMany

@JoinTable

@OrderBy({"name" = "ASC"})

Anotace: http://doctrine-orm.readthedocs.org/en/latest/reference/annotations-reference.html

Vazby: http://doctrine-orm.readthedocs.org/en/latest/reference/association-mapping.html

Nebojte se anotace skutečně využívat

/**

* @ORM\Entity

* @ORM\Table(

* name="mirror_posts",

* options={"engine"="MyISAM"},

* indexes={

* @ORM\Index(columns={"title, body"}, flags={"fulltext"}),

* @ORM\Index(columns={"title"}, flags={"fulltext"}),

* @ORM\Index(columns={"body"}, flags={"fulltext"})

* }

* )

*/

class PostMirror extends Kdyby\Doctrine\Entities\BaseEntity {

//...

EntityManager

• Slouží k práci s entitami jako s celky

• Používá několik principů jako je Identity Map, nebo Lazy Loading

• $em->flush();

$em->persist($entity); $em->remove($entity); $em->detach($entity); $e = $em->merge($entity);

NEW změna na MANAGED ↓ – – $e kopie MANAGED ↓

MANAGED – změna na REMOVED ↓ změna na DETACHED ↓ –

DETACHED EXCEPTION (*) EXCEPTION – $e kopie MANAGED ↑

REMOVED změna na MANAGED ↑ – – EXCEPTION (*)

Create

/** @var EntityManager @inject */

public $em;

$article = new Article;

$article->title = 'Article Title';

$this->em->persist($article);

$this->em->flush();

Read

$articleDao = $this->em->getRepository(Article::class);

$articles = $articleDao->findBy([

'title neq' => 'Dummy title'

]);

foreach ($articles as $article) {

dump($article->title);

}

Update

$articleDao = $this->em->getRepository(Article::class);

/** @var Article $article */

$article = $articleDao->findOneBy([

'title neq' => 'Dummy title',

]);

$article->title = 'New Title';

$this->em->flush();

Delete

$article = $this->em->find(Article::class, $id = 90);

$this->em->remove($article);

$this->em->flush();

EntityDao extends EntityRepository extends EntityRepository

• EntityRepository:• find, findAll, findBy, findOneBy, countBy, findPairs, findAssoc

• select, createQueryBuilder, fetch, fetchOne, …

• EntityDao:• to je to co dostanete při getRepository

• dříve k aktivním zásahům do databáze (save, delete)

• doporučuji používat spíše EntityManager

EntityDao a AOP

• To už je trošku prasárna, ale funkční… (-:

/**

* @Secure\Read(allow="guest")

*/

public function countBy(array $criteria = []) {

return $this->dao->countBy($criteria);

}

services:

- Model\Posts(@doctrine.dao(Entity\Post))

Vlastní „security“ aspekt

Commands

• Na toto začátečníci často zapomínají (neví o tom)…

$ php index.php

$ php index.php orm:info

$ php index.php orm:validate-schema

$ php index.php orm:schema-tool:update

+ vlastní commandy – mrkněte na Kdyby\Console

DQL – Doctrine Query Language

$query = $this->em->createQuery('

SELECT DISTINCT u.id

FROM App\Article a

LEFT JOIN a.user u

WHERE a.title <> :title

AND u NOT IN (

SELECT w.id FROM App\Whatever w

WHERE w.name = :whatever

)

ORDER BY u.name DESC

')->setParameters([

'title' => 'XXX',

'whatever' => 'YYY',

]);

dump($query->getResult());

Query Builder

• Mrkněte na Expression Builder. Je to sice dál, zato horší cestou…

• Zjednodušuje však generování (skládání) dotazů…

Typ hydratace

/** @var Kdyby\Doctrine\QueryBuilder $qb */

$qb = $this->em->createQueryBuilder();

$qb->select('u')->from(App\User::class, 'u')->where('u.id = :id')

->orderBy('u.name', 'ASC')->setParameter('id', 2);

dump($qb->getQuery()->getSingleResult()->name);

Query Object

• Ve spojení s komponentou je to pecka!

• Vlastní query objekt je potomkem objektu QueryObject a obsahuje doCreateQuery metodu.

1. Vytvořte si query objekt

2. Nastavte si jej podle dané situace

3. Předejte tento objekt fetch metodě (z EntityRepository)

4. Win…

help.kdyby.orggithub.com/Kdyby/Doctrine

Děkuji za pozornostwww.zeminem.cz | antstudio.cz

@mrtnzlml