Post on 15-Jul-2015
transcript
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…