Advertisement

Symfony2 and Doctrine2 Integration

Consultant at Sensio Labs
Jun. 23, 2010
Advertisement

More Related Content

Advertisement

Symfony2 and Doctrine2 Integration

  1. Symfony and Doctrine What’s new in the Symfony and Doctrine Integration Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  2. Updated DoctrineBundle • Doctrine2 features fully integrated – Database Abstraction Layer – Object Relational Mapper Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  3. DoctrineMongoDBBundle • MongoDB Object Document Mapper – Transparent persistence to MongoDB – Same architecture as ORM – Map a class as an entity and document Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  4. DoctrineMigrationsBundle • Integration with the database migrations project. • Easily manage and deploy different versions of your database. • Generate migrations when you change your schema mapping information Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  5. DBAL • To use just the DBAL you must configure it: doctrine.dbal: dbname: Symfony user: root password: ~ Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  6. DBAL • If you need to specify multiple connections you can use the following syntax: doctrine.dbal: default_connection: default connections: default: driver: PDOSqlite dbname: Symfony user: root password: null host: localhost port: ~ path: %kernel.data_dir%/symfony.sqlite event_manager_class: DoctrineCommonEventManager configuration_class: DoctrineDBALConfiguration wrapper_class: ~ options: [] Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  7. DBAL Console Commands • Create all configured databases $ php console doctrine:database:create • Create a specific database $ php console doctrine:database:create --connection=default • Drop all configured databases $ php console doctrine:database:drop • Drop a specific database $ php console doctrine:database:drop --connection=default Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  8. DBAL Console Commands • Execute SQL queries $ php console doctrine:query:sql “SELECT * FROM user” • Specify connection $ php console doctrine:query:sql “...” --connection=default Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  9. DBAL • Get the default configured database connection: class MyController extends DoctrineController { public function indexAction() { $conn = $this->getDatabaseConnection(); // ... } } Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  10. DBAL • Get a configured database connection service by its name: class MyController extends DoctrineController { public function indexAction() { $conn = $this->getDatabaseConnection('default'); // ... } } Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  11. ORM • The EntityManager • Central place for persisting and retrieving entities • Multiple instances allowed • One EntityManager per database connection $config = new DoctrineORMConfiguration(); $config->setMetadataCacheImpl(new DoctrineCommonCacheArrayCache); $driverImpl = $config->newDefaultAnnotationDriver(array(__DIR__."/Entities")); $config->setMetadataDriverImpl($driverImpl); $config->setProxyDir(__DIR__ . '/Proxies'); $config->setProxyNamespace('Proxies'); $connectionOptions = array( 'driver' => 'pdo_sqlite', 'path' => 'database.sqlite' ); $em = DoctrineORMEntityManager::create($connectionOptions, $config); • Dependency Injection handles the creation and management of entity manager services Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  12. ORM • What is an Entity? It is a regular PHP object that has been mapped to the Doctrine2 ORM: /** @Entity */ class User { /** * @Id @Column(type="integer") * @GeneratedValue */ private $id; /** @Column(type="string", length=255) */ private $name; public function getId() { return $this->id; } public function getName() { return $this->name; } public function setName($name) { $this->name = $name; } } Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  13. ORM • No more magic in your domain • Clean and testable • Fast! • Only limited by what you can do with PHP OO to design your domain • Inheritance • Use __construct() without any problems • Entities are persisted transparently by the EntityManager Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  14. ORM • Configure an entity manager to start using the ORM: doctrine.orm: default_entity_manager: default cache_driver: apc # array, apc, memcache, xcache entity_managers: default: connection: default Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  15. ORM • Console commands implemented for improved developer workflow: Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  16. ORM • Console commands implemented for improved developer workflow: • Ensure production settings • Clear metadata, query and result cache • Load data fixtures • Create and drop configured databases • Generate entities from mapping information • Generate new skeleton entities • Generate skeleton entity repository classes • Convert mapping information between formats • Convert a Doctrine1 schema • Import mapping information from an existing database • Execute DQL and SQL queries • Create, drop and update database schema from mapping information Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  17. ORM • Get the default configured entity manager service: class MyController extends DoctrineController { public function indexAction() { $em = $this->getEntityManager(); // ... } } Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  18. ORM • Get a configured entity manager service by its name: class MyController extends DoctrineController { public function indexAction() { $em = $this->getEntityManager('default'); // ... } } Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  19. ORM • Persisting entities is as simple as creating the object and telling Doctrine to persist it: class MyController extends DoctrineController { public function createAction() { $em = $this->getEntityManager(); $user = new User(); $user->setName('Jonathan H. Wage'); $em->persist($user); $em->flush(); // ... } } Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  20. ORM • Creating Query instances and issue DQL queries to retrieve objects: class MyController extends DoctrineController { public function indexAction() { $em = $this->getEntityManager(); $query = $em->createQuery('select u from MyBundle:User u'); $users = $query->execute(); // ... } } Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  21. ORM • Creating QueryBuilder instances to programatically build DQL queries through a fluent interface: class MyController extends DoctrineController { public function indexAction() { $em = $this->getEntityManager(); $qb = $em->createQueryBuilder() ->select('u') ->from('MyBundle:User', 'u'); $query = $qb->getQuery(); $users = $query->execute(); // ... } } Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  22. ORM • Update your database schema during development as your domain model evolves • Add a new column to our User entity /** @Entity */ class User { // ... /** @Column(type="string", length=255) */ private $email; } Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  23. ORM • Run update command to update your database schema from mapping information $ php console doctrine:schema:update • The above compares your current database schema to your new mapping information and executes the necessary queries to bring your database up-to-date. Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  24. Object Document Mapper • New Doctrine Project for persisting objects to MongoDB • Same architecture as ORM • Transparently persist PHP5 objects to MongoDB Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  25. MongoDB ODM • The DocumentManager • Central place for persisting and retrieving documents • Multiple instances allowed $config = new Configuration(); $config->setProxyDir(__DIR__ . '/Proxies'); $config->setProxyNamespace('Proxies'); $config->setDefaultDB('doctrine_odm_sandbox'); $reader = new AnnotationReader(); $reader->setDefaultAnnotationNamespace('DoctrineODMMongoDBMapping'); $config->setMetadataDriverImpl(new AnnotationDriver($reader, __DIR__ . '/Documents')); $dm = DocumentManager::create(new Mongo(), $config); • Dependency Injection handles the creation and management of document manager services Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  26. MongoDB ODM • To use the MongoDB ODM you must configure it: doctrine_odm.mongodb: default_document_manager: default cache_driver: array document_managers: default: connection: mongodb connections: mongodb: server: localhost/somedatabase Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  27. MongoDB ODM • If the defaults are good enough for you then you can omit all the previous options: doctrine_odm.mongodb: ~ Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  28. MongoDB ODM • What is a Document? It is a regular PHP object that has been mapped to the MongoDB ODM: /** @Document */ class User { /** * @Id */ private $id; /** @String */ private $name; public function getId() { return $this->id; } public function getName() { return $this->name; } public function setName($name) { $this->name = $name; } } Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  29. MongoDB ODM • Get the default configured document manager: class MyController extends DoctrineController { public function indexAction() { $dm = $this->getDocumentManager(); // ... } } Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  30. MongoDB ODM • Get a configured document manager by its name: class MyController extends DoctrineController { public function indexAction() { $dm = $this->getDocumentManager('default'); // ... } } Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  31. MongoDB ODM • Just like the ORM persisting documents is easy: class MyController extends DoctrineController { public function createAction() { $dm = $this->getDocumentManager(); $user = new User(); $user->setName('Jonathan H. Wage'); $dm->persist($user); $dm->flush(); // ... } } Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  32. MongoDB ODM • Change tracking – All objects are tracked in an identity map – Changesets are calculated on flush – Changesets are used to perform updates using the atomic operators • The following code results in an efficient mongo update with only the properties that need updated: Array ( $user->setName('new name'); -> [$set] => Array ( $dm->flush(); [name] => new name ) ) Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  33. MongoDB ODM • Traditional MongoDB find() and findOne() $users = $dm->find('User', $criteria); $query = $dm->findOne('User', array('username' => 'jwage') ); $user = $query->getSingleResult(); Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  34. MongoDB ODM • Query API for building MongoDB queries through a fluent OO interface: class MyController extends DoctrineController { public function indexAction() { $dm = $this->getDocumentManager(); $query = $dm->createQuery('MyBundle:User'); $users = $query->execute(); // ... } } Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  35. MongoDB ODM • Using Query builder API class MyController extends DoctrineController { public function indexAction() { $dm = $this->getDocumentManager(); $query = $dm->createQuery('User') ->where('username', 'jwage'); $user = $query->getSingleResult(); // ... } } • where(), whereIn(), whereMod(), whereNot(), etc. Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  36. MongoDB ODM • Fluent Query interface generates and executes find() and findOne() methods internally • Query information is collected via fluent oo interface and executed later Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  37. MongoDB ODM • Document Query Language (DQL) – SQL like grammar for querying MongoDB • Query types supported – Find – Insert – Update – Remove Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  38. MongoDB ODM • Find query $query = $dm->query('find all User'); $users = $query->execute(); Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  39. MongoDB ODM • Selecting fields $query = $dm->query('find username, password User'); Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  40. MongoDB ODM • $slice operator for paging embedded collections $query = $dm->query('find comments skip 20 limit 10 Post'); Array ( [comments] => Array ( [$slice] => Array ( [0] => 20 [1] => 10 ) ) ) Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  41. MongoDB ODM • Use atomic operators $query = $dm->query("update User set password = 'changeme' where username = 'jwage'"); Array ( [$set] => Array ( [password] => changeme ) ) Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  42. MongoDB ODM • Complex update $query = $dm->query("update User inc count = 1, inc views = 2, set username = 'jwage'"); Array ( [$inc] => Array ( [count] => 1 [views] => 2 ) [$set] => Array ( [username] => jwage ) ) Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  43. MongoDB ODM • Document Query Language (DQL) – atomic operators – skip and limit main results – skip and limit embedded documents – use dot notation for querying embedded documents – embed JSON values in your DQL syntax $query = $dm->query("update User pushAll groups = '[1, 2, 3]'"); Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  44. Database Migrations • New DoctrineMigrationsBundle contains integration with the Doctrine Database Migrations project • Migrations have been completely re-written from Doctrine1 and are an extension of the database abstraction layer http://www.doctrine-project.org/projects/migrations Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  45. Database Migrations • Migration classes: class Version20100416130401 extends AbstractMigration { public function up(Schema $schema) { } public function down(Schema $schema) { } } Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  46. Database Migrations • Manually execute SQL for migrations: class Version20100416130422 extends AbstractMigration { public function up(Schema $schema) { $this->_addSql('CREATE TABLE addresses (id INT NOT NULL, street VARCHAR(255) NOT NULL, PRIMARY KEY(id)) ENGINE = InnoDB'); } public function down(Schema $schema) { $this->_addSql('DROP TABLE addresses'); } } Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  47. Database Migrations • Use API of Schema objects to perform migration: class Version20100416130401 extends AbstractMigration { public function up(Schema $schema) { $table = $schema->createTable('users'); $table->addColumn('username', 'string'); $table->addColumn('password', 'string'); } public function down(Schema $schema) { $schema->dropTable('users'); } } Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  48. Database Migrations • Check migrations status: $ ./doctrine migrations:status == Configuration >> Name: Doctrine Sandbox Migrations >> Configuration Source: /Users/jwage/Sites/doctrine2git/tools/sandbox/migrations.xml >> Version Table Name: doctrine_migration_versions >> Migrations Namespace: DoctrineMigrations >> Migrations Directory: /Users/jwage/Sites/doctrine2git/tools/sandbox/DoctrineMigrations >> Current Version: 2010-04-16 13:04:22 (20100416130422) >> Latest Version: 2010-04-16 13:04:22 (20100416130422) >> Executed Migrations: 0 >> Available Migrations: 1 >> New Migrations: 1 == Migration Versions >> 2010-04-16 13:04:01 (20100416130401) not migrated Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  49. Database Migrations • Execute migration dry runs: $ ./doctrine migrations:migrate --dry-run Are you sure you wish to continue? y Executing dry run of migration up to 20100416130452 from 0 >> migrating 20100416130452 -> CREATE TABLE users (username VARCHAR(255) NOT NULL, password VARCHAR(255) NOT NULL) ENGINE = InnoDB • Omit --dry-run to execute migration. Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  50. Database Migrations • Specify a version number to revert to or 0 to revert all migrations: $ ./doctrine migrations:migrate 0 Are you sure you wish to continue? y Migrating down to 0 from 20100416130401 -- reverting 20100416130401 -> DROP TABLE users -- reverted Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  51. Database Migrations • Write migration SQL file instead of executing: $ ./doctrine migrations:migrate --write-sql Executing dry run of migration up to 20100416130401 from 0 >> migrating 20100416130401 -> CREATE TABLE users (username VARCHAR(255) NOT NULL, password VARCHAR(255) NOT NULL) ENGINE = InnoDB Writing migration file to "/path/to/sandbox/doctrine_migration_20100416130405.sql" • It would produce a file like: # Doctrine Migration File Generated on 2010-04-16 13:04:05 # Migrating from 0 to 20100416130422 # Version 20100416130401 CREATE TABLE users (username VARCHAR(255) NOT NULL, password VARCHAR(255) NOT NULL) ENGINE = InnoDB; Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  52. Database Migrations • Integration with ORM for generating migrations when you change your mapping information. Add a new property to your Entity: /** @Entity @Table(name="users") */ class User { /** * @var string $test */ private $test; // ... } • Run the migrations diff command: $ ./doctrine migrations:diff Generated new migration class to "/path/to/migrations/DoctrineMigrations/Version20100416130459.php" from schema differences. Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  53. Database Migrations • The generated migration class looks like: class Version20100416130459 extends AbstractMigration { public function up(Schema $schema) { $this->_addSql('ALTER TABLE users ADD test VARCHAR(255) NOT NULL'); } public function down(Schema $schema) { $this->_addSql('ALTER TABLE users DROP test'); } } • It contains the SQL statements required to update your database with the schema changes. Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  54. Database Migrations • Run migrate command to execute the generated migration: $ ./doctrine migrations:migrate • Now your database is up to date and contains the new column named test. Doctrine 2 www.doctrine-project.org www.sensiolabs.com
  55. Questions? Jonathan H. Wage jonathan.wage@sensio.com sensiolabs.com | doctrine-project.org | sympalphp.org | jwage.com You should follow me on http://www.twitter.com/jwage for updates about Symfony, Doctrine and related developments. You can contact Jonathan about Doctrine and Open-Source or for training, consulting, application development, or business related questions at jonathan.wage@sensio.com Doctrine 2 www.doctrine-project.org www.sensiolabs.com
Advertisement