Karsten Dambekalns       Persistence in FLOW3            with Doctrine 2               FLOW3 Experience 2012              ...
Karsten Dambekalnsco-lead of TYPO3 5.0 and FLOW334 years oldlives in Lübeck, Germany1 wife, 3 sons, 1 espresso machinelike...
Persistence in FLOW3 with Doctrine 2Object Persistence in the Flow • Based on Doctrine 2 • Seamless integration into FLOW3...
Basic Object Persistence    • Get your repository injected conveniently    • Handle your objects (almost) like you had no ...
Persistence in FLOW3 with Doctrine 2Differences to plain Doctrine 2 in modeling• Identifier properties are added transparen...
Purely Doctrine 2       use DoctrineORMMapping as ORM;       /**        * @ORMEntity(repositoryClass="BugRepository")     ...
Doctrine 2 in FLOW3       use DoctrineORMMapping as ORM;       /**        * @ORMEntity(repositoryClass="BugRepository")   ...
Purely Doctrine 2     /**      * @var DateTime      * @ORMColumn(type="datetime")      */     protected $created;     /** ...
Doctrine 2 in FLOW3     /**      * @var DateTime      * @ORMColumn(type="datetime")      */     protected $created;     /*...
Using RepositoriesChoose between the generic base repository to support any backend orthe Doctrine base repository to acce...
Advanced Queries using the QOMPostRepository.phpclass PostRepository extends FLOW3PersistenceRepository {	   /**	    * Fin...
Advanced Queries using DQLPostRepository.phpclass PostRepository extends FLOW3PersistenceDoctrineRepository {	 /**	   * Fi...
Modeling Associations• Modeling associations is hard for many people• Start with the model, not the data• Read the Doctrin...
Modeling AssociationsHow FLOW3 helps you with associations• Cascade attributes are managed by FLOW3 • based on aggregate b...
Schema ManagementDoctrine 2 Migrations• Migrations allow schema versioning  and change deployment• Migrations are the reco...
Schema ManagementMigrations Workflow• Develop until your model is ready for a first “freeze”• Create a migration and move / ...
Schema ManagementMigration files are usually very simple code/** * Rename FLOW3 tables to follow FQCN */class Version201108...
Schema ManagementChecking the migration status on the console$ ./flow3 doctrine:migrationstatus == Configuration    >> Nam...
Schema ManagementMigrations Workflow• Rinse and repeat: from now on create a new migration whenever  you changed your model...
Schema ManagementManual database updates• For simple situations this can be good enough:$ ./flow3 doctrine:create$ ./flow3...
Integrating existing database tablesUse existing data from TYPO3 or other applicationsTwo principal approaches • Accessing...
Mapping fe_users to a model      /**       * @FLOW3Entity       * @ORMTable(name=”fe_users”)       */      class FrontendU...
Mapping fe_users to a model      	 /**      	  * @var string      	  */      	 protected $username;      	 /**      	  * @...
Integrating existing database tablesPitfalls • Migrations will try to drop existing tables and columns! • Data type mismat...
Persistence in FLOW3 with Doctrine 2       Questions?                                       25
Thank You! • These slides can be found at:   http://speakerdeck.com/u/kdambekalns | http://slideshare.net/kfish • Give me f...
Upcoming SlideShare
Loading in …5
×

Doctrine in FLOW3

6,322 views

Published on

Presentation given at F3X 2012 on the integration of Doctrine 2 into the PHP framework FLOW3.

Published in: Technology, Business
0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
6,322
On SlideShare
0
From Embeds
0
Number of Embeds
512
Actions
Shares
0
Downloads
26
Comments
0
Likes
2
Embeds 0
No embeds

No notes for slide

Doctrine in FLOW3

  1. 1. Karsten Dambekalns Persistence in FLOW3 with Doctrine 2 FLOW3 Experience 2012 1
  2. 2. Karsten Dambekalnsco-lead of TYPO3 5.0 and FLOW334 years oldlives in Lübeck, Germany1 wife, 3 sons, 1 espresso machinelikes canoeing and climbing 2
  3. 3. Persistence in FLOW3 with Doctrine 2Object Persistence in the Flow • Based on Doctrine 2 • Seamless integration into FLOW3 • Provides the great Doctrine 2 features • Uses UUIDs • Our low-level persistence API • Allows for own, custom persistence backends (instead of Doctrine 2) • CouchDB is supported natively 3
  4. 4. Basic Object Persistence • Get your repository injected conveniently • Handle your objects (almost) like you had no framework // Create a new customer and persist it: $customer = new Customer("Robert"); $this->customerRepository->add($customer); // Update a customer: $customer->setName("I, Robot"); $this->customerRepository->update($customer); // Find an existing customer: $otherCustomer = $this->customerRepository->findByFirstName("Karsten"); // … and delete it: $this->customerRepository->remove($otherCustomer); 4
  5. 5. Persistence in FLOW3 with Doctrine 2Differences to plain Doctrine 2 in modeling• Identifier properties are added transparently• FLOW3 does autodetection for • repository class names, column types, referenced column names • target entity types, cascade attributes• All Doctrine annotations work as usual • Whatever you specify wins over automation • Allows for full flexibility 5
  6. 6. Purely Doctrine 2 use DoctrineORMMapping as ORM; /** * @ORMEntity(repositoryClass="BugRepository") */ class Bug { /** * @var integer * @ORMId * @ORMColumn(type="integer") * @ORMGeneratedValue */ protected $id; /** * @var string * @ORMColumn(type="string") */ protected $description; /** * @var DateTime * @ORMColumn(type="datetime") */ 6
  7. 7. Doctrine 2 in FLOW3 use DoctrineORMMapping as ORM; /** * @ORMEntity(repositoryClass="BugRepository") */ class Bug { /** * @var integer * @ORMId * @ORMColumn(type="integer") * @ORMGeneratedValue */ protected $id; /** * @var string * @ORMColumn(type="string") */ protected $description; /** * @var DateTime * @ORMColumn(type="datetime") */ 7
  8. 8. Purely Doctrine 2 /** * @var DateTime * @ORMColumn(type="datetime") */ protected $created; /** * @var ExampleUser * @ORMManyToOne(targetEntity="ExampleUser", inversedBy="assignedBugs") */ protected $engineer; /** * @var DoctrineCommonCollectionsCollection<ExampleProduct> * @ORMManyToMany(targetEntity="ExampleProduct") */ protected $products; } 8
  9. 9. Doctrine 2 in FLOW3 /** * @var DateTime * @ORMColumn(type="datetime") */ protected $created; /** * @var ExampleUser * @ORMManyToOne(targetEntity="ExampleUser", inversedBy="assignedBugs") */ protected $engineer; /** * @var DoctrineCommonCollectionsCollection<ExampleProduct> * @ORMManyToMany(targetEntity="ExampleProduct") */ protected $products; } 9
  10. 10. Using RepositoriesChoose between the generic base repository to support any backend orthe Doctrine base repository to access advanced Doctrine functionality.Extending the base repositories of FLOW3 • Provides basic methods like: findAll(), countAll(), remove(), removeAll() • Provides automatic finder methods to retrieve by property: findByPropertyName($value), findOneByPropertyName($value)Add specialized finder methods to your own repository. 10
  11. 11. Advanced Queries using the QOMPostRepository.phpclass PostRepository extends FLOW3PersistenceRepository { /** * Finds most recent posts excluding the given post * * @param TYPO3BlogDomainModelPost $post Post to exclude from result * @param integer $limit The number of posts to return at max * @return array All posts of the $posts blog except for $post */ public function findRecentExceptThis(TYPO3BlogDomainModelPost $post, $limit = 20) { $query = $this->createQuery(); $posts = $query->matching($query->equals(blog, $post->getBlog())) ->setOrderings(array( date => TYPO3FLOW3PersistenceQueryInterface::ORDER_DESCENDING )) ->setLimit($limit) ->execute() ->toArray(); unset($posts[array_search($post, $posts)]); return $posts; }} 11
  12. 12. Advanced Queries using DQLPostRepository.phpclass PostRepository extends FLOW3PersistenceDoctrineRepository { /** * Finds most recent posts excluding the given post * * @param TYPO3BlogDomainModelPost $post Post to exclude from result * @param integer $limit The number of posts to return at max * @return array All posts of the $posts blog except for $post */ public function findRecentExceptThis(TYPO3BlogDomainModelPost $post, $limit = 20) { // this is an alternative way of doing this when extending the Doctrine 2 // specific repository and using DQL. $query = $this->entityManager->createQuery(SELECT p FROM TYPO3BlogDomainModelPost p WHERE p.blog = :blog AND NOT p= :excludedPost ORDER BY p.date DESC); return $query ->setMaxResults($limit) ->execute(array(blog => $post->getBlog(), excludedPost => $post)); }} 12
  13. 13. Modeling Associations• Modeling associations is hard for many people• Start with the model, not the data• Read the Doctrine documentation on associations• Put a printed list of possible association on your wall• Always remember: The owning side of a relationship determines the updates to the relationship in the database 13
  14. 14. Modeling AssociationsHow FLOW3 helps you with associations• Cascade attributes are managed by FLOW3 • based on aggregate boundaries• Target entity can be left out• Join columns and tables have automagic defaults • No, not only if your identifier column is named id• Check your mapping with flow3 doctrine:validateAll magic can be overridden by using annotations! 14
  15. 15. Schema ManagementDoctrine 2 Migrations• Migrations allow schema versioning and change deployment• Migrations are the recommended way for schema updates• Can also be used to deploy predefined and update existing data• Tools to create and deploy migrations are integrated with FLOW3 15
  16. 16. Schema ManagementMigrations Workflow• Develop until your model is ready for a first “freeze”• Create a migration and move / check / customize it$ ./flow3 doctrine:migrationgenerateGenerated new migration class!Next Steps:- Move /…/DoctrineMigrations/Version20120328152041.php to YourPackage/Migrations/Mysql/- Review and adjust the generated migration.- (optional) execute the migration using ./flow3 doctrine:migrate• Migrate to create the tables$ ./flow3 doctrine:migrate 16
  17. 17. Schema ManagementMigration files are usually very simple code/** * Rename FLOW3 tables to follow FQCN */class Version20110824124835 extends AbstractMigration { /** * @param Schema $schema * @return void */ public function up(Schema $schema) { $this->abortIf($this->connection->getDatabasePlatform()->getName() != "mysql"); $this->addSql("RENAME TABLE flow3_policy_role TO typo3_flow3_security_policy_role"); $this->addSql("RENAME TABLE flow3_resource_resource TO typo3_flow3_resource_resource"); $this->addSql("RENAME TABLE flow3_resource_resourcepointer TOtypo3_flow3_resource_resourcepointer"); $this->addSql("RENAME TABLE flow3_resource_securitypublishingconfiguration TOtypo3_flow3_security_authorization_resource_securitypublis_6180a"); $this->addSql("RENAME TABLE flow3_security_account TO typo3_flow3_security_account"); } 17
  18. 18. Schema ManagementChecking the migration status on the console$ ./flow3 doctrine:migrationstatus == Configuration >> Name: Doctrine Database Migrations >> Database Driver: pdo_mysql >> Database Name: blog >> Configuration Source: manually configured >> Version Table Name: flow3_doctrine_migrationstatus >> Migrations Namespace: TYPO3FLOW3PersistenceDoctrineMigrations >> Migrations Directory: /…/Configuration/Doctrine/Migrations >> Current Version: 2011-06-08 07:43:24 (20110608074324) >> Latest Version: 2011-06-08 07:43:24 (20110608074324) >> Executed Migrations: 1 >> Available Migrations: 1 >> New Migrations: 0 == Migration Versions >> 2011-06-08 07:43:24 (20110608074324) migrated 18
  19. 19. Schema ManagementMigrations Workflow• Rinse and repeat: from now on create a new migration whenever you changed your model classes• Generated migrations most probably need to be adjusted: • Renaming a model means renaming a table, not dropping and creating • Data migration might need to be added • Sometimes the generated changes are useless Good migrations make your user’s day 19
  20. 20. Schema ManagementManual database updates• For simple situations this can be good enough:$ ./flow3 doctrine:create$ ./flow3 doctrine:update• Useful when • You need to use an existing database dump • No migrations exist for your database of choice (send patches!) • Using SQLite (due to limited schema change functionality) 20
  21. 21. Integrating existing database tablesUse existing data from TYPO3 or other applicationsTwo principal approaches • Accessing raw data in a specialized repository • Use your own database connection and SQL • Does not use the default persistence layer • Creating a clean model mapped to the existing structure • FLOW3 will use the same database as the existing application • Uses the default persistence layer 21
  22. 22. Mapping fe_users to a model /** * @FLOW3Entity * @ORMTable(name=”fe_users”) */ class FrontendUser { /** * @var integer * @ORMId * @ORMColumn(name="uid") * @ORMGeneratedValue */ protected $identifier; /** * @var string */ protected $username; 22
  23. 23. Mapping fe_users to a model /** * @var string */ protected $username; /** * @var string * @ORMColumn(name="first_name") */ protected $firstName; /** * @var DoctrineCommonCollectionsCollection<My ExampleFrontendUserGroup> * @ORMManyToMany(mappedBy="users") * @ORMJoinTable(name="user_groups_mm", …) */ protected $groups; 23
  24. 24. Integrating existing database tablesPitfalls • Migrations will try to drop existing tables and columns! • Data type mismatches break FK constraints • integer vs. unsigned integer • Real data can be bad data • No FK constraints on legacy data • Missing entries break associations • Watch out for specifics like deleted and hidden flags 24
  25. 25. Persistence in FLOW3 with Doctrine 2 Questions? 25
  26. 26. Thank You! • These slides can be found at: http://speakerdeck.com/u/kdambekalns | http://slideshare.net/kfish • Give me feedback: karsten@typo3.org | karsten@dambekalns.de • Download FLOW3: http://flow3.typo3.org • Follow me on twitter: @kdambekalns • Support me using 26

×