Doctrator Symfony Live 2011 Paris

135
Doctrator Pablo Díez Symfony Live 2011 - Paris viernes 4 de marzo de 2011

description

 

Transcript of Doctrator Symfony Live 2011 Paris

Page 1: Doctrator Symfony Live 2011 Paris

DoctratorPablo Díez

Symfony Live 2011 - Paris

viernes 4 de marzo de 2011

Page 2: Doctrator Symfony Live 2011 Paris

Pablo DíezCreator of Mondongo

ODM for MongoDB and PHPhttp://mondongo.es (in English :)

Creator of MondatorClass generator for PHP

Creator of Doctrator

http://twitter.com/pablodiphttp://github.com/pablodip

viernes 4 de marzo de 2011

Page 3: Doctrator Symfony Live 2011 Paris

What is Doctrator?

viernes 4 de marzo de 2011

Page 4: Doctrator Symfony Live 2011 Paris

Doctrator = Doctrine2 + Mondator

viernes 4 de marzo de 2011

Page 5: Doctrator Symfony Live 2011 Paris

Agile Development

viernes 4 de marzo de 2011

Page 6: Doctrator Symfony Live 2011 Paris

Agile Development

ActiveRecord

viernes 4 de marzo de 2011

Page 7: Doctrator Symfony Live 2011 Paris

ActiveRecord optional

Agile Development

viernes 4 de marzo de 2011

Page 8: Doctrator Symfony Live 2011 Paris

ActiveRecord

Behaviors

Agile Development

viernes 4 de marzo de 2011

Page 9: Doctrator Symfony Live 2011 Paris

Doctrator saves you a lot of time! ;)

ActiveRecord

Behaviors

Agile Development

viernes 4 de marzo de 2011

Page 10: Doctrator Symfony Live 2011 Paris

How does Doctrine2 work?

viernes 4 de marzo de 2011

Page 11: Doctrator Symfony Live 2011 Paris

“Doctrine2 provides transparent persistence for PHP objects.”

How does Doctrine2 work?

http://www.doctrine-project.org/docs/orm/2.0/en/reference/introduction.html

viernes 4 de marzo de 2011

Page 12: Doctrator Symfony Live 2011 Paris

namespace Model;

class User{ public $id; public $username; public $email;}

That is, persist PHP objects without restrictions of a base class, properties, methods.

viernes 4 de marzo de 2011

Page 13: Doctrator Symfony Live 2011 Paris

You only have to tell Doctrine2 (map) what you want to persist.

viernes 4 de marzo de 2011

Page 14: Doctrator Symfony Live 2011 Paris

With Docblock Annotations

/** * @Entity */class User{ /** * @Id * @Column(type="integer") */ public $id; /** * @Column(length=50) */ public $username; /** * @Column(length=100) */ public $email;}

You only have to tell Doctrine2 (map) what you want to persist.

viernes 4 de marzo de 2011

Page 15: Doctrator Symfony Live 2011 Paris

Entities\User: type: entity fields: id: { type: integer, id: true } username: { type: string(50) } email: { type: string(50) }

With YAML

You only have to tell Doctrine2 (map) what you want to persist.

viernes 4 de marzo de 2011

Page 16: Doctrator Symfony Live 2011 Paris

<?xml version="1.0" encoding="UTF-8"?><doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping http://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">

<entity name="Model\User" table="user">

<id name="id" type="integer" column="id"> <generator strategy="AUTO"/> </id>

<field name="username" type="string" length="50" /> <field name="email" type="string" length="100" />

</entity>

</doctrine-mapping>

With XML

You only have to tell Doctrine2 (map) what you want to persist.

viernes 4 de marzo de 2011

Page 17: Doctrator Symfony Live 2011 Paris

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

$metadata->mapField(array( 'fieldName' => 'username', 'type' => 'string'));

$metadata->mapField(array( 'fieldName' => 'email', 'type' => 'string'));

With PHP

You only have to tell Doctrine2 (map) what you want to persist.

viernes 4 de marzo de 2011

Page 18: Doctrator Symfony Live 2011 Paris

Then you are able to persist those objects.

You only have to tell Doctrine2 (map) what you want to persist.

viernes 4 de marzo de 2011

Page 19: Doctrator Symfony Live 2011 Paris

Then you are able to persist those objects.

$user = new User();$user->username = 'pablodip';$user->password = 'pa$$word';$user->email = '[email protected]';

