1. Karsten Dambekalns
Persistence in FLOW3
with Doctrine 2
FLOW3 Experience 2012
1
2. Karsten Dambekalns
co-lead of TYPO3 5.0 and FLOW3
34 years old
lives in Lübeck, Germany
1 wife, 3 sons, 1 espresso machine
likes canoeing and climbing
2
3. Persistence in FLOW3 with Doctrine 2
Object 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. 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. Persistence in FLOW3 with Doctrine 2
Differences 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
10. Using Repositories
Choose between the generic base repository to support 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
11. Advanced Queries using the QOM
PostRepository.php
class 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 $post's 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. Advanced Queries using DQL
PostRepository.php
class 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 $post's 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. 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. Modeling Associations
How 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:validate
All magic can be overridden by using annotations!
14
15. Schema Management
Doctrine 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. Schema Management
Migrations Workflow
• Develop until your model is ready for a first “freeze”
• Create a migration and move / check / customize it
$ ./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
• Migrate to create the tables
$ ./flow3 doctrine:migrate
16
17. Schema Management
Migration 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 TO
typo3_flow3_resource_resourcepointer");
$this->addSql("RENAME TABLE flow3_resource_securitypublishingconfiguration TO
typo3_flow3_security_authorization_resource_securitypublis_6180a");
$this->addSql("RENAME TABLE flow3_security_account TO typo3_flow3_security_account");
}
17
18. Schema Management
Checking 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. Schema Management
Migrations 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. Schema Management
Manual 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. Integrating existing database tables
Use existing data from TYPO3 or 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
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
24. Integrating existing database tables
Pitfalls
• 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
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