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
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); • Get your repository injected conveniently • Handle your objects (almost) like you had no framework 4
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
any backend or the 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
/** * Finds most recent posts excluding the given post * * @param \TYPO3\Blog\Domain\Model\Post $post Post to exclude from result * @param integer $limit The number of posts to return at max * @return array All posts of the $post's blog except for $post */ public function findRecentExceptThis(\TYPO3\Blog\Domain\Model\Post $post, $limit = 20) { $query = $this->createQuery(); $posts = $query->matching($query->equals('blog', $post->getBlog())) ->setOrderings(array( 'date' => \TYPO3\FLOW3\Persistence\QueryInterface::ORDER_DESCENDING )) ->setLimit($limit) ->execute() ->toArray(); unset($posts[array_search($post, $posts)]); return $posts; } } PostRepository.php 11
* Finds most recent posts excluding the given post * * @param \TYPO3\Blog\Domain\Model\Post $post Post to exclude from result * @param integer $limit The number of posts to return at max * @return array All posts of the $post's blog except for $post */ public function findRecentExceptThis(\TYPO3\Blog\Domain\Model\Post $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 \TYPO3\Blog\Domain\Model\Post 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)); } } PostRepository.php 12
• 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
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:validate All magic can be overridden by using annotations! 14
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
ready for a first “freeze” • Create a migration and move / check / customize it • Migrate to create the tables $ ./flow3 doctrine:migrationgenerate Generated 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 $ ./flow3 doctrine:migrate 16
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
can be good enough: • 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) $ ./flow3 doctrine:create $ ./flow3 doctrine:update 20
other applications Two 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
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
| http://slideshare.net/kfish • Give me feedback: [email protected] | [email protected] • Download FLOW3: http://flow3.typo3.org • Follow me on twitter: @kdambekalns • Support me using 26