Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
Upcoming SlideShare
Program conf 2014
Program conf 2014
Loading in …3
×
1 of 135

Doctrator Symfony Live 2011 Paris

10

Share

Download to read offline

Related Books

Free with a 30 day trial from Scribd

See all

Related Audiobooks

Free with a 30 day trial from Scribd

See all

Doctrator Symfony Live 2011 Paris

  1. 1. Doctrator Pablo Díez Symfony Live 2011 - Paris viernes 4 de marzo de 2011
  2. 2. Pablo Díez Creator of Mondongo ODM for MongoDB and PHP http://mondongo.es (in English :) Creator of Mondator Class generator for PHP Creator of Doctrator http://twitter.com/pablodip http://github.com/pablodip viernes 4 de marzo de 2011
  3. 3. What is Doctrator? viernes 4 de marzo de 2011
  4. 4. Doctrator = Doctrine2 + Mondator viernes 4 de marzo de 2011
  5. 5. Agile Development viernes 4 de marzo de 2011
  6. 6. Agile Development ActiveRecord viernes 4 de marzo de 2011
  7. 7. Agile Development ActiveRecord optional viernes 4 de marzo de 2011
  8. 8. Agile Development ActiveRecord Behaviors viernes 4 de marzo de 2011
  9. 9. Agile Development ActiveRecord Behaviors Doctrator saves you a lot of time! ;) viernes 4 de marzo de 2011
  10. 10. How does Doctrine2 work? viernes 4 de marzo de 2011
  11. 11. How does Doctrine2 work? “Doctrine2 provides transparent persistence for PHP objects.” http://www.doctrine-project.org/docs/orm/2.0/en/reference/introduction.html viernes 4 de marzo de 2011
  12. 12. That is, persist PHP objects without restrictions of a base class, properties, methods. namespace Model; class User { public $id; public $username; public $email; } viernes 4 de marzo de 2011
  13. 13. You only have to tell Doctrine2 (map) what you want to persist. viernes 4 de marzo de 2011
  14. 14. You only have to tell Doctrine2 (map) what you want to persist. With Docblock Annotations /** * @Entity */ class User { /** * @Id * @Column(type="integer") */ public $id; /** * @Column(length=50) */ public $username; /** * @Column(length=100) */ public $email; } viernes 4 de marzo de 2011
  15. 15. You only have to tell Doctrine2 (map) what you want to persist. With YAML EntitiesUser: type: entity fields: id: { type: integer, id: true } username: { type: string(50) } email: { type: string(50) } viernes 4 de marzo de 2011
  16. 16. You only have to tell Doctrine2 (map) what you want to persist. With XML <?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="ModelUser" 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> viernes 4 de marzo de 2011
  17. 17. You only have to tell Doctrine2 (map) what you want to persist. With PHP $metadata->mapField(array( 'id' => true, 'fieldName' => 'id', 'type' => 'integer' )); $metadata->mapField(array( 'fieldName' => 'username', 'type' => 'string' )); $metadata->mapField(array( 'fieldName' => 'email', 'type' => 'string' )); viernes 4 de marzo de 2011
  18. 18. You only have to tell Doctrine2 (map) what you want to persist. Then you are able to persist those objects. viernes 4 de marzo de 2011
  19. 19. Then you are able to persist those objects. $user = new User(); $user->username = 'pablodip'; $user->password = 'pa$$word'; $user->email = 'pablodip@gmail.com'; $entityManager->persist($user); $entityManager->flush(); viernes 4 de marzo de 2011
  20. 20. A Doctrine2 good practice is to use non public properties in the entities. class User { protected $id; protected $username; protected $password; protected $email; } viernes 4 de marzo de 2011
  21. 21. You have to create methods to access to the properties. Setters & Getters 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
  22. 22. What do you need to work with this simple table? user id integer username string password string email string viernes 4 de marzo de 2011
  23. 23. namespace Model; class User { } Class user id integer username string password string email string viernes 4 de marzo de 2011
  24. 24. namespace Model; protected $id; class User protected $username; { protected $password; } protected $email; Class Properties user id integer username string password string email string viernes 4 de marzo de 2011
  25. 25. namespace Model; protected $id; class User protected $username; { protected $password; } protected $email; Class Properties user id integer username string public function setId($id) { } $this->id = $id; password string public function getId() { return $this->id; email string } public function setUsername($username) { $this->username = $username; Setters/Getters } public function getUsername() { return $this->username; } public function setPassword($password) { $this->password = $password; viernes 4 de marzo de 2011
  26. 26. namespace Model; protected $id; class User protected $username; { protected $password; } protected $email; Class Mapping Properties user id integer /** * @Entity username string */ public function setId($id) { /** } $this->id = $id; password string * @Id * @Column(type="integer") */ public function getId() { return $this->id; email string /** * @Column(length=50) } */ public function setUsername($username) { $this->username = $username; Setters/Getters /** * @Column(length=100) } */ public function getUsername() { return $this->username; } public function setPassword($password) { $this->password = $password; viernes 4 de marzo de 2011
  27. 27. namespace Model; /** * @Entity */ class User { /** * @Id * @Column(type="integer") */ protected $id; /** * @Column(length="50") */ protected $username; /** * @Column(length="40") */ protected $password; /** user * @Column(length="100") */ protected $email; id integer public function setId($id) { $this->id = $id; } username string public function getId() { return $this->id; password string } public function setUsername($username) { email string } $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
  28. 28. namespace Model; /** * @Entity */ class User { /** * @Id * @Column(type="integer") */ protected $id; /** * @Column(length="50") */ protected $username; /** * @Column(length="40") */ protected $password; /** user * @Column(length="100") */ protected $email; id integer public function setId($id) { $this->id = $id; LORC } username string public function getId() { return $this->id; password string } public function setUsername($username) { email string } $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
  29. 29. LORC Lines Of Repetitive Code viernes 4 de marzo de 2011
  30. 30. LORC Lines Of Repetitive Code ... and we still don’t have any features! :) viernes 4 de marzo de 2011
  31. 31. How many LORC do we need in a real database? viernes 4 de marzo de 2011
  32. 32. How many LORC do we need in a real database? ... viernes 4 de marzo de 2011
  33. 33. What does Doctrator do? viernes 4 de marzo de 2011
  34. 34. What does Doctrator do? Doctrator generates classes and maps them with Doctrine2 viernes 4 de marzo de 2011
  35. 35. Doctrator generates classes and maps them with Doctrine2 You only have to tell it the configuration of the classes. viernes 4 de marzo de 2011
  36. 36. In PHP array( 'ModelUser' => 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), ), ), ); viernes 4 de marzo de 2011
  37. 37. In YAML ModelUser: columns: id: { id: auto, type: integer } username: { type: string, length: 50 } password: { type: string, length: 40 } email: { type: string, length: 100 } viernes 4 de marzo de 2011
  38. 38. ModelUser: 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. This maps your object. class User { protected $id; protected $username; /** protected $password; * @Entity protected $email; */ public function setId($id) { $this->id = $id; } /** public function getId() * @Id { return $this->id; * @Column(type="integer") } */ public function setUsername($username) { $this->username = $username; } /** public function getUsername() * @Column(length=50) { return $this->username; */ } public function setPassword($password) { /** } $this->password = $password; * @Column(length=100) public function getPassword() */ { return $this->password; } public function setEmail($email) viernes 4 de marzo de 2011
  39. 39. ModelUser: 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 ModelUser(); $user->setUsername('pagafantas'); $user->setEmail('pagafantas@gmail.com'); $entityManager->persist($user); $entityManager->flush(); viernes 4 de marzo de 2011
  40. 40. How does Doctrator work? viernes 4 de marzo de 2011
  41. 41. How does Doctrator work? Doctrator uses Mondator to generate the classes for you. viernes 4 de marzo de 2011
  42. 42. Mondator defines PHP classes. viernes 4 de marzo de 2011
  43. 43. 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
  44. 44. namespace Model; Definition class User { Properties protected $username; public function setUsername($username) { $this->username = $username; } public function getUsername() { return $this->username; } } Methods viernes 4 de marzo de 2011
  45. 45. use MondongoMondatorDefinitionDefinition; use MondongoMondatorDefinitionProperty; use MondongoMondatorDefinitionMethod; viernes 4 de marzo de 2011
  46. 46. namespace Model; class User { } Full Class Name $definition = new Definition('ModelUser'); viernes 4 de marzo de 2011
  47. 47. protected $username; Visibility Name $property = new Property('protected', 'username'); $definition->addProperty($property); viernes 4 de marzo de 2011
  48. 48. public function setUsername($username) { $this->username = $username; } Visibility Name Arguments Code $method = new Method('public', 'setUsername', '$username', <<<EOF $this->username = $username; EOF ); $definition->addMethod($method); viernes 4 de marzo de 2011
  49. 49. You can define any PHP class. viernes 4 de marzo de 2011
  50. 50. Parent class $definition->setParentClass('ModelBaseUser'); Interfaces $definition->addInterface('ArrayAccess'); Abstract $definition->setIsAbstract(true); viernes 4 de marzo de 2011
  51. 51. Default value $property->setValue($defaultValue); Static $property->setIsStatic(true); viernes 4 de marzo de 2011
  52. 52. Abstract $method->setIsAbstract(true); Static $method->setIsStatic(true); viernes 4 de marzo de 2011
  53. 53. Even with comments. viernes 4 de marzo de 2011
  54. 54. $definition->setDocComment(<<<EOF /** * User Class. */ EOF ); $method->setDocComment(<<<EOF /** * Set the username. * * @param string $username The username. */ EOF ); viernes 4 de marzo de 2011
  55. 55. Then you can export them with the Dumper. use MondongoMondatorDumper; $dumper = new Dumper($definition); $classCode = $dumper->dump(); echo $classCode; viernes 4 de marzo de 2011
  56. 56. /** * 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
  57. 57. And save them in files. file_put_contents($file, $codeClass); viernes 4 de marzo de 2011
  58. 58. Mondator Extensions viernes 4 de marzo de 2011
  59. 59. Mondator Extensions Mondator uses extensions to generate similar classes in a powerful and flexible way. viernes 4 de marzo de 2011
  60. 60. The Mondator Extensions process the config classes to define what classes will be generated. viernes 4 de marzo de 2011
  61. 61. ModelUser: columns: id: { id: auto, type: integer } username: { type: string, length: 50 } password: { type: string, length: 40 } email: { type: string, length: 100 } The Mondator Extensions process the config classes to define what classes will be generated. MondongoMondatorDefinitionDefinition viernes 4 de marzo de 2011
  62. 62. ModelUser: columns: id: { id: auto, type: integer } username: { type: string, length: 50 } password: { type: string, length: 40 } email: { type: string, length: 100 } use MondongoMondatorExtension; class Doctrator extends Extension { protected function doClassProcess() { $this->class; $this->configClass; $this->definitions; } } viernes 4 de marzo de 2011
  63. 63. ModelUser: columns: id: { id: auto, type: integer } username: { type: string, length: 50 } password: { type: string, length: 40 } email: { type: string, length: 100 } use MondongoMondatorExtension; class Doctrator extends Extension { protected function doClassProcess() { $this->class; $this->configClass; $this->definitions; } } viernes 4 de marzo de 2011
  64. 64. ModelUser: columns: id: { id: auto, type: integer } username: { type: string, length: 50 } password: { type: string, length: 40 } email: { type: string, length: 100 } use MondongoMondatorExtension; class Doctrator extends Extension { protected function doClassProcess() { $this->class; $this->configClass; $this->definitions; } } viernes 4 de marzo de 2011
  65. 65. ModelUser: columns: id: { id: auto, type: integer } username: { type: string, length: 50 } password: { type: string, length: 40 } email: { type: string, length: 100 } use MondongoMondatorExtension; class Doctrator extends Extension { protected function doClassProcess() { $this->class; $this->configClass; $this->definitions; } } Definitions to generate viernes 4 de marzo de 2011
  66. 66. An extension can generate any definition. viernes 4 de marzo de 2011
  67. 67. use MondongoMondatorExtension; use MondongoMondatorDefinitionDefinition; 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
  68. 68. foreach ($this->configClass['columns'] as $name => $column) { $property = new Property('protected', $name); $this->definitions['entity']->addProperty($property); } viernes 4 de marzo de 2011
  69. 69. 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
  70. 70. Different extensions can modify the same definition. viernes 4 de marzo de 2011
  71. 71. 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
  72. 72. An extension can have options. viernes 4 de marzo de 2011
  73. 73. 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
  74. 74. You can process the extensions that you want. viernes 4 de marzo de 2011
  75. 75. $mondator = new MondongoMondatorMondator(); $mondator->setConfigClasses($configClasses); $mondator->setExtensions(array( new DoctratorExtensionCore($options), new DoctratorExtensionArrayAccess(), )); $mondator->process(); $article['title'] = 'Doctrator'; echo $article['title']; // Doctrator viernes 4 de marzo de 2011
  76. 76. $mondator = new MondongoMondatorMondator(); $mondator->setConfigClasses($configClasses); $mondator->setExtensions(array( new DoctratorExtensionCore($options), //new DoctratorExtensionArrayAccess(), )); $mondator->process(); $article['title'] = 'Doctrator'; echo $article['title']; // Doctrator viernes 4 de marzo de 2011
  77. 77. An extension can change the config class to extend another extension. viernes 4 de marzo de 2011
  78. 78. 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
  79. 79. You can even use extensions in the config classes. viernes 4 de marzo de 2011
  80. 80. ModelArticle: columns: id: { id: auto, type: integer } title: { type: string, length: 100 } behaviors: - class: DoctratorBehaviorTimestampable options: { } viernes 4 de marzo de 2011
  81. 81. And you can combine all these things to do what you want. viernes 4 de marzo de 2011
  82. 82. Generated code is not necessarily magic code. viernes 4 de marzo de 2011
  83. 83. Doctrator Extensions viernes 4 de marzo de 2011
  84. 84. Doctrator Extensions Core ArrayAccess PropertyOverloading ActiveRecord Behaviors viernes 4 de marzo de 2011
  85. 85. Core Generates and maps objects with Doctrine2. viernes 4 de marzo de 2011
  86. 86. Doctrator uses base classes to separate generated code from your code. viernes 4 de marzo de 2011
  87. 87. ModelUser namespace Model; class User extends ModelBaseUser { // your code } namespace ModelBase; class User { // generated code } viernes 4 de marzo de 2011
  88. 88. ModelArticle: 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: ModelCategory, inversed: articles } indexes: slug: { columns: ['slug'], unique: true } date: { columns: ['is_active', 'date'] } events: preUpdate: ['updateDate'] viernes 4 de marzo de 2011
  89. 89. Associations ModelArticle: table_name: articles one_to_one one_to_many columns: many_to_one id: { id: auto,many_to_many type: integer } title: { type: string, length: 100 } slug: { type: string, length: 100 } name content: { type: string class } mapped is_active: { type: boolean, default: true } date: { type: date }inversed many_to_one: category: { class: ModelCategory, inversed: articles } indexes: slug: { columns: ['slug'], unique: true } date: { columns: ['is_active', 'date'] } events: preUpdate: ['updateDate'] viernes 4 de marzo de 2011
  90. 90. ModelArticle: Events table_name: articles columns: prePersist id: { id: auto, type: integer } postPersist title: { type: string, length: 100 } preUpdate slug: postUpdate { type: string, length: 100 } preRemove content: { type: string } postRemove is_active: { type: boolean, default: true } postLoad date: { type: date } many_to_one: category: { class: ModelCategory, inversed: articles } indexes: slug: { columns: ['slug'], unique: true } date: { columns: ['is_active', 'date'] } events: preUpdate: ['updateDate'] viernes 4 de marzo de 2011
  91. 91. $category = new ModelCategory(); $category->setName('Class Generator'); $entityManager->persist($category); $article = new ModelArticle(); $article->setTitle('Doctrator'); $article->setDate(new DateTime('now')); $article->setCategory($category); $entityManager->persist($article); $entityManager->flush(); viernes 4 de marzo de 2011
  92. 92. Core Useful methods. viernes 4 de marzo de 2011
  93. 93. Set & Get by string $article->set('title', 'Doctrator'); echo $article->get('title'); // Doctrator viernes 4 de marzo de 2011
  94. 94. fromArray & toArray $article->fromArray(array( 'title' => 'Doctrator', 'date' => new DateTime('now') )); $array = $article->toArray(); viernes 4 de marzo de 2011
  95. 95. ArrayAccess Implements the ArrayAccess interface in the entities. viernes 4 de marzo de 2011
  96. 96. $article = new ModelArticle(); $article['title'] = 'Doctrator'; echo $article['title']; // Doctrator viernes 4 de marzo de 2011
  97. 97. PropertyOverloading Allows you access to entity data like properties. viernes 4 de marzo de 2011
  98. 98. $article = new ModelArticle(); $article->title = 'Doctrator'; echo $article->title; // Doctrator viernes 4 de marzo de 2011
  99. 99. ActiveRecord Implements the ActiveRecord pattern in your entities. viernes 4 de marzo de 2011
  100. 100. $article = new ModelArticle(); $article->setTitle('Doctrator'); $article->save(); $article->refresh(); $article->delete(); viernes 4 de marzo de 2011
  101. 101. print_r($article); viernes 4 de marzo de 2011
  102. 102. print_r($article); ModelArticle Object ( [id:protected] => 1 [title:protected] => Doctrator [content:protected] => Rocks! ) Doctrator entities are clean even with ActiveRecord! viernes 4 de marzo de 2011
  103. 103. $em = ModelArticle::entityManager(); $articleRepository = ModelArticle::repository(); $queryBuilder = ModelArticle::queryBuilder(); viernes 4 de marzo de 2011
  104. 104. $articles = $entityManager->getRepository('Model Article')->findAll(); $article = $entityManager->getRepository('Model Article')->find($id); $articles = ModelArticle::repository()->findAll(); $article = ModelArticle::repository()->find($id); viernes 4 de marzo de 2011
  105. 105. Behaviors viernes 4 de marzo de 2011
  106. 106. Behaviors Reuse features. viernes 4 de marzo de 2011
  107. 107. A behavior is simply a Mondator extension. viernes 4 de marzo de 2011
  108. 108. A behavior can Have options Change config classes: • Columns • Associations • Indexes • Events • ... Add new generated classes Add properties and methods • Entities • Repositories • ... viernes 4 de marzo de 2011
  109. 109. Timestampable Saves the created and updated date. created TRUE created_column created_at updated TRUE updated_column updated_at viernes 4 de marzo de 2011
  110. 110. ModelArticle: columns: id: { id: auto, type: integer } title: { type: name, length: 100 } behaviors: - DoctratorBehaviorTimestampable viernes 4 de marzo de 2011
  111. 111. $article = new ModelArticle(); $article->setTitle('Doctrator'); $article->save(); echo $article->getCreatedAt(); // now echo $article->getUpdatedAt(); // null $article->setContent('Rocks!'); $article->save(); echo $article->getCreatedAt(); // before echo $article->getUpdatedAt(); // now viernes 4 de marzo de 2011
  112. 112. Ipable Saves the created and updated ip. created TRUE created_column created_from updated TRUE updated_column updated_from viernes 4 de marzo de 2011
  113. 113. Hashable Ipable Saves a unique hash in each entity. column hash viernes 4 de marzo de 2011
  114. 114. ModelArticle: columns: id: { id: auto, type: integer } title: { type: name, length: 100 } behaviors: - DoctratorBehaviorHashable viernes 4 de marzo de 2011
  115. 115. $article = new Article(); $article->setTitle('Doctrator'); $entityManager->persist(); $entityManager->flush(); echo $article->getHash(); // da39a3ee5e6b4b0d3255bfef95601890afd80709 viernes 4 de marzo de 2011
  116. 116. Timestampable Sluggable Saves a slug from a field. from_column * slug_column slug unique TRUE update FALSE viernes 4 de marzo de 2011
  117. 117. ModelArticle: columns: id: { id: auto, type: integer } title: { type: name, length: 100 } behaviors: - class: DoctratorBehaviorSluggable options: { from_column: title } viernes 4 de marzo de 2011
  118. 118. $article = new ModelArticle(); $article->setTitle('Doctrator Rocks!'); $article->save(); echo $article->getSlug(); // doctrator-rocks viernes 4 de marzo de 2011
  119. 119. Sortable Allows you to sort your entities. column position new_position bottom viernes 4 de marzo de 2011
  120. 120. $articles = array(); for ($i = 0; $i <= 10; $i++) { $articles[$i] = $a = new ModelArticle(); $a->setTitle('Article '.$i); $a->save(); } echo $articles[3]->getPosition(); // 3 echo $articles[6]->getPosition(); // 6 viernes 4 de marzo de 2011
  121. 121. // 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
  122. 122. Taggable Sortable Allows you to save tags in the entities. viernes 4 de marzo de 2011
  123. 123. $article = new ModelArticle(); $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
  124. 124. Translatable Taggable Sortable Allows you to translate entity columns. columns * viernes 4 de marzo de 2011
  125. 125. ModelArticle: columns: id: { id: auto, type: integer } title: { type: string, length: 100 } content: { type: string } date: { type: date } behaviors: - class: DoctratorBehaviorTranslatable options: { columns: ['title', 'content'] } viernes 4 de marzo de 2011
  126. 126. $article = new ModelArticle(); $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
  127. 127. Doctrator in Symfony2 viernes 4 de marzo de 2011
  128. 128. DoctratorBundle viernes 4 de marzo de 2011
  129. 129. doctrator.config: extensions: array_access: false property_overloading: false active_record: true behaviors: true validation: true viernes 4 de marzo de 2011
  130. 130. 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
  131. 131. Config Classes app/config/doctrator/*.yml *Bundle/Resources/doctrator/*.yml viernes 4 de marzo de 2011
  132. 132. Standard Namespace ModelArticle: columns: id: { id: auto, type: integer } title: { type: string, length: 100 } content: { type: string } ModelDoctratorUserBundleUser: columns: id: { id: auto, type: integer } username: { type: string, length: 20 } viernes 4 de marzo de 2011
  133. 133. ModelArticle: 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
  134. 134. php app/console doctrator:generate viernes 4 de marzo de 2011
  135. 135. Questions? http://mondongo.es (English :) You can contact me for Mondongo, Doctrator, consulting, development pablodip@gmail.com viernes 4 de marzo de 2011

×