$entityManager->persist($user);$entityManager->flush();

viernes 4 de marzo de 2011

Page 20: Doctrator Symfony Live 2011 Paris

class User{ protected $id; protected $username; protected $password; protected $email;}

A Doctrine2 good practice is to use non public properties in the entities.

viernes 4 de marzo de 2011

Page 21: Doctrator Symfony Live 2011 Paris

Setters & Getters

You have to create methods to access to the properties.

public function setId($id){ $this->id = $id;}

public function getId(){ return $this->id;}

public function setUsername($username){ $this->username = $username;}

public function getUsername(){ return $this->username;}

public function setPassword($password){ $this->password = $password;

viernes 4 de marzo de 2011

Page 22: Doctrator Symfony Live 2011 Paris

useruser

id integer

username string

password string

email string

What do you need to work with this simple table?

viernes 4 de marzo de 2011

Page 23: Doctrator Symfony Live 2011 Paris

useruser

id integer

username string

password string

email string

namespace Model;

class User{}

Class

viernes 4 de marzo de 2011

Page 24: Doctrator Symfony Live 2011 Paris

useruser

id integer

username string

password string

email string

namespace Model;

class User{}

protected $id;protected $username;protected $password;protected $email;

ClassProperties

viernes 4 de marzo de 2011

Page 25: Doctrator Symfony Live 2011 Paris

useruser

id integer

username string

password string

email string

namespace Model;

class User{}

protected $id;protected $username;protected $password;protected $email;

ClassProperties

public function setId($id){ $this->id = $id;}

public function getId(){ return $this->id;}

public function setUsername($username){ $this->username = $username;}

public function getUsername(){ return $this->username;}

public function setPassword($password){ $this->password = $password;

Setters/Getters

viernes 4 de marzo de 2011

Page 26: Doctrator Symfony Live 2011 Paris

useruser

id integer

username string

password string

email string

namespace Model;

class User{}

protected $id;protected $username;protected $password;protected $email;

ClassProperties

public function setId($id){ $this->id = $id;}

public function getId(){ return $this->id;}

public function setUsername($username){ $this->username = $username;}

public function getUsername(){ return $this->username;}

public function setPassword($password){ $this->password = $password;

Setters/Getters

/** * @Entity */

/** * @Id * @Column(type="integer") */ /** * @Column(length=50) */ /** * @Column(length=100) */

Mapping

viernes 4 de marzo de 2011

Page 27: Doctrator Symfony Live 2011 Paris

useruser

id integer

username string

password string

email string

namespace Model;

/** * @Entity */class User{ /** * @Id * @Column(type="integer") */ protected $id; /** * @Column(length="50") */ protected $username; /** * @Column(length="40") */ protected $password; /** * @Column(length="100") */ protected $email;

public function setId($id) { $this->id = $id; }

public function getId() { return $this->id; }

public function setUsername($username) { $this->username = $username; }

public function getUsername() { return $this->username; }

public function setPassword($password) { $this->password = $password; }

public function getPassword() { return $this->password; }

public function setEmail($email) { $this->email = $email; }

public function getEmail() { return $this->email; }}

viernes 4 de marzo de 2011

Page 28: Doctrator Symfony Live 2011 Paris

useruser

id integer

username string

password string

email string

namespace Model;

/** * @Entity */class User{ /** * @Id * @Column(type="integer") */ protected $id; /** * @Column(length="50") */ protected $username; /** * @Column(length="40") */ protected $password; /** * @Column(length="100") */ protected $email;

public function setId($id) { $this->id = $id; }

public function getId() { return $this->id; }

public function setUsername($username) { $this->username = $username; }

public function getUsername() { return $this->username; }

public function setPassword($password) { $this->password = $password; }

public function getPassword() { return $this->password; }

public function setEmail($email) { $this->email = $email; }

public function getEmail() { return $this->email; }}

LORC

viernes 4 de marzo de 2011

Page 29: Doctrator Symfony Live 2011 Paris

LORC

Lines Of Repetitive Code

viernes 4 de marzo de 2011

Page 30: Doctrator Symfony Live 2011 Paris

LORC

Lines Of Repetitive Code

... and we still don’t have any features! :)

viernes 4 de marzo de 2011

Page 31: Doctrator Symfony Live 2011 Paris

How many LORC do we need in a real database?

viernes 4 de marzo de 2011

Page 32: Doctrator Symfony Live 2011 Paris

How many LORC do we need in a real database?

...

viernes 4 de marzo de 2011

Page 33: Doctrator Symfony Live 2011 Paris

What does Doctrator do?

viernes 4 de marzo de 2011

Page 34: Doctrator Symfony Live 2011 Paris

Doctrator generates classes and maps them with Doctrine2

What does Doctrator do?

viernes 4 de marzo de 2011

Page 35: Doctrator Symfony Live 2011 Paris

You only have to tell it the configuration of the classes.

Doctrator generates classes and maps them with Doctrine2

viernes 4 de marzo de 2011

Page 36: Doctrator Symfony Live 2011 Paris

array( 'Model\User' => array( 'columns' => array( 'id' => array('id' => 'auto', 'type' => 'integer'), 'username' => array('type' => 'string', 'length' => 50), 'password' => array('type' => 'string', 'length' => 40), 'email' => array('type' => 'string', 'length' => 100), ), ),);

In PHP

viernes 4 de marzo de 2011

Page 37: Doctrator Symfony Live 2011 Paris

Model\User: columns: id: { id: auto, type: integer } username: { type: string, length: 50 } password: { type: string, length: 40 } email: { type: string, length: 100 }

In YAML

viernes 4 de marzo de 2011

Page 38: Doctrator Symfony Live 2011 Paris

Model\User: columns: id: { id: auto, type: integer } username: { type: string, length: 50 } password: { type: string, length: 40 } email: { type: string, length: 100 }

This generates your object.

class User{

protected $id;

protected $username;

protected $password;

protected $email;

public function setId($id) { $this->id = $id; }

public function getId() { return $this->id; }

public function setUsername($username) { $this->username = $username; }

public function getUsername() { return $this->username; }

public function setPassword($password) { $this->password = $password; }

public function getPassword() { return $this->password; }

public function setEmail($email)

This maps your object.

/** * @Entity */

/** * @Id * @Column(type="integer") */ /** * @Column(length=50) */ /** * @Column(length=100) */

viernes 4 de marzo de 2011

Page 39: Doctrator Symfony Live 2011 Paris

Model\User: columns: id: { id: auto, type: integer } username: { type: string, length: 50 } password: { type: string, length: 40 } email: { type: string, length: 100 }

You can start to work.

$user = new \Model\User();$user->setUsername('pagafantas');$user->setEmail('[email protected]');

$entityManager->persist($user);$entityManager->flush();

viernes 4 de marzo de 2011

Page 40: Doctrator Symfony Live 2011 Paris

How does Doctrator work?

viernes 4 de marzo de 2011

Page 41: Doctrator Symfony Live 2011 Paris

Doctrator uses Mondator to generate the classes for you.

How does Doctrator work?

viernes 4 de marzo de 2011

Page 42: Doctrator Symfony Live 2011 Paris

Mondator defines PHP classes.

viernes 4 de marzo de 2011

Page 43: Doctrator Symfony Live 2011 Paris

namespace Model;

class User{ protected $username; public function setUsername($username) { $this->username = $username; } public function getUsername() { return $this->username; }}

viernes 4 de marzo de 2011

Page 44: Doctrator Symfony Live 2011 Paris

namespace Model;

class User{ protected $username; public function setUsername($username) { $this->username = $username; } public function getUsername() { return $this->username; }}

Definition

Properties

Methods

viernes 4 de marzo de 2011

Page 45: Doctrator Symfony Live 2011 Paris

use Mondongo\Mondator\Definition\Definition;use Mondongo\Mondator\Definition\Property;use Mondongo\Mondator\Definition\Method;

viernes 4 de marzo de 2011

Page 46: Doctrator Symfony Live 2011 Paris

namespace Model;

class User{}

$definition = new Definition('Model\User');

Full Class Name

viernes 4 de marzo de 2011

Page 47: Doctrator Symfony Live 2011 Paris

protected $username;

$property = new Property('protected', 'username');$definition->addProperty($property);

Visibility Name

viernes 4 de marzo de 2011

Page 48: Doctrator Symfony Live 2011 Paris

public function setUsername($username){ $this->username = $username;}

$method = new Method('public', 'setUsername', '$username', <<<EOF \$this->username = \$username;EOF);$definition->addMethod($method);

Visibility Name Arguments Code

viernes 4 de marzo de 2011

Page 49: Doctrator Symfony Live 2011 Paris

You can define any PHP class.

viernes 4 de marzo de 2011

Page 50: Doctrator Symfony Live 2011 Paris

$definition->setParentClass('\Model\Base\User');

$definition->addInterface('\ArrayAccess');

$definition->setIsAbstract(true);

Parent class

Interfaces

Abstract

viernes 4 de marzo de 2011

Page 51: Doctrator Symfony Live 2011 Paris

$property->setValue($defaultValue);

$property->setIsStatic(true);

Default value

Static

viernes 4 de marzo de 2011

Page 52: Doctrator Symfony Live 2011 Paris

$method->setIsAbstract(true);

$method->setIsStatic(true);

Abstract

Static

viernes 4 de marzo de 2011

Page 53: Doctrator Symfony Live 2011 Paris

Even with comments.

viernes 4 de marzo de 2011

Page 54: Doctrator Symfony Live 2011 Paris

$definition->setDocComment(<<<EOF/** * User Class. */EOF);

$method->setDocComment(<<<EOF /** * Set the username. * * @param string \$username The username. */EOF);

viernes 4 de marzo de 2011

Page 55: Doctrator Symfony Live 2011 Paris

use \Mondongo\Mondator\Dumper;

$dumper = new Dumper($definition);$classCode = $dumper->dump();

echo $classCode;

Then you can export them with the Dumper.

viernes 4 de marzo de 2011

Page 56: Doctrator Symfony Live 2011 Paris

/** * User entity. */class User{ protected $username; /** * Set the username. * * @param string $username The username. */ public function setUsername($username) { $this->username = $username; } /** * Returns the username. * * @return string The username. */ public function getUsername() { return $this->username; }}

viernes 4 de marzo de 2011

Page 57: Doctrator Symfony Live 2011 Paris

And save them in files.

file_put_contents($file, $codeClass);

viernes 4 de marzo de 2011

Page 58: Doctrator Symfony Live 2011 Paris

Mondator Extensions

viernes 4 de marzo de 2011

Page 59: Doctrator Symfony Live 2011 Paris

Mondator uses extensions to generate similar classes in a powerful and flexible way.

Mondator Extensions

viernes 4 de marzo de 2011

Page 60: Doctrator Symfony Live 2011 Paris

The Mondator Extensions process the config classes to define what classes will be generated.

viernes 4 de marzo de 2011

Page 61: Doctrator Symfony Live 2011 Paris

The Mondator Extensions process the config classes to define what classes will be generated.

Model\User: columns: id: { id: auto, type: integer } username: { type: string, length: 50 } password: { type: string, length: 40 } email: { type: string, length: 100 }

Mondongo\Mondator\Definition\Definition

viernes 4 de marzo de 2011

Page 62: Doctrator Symfony Live 2011 Paris

Model\User: columns: id: { id: auto, type: integer } username: { type: string, length: 50 } password: { type: string, length: 40 } email: { type: string, length: 100 }

use Mondongo\Mondator\Extension;

class Doctrator extends Extension{ protected function doClassProcess() { $this->class; $this->configClass; $this->definitions; }}

viernes 4 de marzo de 2011

Page 63: Doctrator Symfony Live 2011 Paris

Model\User: columns: id: { id: auto, type: integer } username: { type: string, length: 50 } password: { type: string, length: 40 } email: { type: string, length: 100 }

use Mondongo\Mondator\Extension;

class Doctrator extends Extension{ protected function doClassProcess() { $this->class; $this->configClass; $this->definitions; }}

viernes 4 de marzo de 2011

Page 64: Doctrator Symfony Live 2011 Paris

Model\User: columns: id: { id: auto, type: integer } username: { type: string, length: 50 } password: { type: string, length: 40 } email: { type: string, length: 100 }

use Mondongo\Mondator\Extension;

class Doctrator extends Extension{ protected function doClassProcess() { $this->class; $this->configClass; $this->definitions; }}

viernes 4 de marzo de 2011

Page 65: Doctrator Symfony Live 2011 Paris

Model\User: columns: id: { id: auto, type: integer } username: { type: string, length: 50 } password: { type: string, length: 40 } email: { type: string, length: 100 }

use Mondongo\Mondator\Extension;

class Doctrator extends Extension{ protected function doClassProcess() { $this->class; $this->configClass; $this->definitions; }} Definitions to generate

viernes 4 de marzo de 2011

Page 66: Doctrator Symfony Live 2011 Paris

An extension can generate any definition.

viernes 4 de marzo de 2011

Page 67: Doctrator Symfony Live 2011 Paris

use Mondongo\Mondator\Extension;use Mondongo\Mondator\Definition\Definition;

class Doctrator extends Extension{ protected function doClassProcess() { $definition = new Definition($this->class); $this->definitions['entity'] = $definition;

$definition = new Definition($this->class.'Repository'); $this->definitions['repository'] = $definition; }}

viernes 4 de marzo de 2011

Page 68: Doctrator Symfony Live 2011 Paris

foreach ($this->configClass['columns'] as $name => $column) {

$property = new Property('protected', $name);

$this->definitions['entity']->addProperty($property);

}

viernes 4 de marzo de 2011

Page 69: Doctrator Symfony Live 2011 Paris

foreach ($this->configClass['columns'] as $name => $column) { $setterName = 'set'.Inflector::camelize($name); $setter = new Method('public', $setterName, '$value', <<<EOF \$this->$name = \$value;EOF );

$this->definitions['entity']->addMethod($setter);}

viernes 4 de marzo de 2011

Page 70: Doctrator Symfony Live 2011 Paris

Different extensions can modify the same definition.

viernes 4 de marzo de 2011

Page 71: Doctrator Symfony Live 2011 Paris

class Doctrator extends Extension{ protected function doClassProcess() { $definition = new Definition($this->class); $this->definitions['entity'] = $defintion; $this->processColumns(); }}

class ArrayAccess extends Extension{ protected function doClassProcess() { $this->definitions['entity']->addInterface('\ArrayAccess'); $method = new Method('public', 'offsetGet', '$name', $code); $this->definitions['entity']->addMethod($method); // ... }}

viernes 4 de marzo de 2011

Page 72: Doctrator Symfony Live 2011 Paris

An extension can have options.

viernes 4 de marzo de 2011

Page 73: Doctrator Symfony Live 2011 Paris

class Doctrator extends Extension{ protected function setUp() { $this->addOptions(array( 'columns' => true, 'array_access' => true, )); }

protected function doClassProcess() { if ($this->getOption('columns')) { $this->processColumns(); } if ($this->getOption('array_access')) { $this->processArrayAccess(); } }}

viernes 4 de marzo de 2011

Page 74: Doctrator Symfony Live 2011 Paris

You can process the extensions that you want.

viernes 4 de marzo de 2011

Page 75: Doctrator Symfony Live 2011 Paris

$mondator = new \Mondongo\Mondator\Mondator();$mondator->setConfigClasses($configClasses);$mondator->setExtensions(array( new \Doctrator\Extension\Core($options), new \Doctrator\Extension\ArrayAccess(),));$mondator->process();

$article['title'] = 'Doctrator';echo $article['title']; // Doctrator

viernes 4 de marzo de 2011

Page 76: Doctrator Symfony Live 2011 Paris

$mondator = new \Mondongo\Mondator\Mondator();$mondator->setConfigClasses($configClasses);$mondator->setExtensions(array( new \Doctrator\Extension\Core($options), //new \Doctrator\Extension\ArrayAccess(),));$mondator->process();

$article['title'] = 'Doctrator';echo $article['title']; // Doctrator

viernes 4 de marzo de 2011

Page 77: Doctrator Symfony Live 2011 Paris

An extension can change the config class to extend another extension.

viernes 4 de marzo de 2011

Page 78: Doctrator Symfony Live 2011 Paris

class Doctrator extends Extension{ protected function doClassProcess() { foreach ($this->configClass['columns'] as $name => $column) { // ... } }}

class DateColumn extends Extension{ protected function doConfigClassProcess() { $this->configClass['columns']['date'] = array( 'type' => 'date', ) }}

viernes 4 de marzo de 2011

Page 79: Doctrator Symfony Live 2011 Paris

You can even use extensions in the config classes.

viernes 4 de marzo de 2011

Page 80: Doctrator Symfony Live 2011 Paris

Model\Article: columns: id: { id: auto, type: integer } title: { type: string, length: 100 } behaviors: - class: Doctrator\Behavior\Timestampable options: { }

viernes 4 de marzo de 2011

Page 81: Doctrator Symfony Live 2011 Paris

And you can combine all these things to do what you want.

viernes 4 de marzo de 2011

Page 82: Doctrator Symfony Live 2011 Paris

Generated code is not necessarily magic code.

viernes 4 de marzo de 2011

Page 83: Doctrator Symfony Live 2011 Paris

Doctrator Extensions

viernes 4 de marzo de 2011

Page 84: Doctrator Symfony Live 2011 Paris

Core

ActiveRecordArrayAccess PropertyOverloading Behaviors

Doctrator Extensions

viernes 4 de marzo de 2011

Page 85: Doctrator Symfony Live 2011 Paris

Core

Generates and maps objects with Doctrine2.

viernes 4 de marzo de 2011

Page 86: Doctrator Symfony Live 2011 Paris

Doctrator uses base classes to separate generated code from your code.

viernes 4 de marzo de 2011

Page 87: Doctrator Symfony Live 2011 Paris

Model\Usernamespace Model;

class User extends \Model\Base\User{ // your code}

namespace Model\Base;

class User{ // generated code}

viernes 4 de marzo de 2011

Page 88: Doctrator Symfony Live 2011 Paris

Model\Article: table_name: articles columns: id: { id: auto, type: integer } title: { type: string, length: 100 } slug: { type: string, length: 100 } content: { type: string } is_active: { type: boolean, default: true } date: { type: date } many_to_one: category: { class: Model\Category, inversed: articles } indexes: slug: { columns: ['slug'], unique: true } date: { columns: ['is_active', 'date'] } events: preUpdate: ['updateDate']

viernes 4 de marzo de 2011

Page 89: Doctrator Symfony Live 2011 Paris

Model\Article: table_name: articles columns: id: { id: auto, type: integer } title: { type: string, length: 100 } slug: { type: string, length: 100 } content: { type: string } is_active: { type: boolean, default: true } date: { type: date } many_to_one: category: { class: Model\Category, inversed: articles } indexes: slug: { columns: ['slug'], unique: true } date: { columns: ['is_active', 'date'] } events: preUpdate: ['updateDate']

Associations

one_to_oneone_to_manymany_to_one

many_to_many

nameclass

mappedinversed

viernes 4 de marzo de 2011

Page 90: Doctrator Symfony Live 2011 Paris

Model\Article: table_name: articles columns: id: { id: auto, type: integer } title: { type: string, length: 100 } slug: { type: string, length: 100 } content: { type: string } is_active: { type: boolean, default: true } date: { type: date } many_to_one: category: { class: Model\Category, inversed: articles } indexes: slug: { columns: ['slug'], unique: true } date: { columns: ['is_active', 'date'] } events: preUpdate: ['updateDate']

Events

prePersistpostPersistpreUpdatepostUpdatepreRemovepostRemove

postLoad

viernes 4 de marzo de 2011

Page 91: Doctrator Symfony Live 2011 Paris

$category = new \Model\Category();$category->setName('Class Generator');$entityManager->persist($category);

$article = new \Model\Article();$article->setTitle('Doctrator');$article->setDate(new \DateTime('now'));$article->setCategory($category);$entityManager->persist($article);

$entityManager->flush();

viernes 4 de marzo de 2011

Page 92: Doctrator Symfony Live 2011 Paris

Useful methods.

Core

viernes 4 de marzo de 2011

Page 93: Doctrator Symfony Live 2011 Paris

$article->set('title', 'Doctrator');

echo $article->get('title'); // Doctrator

Set & Get by string

viernes 4 de marzo de 2011

Page 94: Doctrator Symfony Live 2011 Paris

$article->fromArray(array( 'title' => 'Doctrator', 'date' => new \DateTime('now')));

$array = $article->toArray();

fromArray & toArray

viernes 4 de marzo de 2011

Page 95: Doctrator Symfony Live 2011 Paris

Implements the ArrayAccess interface in the entities.

ArrayAccess

viernes 4 de marzo de 2011

Page 96: Doctrator Symfony Live 2011 Paris

$article = new \ModelArticle();$article['title'] = 'Doctrator';echo $article['title']; // Doctrator

viernes 4 de marzo de 2011

Page 97: Doctrator Symfony Live 2011 Paris

Allows you access to entity data like properties.

PropertyOverloading

viernes 4 de marzo de 2011

Page 98: Doctrator Symfony Live 2011 Paris

$article = new \ModelArticle();$article->title = 'Doctrator';echo $article->title; // Doctrator

viernes 4 de marzo de 2011

Page 99: Doctrator Symfony Live 2011 Paris

Implements the ActiveRecord pattern in your entities.

ActiveRecord

viernes 4 de marzo de 2011

Page 100: Doctrator Symfony Live 2011 Paris

$article = new \Model\Article();$article->setTitle('Doctrator');$article->save();

$article->refresh();

$article->delete();

viernes 4 de marzo de 2011

Page 101: Doctrator Symfony Live 2011 Paris

print_r($article);

viernes 4 de marzo de 2011

Page 102: Doctrator Symfony Live 2011 Paris

Model\Article Object( [id:protected] => 1 [title:protected] => Doctrator [content:protected] => Rocks!)

Doctrator entities are clean even with ActiveRecord!

print_r($article);

viernes 4 de marzo de 2011

Page 103: Doctrator Symfony Live 2011 Paris

$em = \Model\Article::entityManager();$articleRepository = \Model\Article::repository();$queryBuilder = \Model\Article::queryBuilder();

viernes 4 de marzo de 2011

Page 104: Doctrator Symfony Live 2011 Paris

$articles = \Model\Article::repository()->findAll();$article = \Model\Article::repository()->find($id);

$articles = $entityManager->getRepository('Model\Article')->findAll();$article = $entityManager->getRepository('Model\Article')->find($id);

viernes 4 de marzo de 2011

Page 105: Doctrator Symfony Live 2011 Paris

Behaviors

viernes 4 de marzo de 2011

Page 106: Doctrator Symfony Live 2011 Paris

Behaviors

Reuse features.

viernes 4 de marzo de 2011

Page 107: Doctrator Symfony Live 2011 Paris

A behavior is simply a Mondator extension.

viernes 4 de marzo de 2011

Page 108: Doctrator Symfony Live 2011 Paris

A behavior can

Have optionsChange config classes:• Columns• Associations• Indexes• Events• ...

Add new generated classesAdd properties and methods• Entities• Repositories• ...

viernes 4 de marzo de 2011

Page 109: Doctrator Symfony Live 2011 Paris

Saves the created and updated date.

Timestampable

created TRUE

created_column created_at

updated TRUE

updated_column updated_at

viernes 4 de marzo de 2011

Page 110: Doctrator Symfony Live 2011 Paris

Model\Article: columns: id: { id: auto, type: integer } title: { type: name, length: 100 } behaviors: - Doctrator\Behavior\Timestampable

viernes 4 de marzo de 2011

Page 111: Doctrator Symfony Live 2011 Paris

$article = new \Model\Article();$article->setTitle('Doctrator');$article->save(); echo $article->getCreatedAt(); // nowecho $article->getUpdatedAt(); // null $article->setContent('Rocks!');$article->save(); echo $article->getCreatedAt(); // beforeecho $article->getUpdatedAt(); // now

viernes 4 de marzo de 2011

Page 112: Doctrator Symfony Live 2011 Paris

Saves the created and updated ip.

Ipable

created TRUE

created_column created_from

updated TRUE

updated_column updated_from

viernes 4 de marzo de 2011

Page 113: Doctrator Symfony Live 2011 Paris

Saves a unique hash in each entity.

IpableHashable

column hash

viernes 4 de marzo de 2011

Page 114: Doctrator Symfony Live 2011 Paris

Model\Article: columns: id: { id: auto, type: integer } title: { type: name, length: 100 } behaviors: - Doctrator\Behavior\Hashable

viernes 4 de marzo de 2011

Page 115: Doctrator Symfony Live 2011 Paris

$article = new Article();$article->setTitle('Doctrator');

$entityManager->persist();$entityManager->flush();

echo $article->getHash();// da39a3ee5e6b4b0d3255bfef95601890afd80709

viernes 4 de marzo de 2011

Page 116: Doctrator Symfony Live 2011 Paris

Saves a slug from a field.

TimestampableSluggable

from_column *

slug_column slug

unique TRUE

update FALSE

viernes 4 de marzo de 2011

Page 117: Doctrator Symfony Live 2011 Paris

Model\Article: columns: id: { id: auto, type: integer } title: { type: name, length: 100 } behaviors: - class: Doctrator\Behavior\Sluggable options: { from_column: title }

viernes 4 de marzo de 2011

Page 118: Doctrator Symfony Live 2011 Paris

$article = new \Model\Article();$article->setTitle('Doctrator Rocks!');$article->save(); echo $article->getSlug(); // doctrator-rocks

viernes 4 de marzo de 2011

Page 119: Doctrator Symfony Live 2011 Paris

Allows you to sort your entities.

column position

new_position bottom

Sortable

viernes 4 de marzo de 2011

Page 120: Doctrator Symfony Live 2011 Paris

$articles = array();for ($i = 0; $i <= 10; $i++) { $articles[$i] = $a = new \Model\Article(); $a->setTitle('Article '.$i); $a->save();} echo $articles[3]->getPosition(); // 3echo $articles[6]->getPosition(); // 6

viernes 4 de marzo de 2011

Page 121: Doctrator Symfony Live 2011 Paris

// some methods$articles[1]->isFirst();$articles[1]->isLast();$articles[1]->getNext();$articles[1]->getPrevious();$articles[1]->swapWith($articles[2]);$articles[1]->moveUp();$articles[1]->moveDown(); $repository->getMinPosition();$repository->getMaxPosition();

viernes 4 de marzo de 2011

Page 122: Doctrator Symfony Live 2011 Paris

Allows you to save tags in the entities.

SortableTaggable

viernes 4 de marzo de 2011

Page 123: Doctrator Symfony Live 2011 Paris

$article = new \Model\Article();$article->setTitle('My Title');$article->save(); // methods$article->addTags('foobar, barfoo');$article->removeTags('foobar');$article->removeAllTags(); // saved and not saved$article->getSavedTags();$article->getTags(); // saved and not saved$article->setTags(array('foo', 'bar'));$article->saveTags(); $repository->getTags();$repository->getTagsWithCount();

viernes 4 de marzo de 2011

Page 124: Doctrator Symfony Live 2011 Paris

Allows you to translate entity columns.

columns *

SortableTaggableTranslatable

viernes 4 de marzo de 2011

Page 125: Doctrator Symfony Live 2011 Paris

Model\Article: columns: id: { id: auto, type: integer } title: { type: string, length: 100 } content: { type: string } date: { type: date } behaviors: - class: Doctrator\Behavior\Translatable options: { columns: ['title', 'content'] }

viernes 4 de marzo de 2011

Page 126: Doctrator Symfony Live 2011 Paris

$article = new \Model\Article();$article->setDate(new \DateTime()); // en$article->translation('en')->setTitle('My Title');$article->translation('en')->setContent('My Content'); // es$article->translation('es')->setTitle('Mi Título');$article->translation('es')->setContent('Mi Contenido'); $article->save();

viernes 4 de marzo de 2011

Page 127: Doctrator Symfony Live 2011 Paris

Doctrator in Symfony2

viernes 4 de marzo de 2011

Page 128: Doctrator Symfony Live 2011 Paris

DoctratorBundle

viernes 4 de marzo de 2011

Page 129: Doctrator Symfony Live 2011 Paris

doctrator.config: extensions: array_access: false property_overloading: false active_record: true behaviors: true

validation: true

viernes 4 de marzo de 2011

Page 130: Doctrator Symfony Live 2011 Paris

doctrator.config: extensions: array_access: false property_overloading: false active_record: true behaviors: true

validation: true

my_extension_id: true

viernes 4 de marzo de 2011

Page 131: Doctrator Symfony Live 2011 Paris

*Bundle/Resources/doctrator/*.yml

Config Classes

app/config/doctrator/*.yml

viernes 4 de marzo de 2011

Page 132: Doctrator Symfony Live 2011 Paris

Model\Article: columns: id: { id: auto, type: integer } title: { type: string, length: 100 } content: { type: string }

Model\DoctratorUserBundle\User: columns: id: { id: auto, type: integer } username: { type: string, length: 20 }

Standard Namespace

viernes 4 de marzo de 2011

Page 133: Doctrator Symfony Live 2011 Paris

Model\Article: validation: - MyArticleClassValidator: ~ columns: id: { id: auto, type: integer } title: { type: string, length: 100 } content: { type: string, validation: [MaxLength: 2000] }

Validation integrated

viernes 4 de marzo de 2011

Page 134: Doctrator Symfony Live 2011 Paris

php app/console doctrator:generate

viernes 4 de marzo de 2011

Page 135: Doctrator Symfony Live 2011 Paris

Questions?

[email protected]

http://mondongo.es (English :)

You can contact me for Mondongo, Doctrator, consulting, development

viernes 4 de marzo de 2011