Doctrator Symfony Live 2011 Paris

5,753 views

Published on

Published in: Technology
0 Comments
10 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
5,753
On SlideShare
0
From Embeds
0
Number of Embeds
3,377
Actions
Shares
0
Downloads
95
Comments
0
Likes
10
Embeds 0
No embeds

No notes for slide

Doctrator Symfony Live 2011 Paris

  1. 1. Doctrator Pablo Díez Symfony Live 2011 - Parisviernes 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/pablodipviernes 4 de marzo de 2011
  3. 3. What is Doctrator?viernes 4 de marzo de 2011
  4. 4. Doctrator = Doctrine2 + Mondatorviernes 4 de marzo de 2011
  5. 5. Agile Developmentviernes 4 de marzo de 2011
  6. 6. Agile Development ActiveRecordviernes 4 de marzo de 2011
  7. 7. Agile Development ActiveRecord optionalviernes 4 de marzo de 2011
  8. 8. Agile Development ActiveRecord Behaviorsviernes 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.htmlviernes 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 stringviernes 4 de marzo de 2011
  23. 23. namespace Model; class User { } Class user id integer username string password string email stringviernes 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 stringviernes 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 Codeviernes 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 Doctrine2viernes 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; } } Methodsviernes 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 Extensionsviernes 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. MondongoMondatorDefinitionDefinitionviernes 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 generateviernes 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]; // Doctratorviernes 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]; // Doctratorviernes 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 Extensionsviernes 4 de marzo de 2011
  84. 84. Doctrator Extensions Core ArrayAccess PropertyOverloading ActiveRecord Behaviorsviernes 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); // Doctratorviernes 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]; // Doctratorviernes 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; // Doctratorviernes 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. Behaviorsviernes 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_atviernes 4 de marzo de 2011
  110. 110. ModelArticle: columns: id: { id: auto, type: integer } title: { type: name, length: 100 } behaviors: - DoctratorBehaviorTimestampableviernes 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(); // nowviernes 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_fromviernes 4 de marzo de 2011
  113. 113. Hashable Ipable Saves a unique hash in each entity. column hashviernes 4 de marzo de 2011
  114. 114. ModelArticle: columns: id: { id: auto, type: integer } title: { type: name, length: 100 } behaviors: - DoctratorBehaviorHashableviernes 4 de marzo de 2011
  115. 115. $article = new Article(); $article->setTitle(Doctrator); $entityManager->persist(); $entityManager->flush(); echo $article->getHash(); // da39a3ee5e6b4b0d3255bfef95601890afd80709viernes 4 de marzo de 2011
  116. 116. Timestampable Sluggable Saves a slug from a field. from_column * slug_column slug unique TRUE update FALSEviernes 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-rocksviernes 4 de marzo de 2011
  119. 119. Sortable Allows you to sort your entities. column position new_position bottomviernes 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(); // 6viernes 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 Symfony2viernes 4 de marzo de 2011
  128. 128. DoctratorBundleviernes 4 de marzo de 2011
  129. 129. doctrator.config: extensions: array_access: false property_overloading: false active_record: true behaviors: true validation: trueviernes 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: trueviernes 4 de marzo de 2011
  131. 131. Config Classes app/config/doctrator/*.yml *Bundle/Resources/doctrator/*.ymlviernes 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 integratedviernes 4 de marzo de 2011
  134. 134. php app/console doctrator:generateviernes 4 de marzo de 2011
  135. 135. Questions? http://mondongo.es (English :) You can contact me for Mondongo, Doctrator, consulting, development pablodip@gmail.comviernes 4 de marzo de 2011

×