symfony2 and doctrine2 integration

55
Doctrine 2 www.doctrine-project.org www.sensiolabs.com Symfony and Doctrine What’s new in the Symfony and Doctrine Integration

Upload: jonathan-wage

Post on 08-May-2015

29.782 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Symfony2 and Doctrine2 Integration

Doctrine 2 www.doctrine-project.org www.sensiolabs.com

Symfony and DoctrineWhat’s new in the Symfony and Doctrine Integration

Page 2: Symfony2 and Doctrine2 Integration

Doctrine 2 www.doctrine-project.org www.sensiolabs.com

Updated DoctrineBundle• Doctrine2 features fully integrated– Database Abstraction Layer– Object Relational Mapper

Page 3: Symfony2 and Doctrine2 Integration

Doctrine 2 www.doctrine-project.org www.sensiolabs.com

DoctrineMongoDBBundle• MongoDB Object Document Mapper– Transparent persistence to MongoDB– Same architecture as ORM– Map a class as an entity and document

Page 4: Symfony2 and Doctrine2 Integration

Doctrine 2 www.doctrine-project.org www.sensiolabs.com

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

Page 5: Symfony2 and Doctrine2 Integration

Doctrine 2 www.doctrine-project.org www.sensiolabs.com

DBAL• To use just the DBAL you must configure it:

doctrine.dbal: dbname: Symfony user: root password: ~

Page 6: Symfony2 and Doctrine2 Integration

Doctrine 2 www.doctrine-project.org www.sensiolabs.com

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: Doctrine\Common\EventManager configuration_class: Doctrine\DBAL\Configuration wrapper_class: ~ options: []

Page 7: Symfony2 and Doctrine2 Integration

Doctrine 2 www.doctrine-project.org www.sensiolabs.com

DBAL Console Commands• Create all configured databases

• Create a specific database

• Drop all configured databases

• Drop a specific database

$ php console doctrine:database:create

$ php console doctrine:database:create --connection=default

$ php console doctrine:database:drop

$ php console doctrine:database:drop --connection=default

Page 8: Symfony2 and Doctrine2 Integration

Doctrine 2 www.doctrine-project.org www.sensiolabs.com

DBAL Console Commands• Execute SQL queries

• Specify connection

$ php console doctrine:query:sql “SELECT * FROM user”

$ php console doctrine:query:sql “...” --connection=default

Page 9: Symfony2 and Doctrine2 Integration

Doctrine 2 www.doctrine-project.org www.sensiolabs.com

DBAL• Get the default configured database

connection:class MyController extends DoctrineController{ public function indexAction() { $conn = $this->getDatabaseConnection(); // ... }}

Page 10: Symfony2 and Doctrine2 Integration

Doctrine 2 www.doctrine-project.org www.sensiolabs.com

DBAL• Get a configured database connection service

by its name:class MyController extends DoctrineController{ public function indexAction() { $conn = $this->getDatabaseConnection('default'); // ... }}

Page 11: Symfony2 and Doctrine2 Integration

Doctrine 2 www.doctrine-project.org www.sensiolabs.com

ORM• The EntityManager

• Central place for persisting and retrieving entities•Multiple instances allowed•One EntityManager per database connection

•Dependency Injection handles the creation and management of entity manager services

$config = new \Doctrine\ORM\Configuration();$config->setMetadataCacheImpl(new \Doctrine\Common\Cache\ArrayCache);$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 = \Doctrine\ORM\EntityManager::create($connectionOptions, $config);

Page 12: Symfony2 and Doctrine2 Integration

Doctrine 2 www.doctrine-project.org www.sensiolabs.com

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; }}

Page 13: Symfony2 and Doctrine2 Integration

Doctrine 2 www.doctrine-project.org www.sensiolabs.com

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

Page 14: Symfony2 and Doctrine2 Integration

Doctrine 2 www.doctrine-project.org www.sensiolabs.com

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

Page 15: Symfony2 and Doctrine2 Integration

• Console commands implemented for improved developer workflow:

Doctrine 2 www.doctrine-project.org www.sensiolabs.com

ORM

Page 16: Symfony2 and Doctrine2 Integration

Doctrine 2 www.doctrine-project.org www.sensiolabs.com

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

Page 17: Symfony2 and Doctrine2 Integration

Doctrine 2 www.doctrine-project.org www.sensiolabs.com

ORM• Get the default configured entity manager

service:

class MyController extends DoctrineController{ public function indexAction() { $em = $this->getEntityManager(); // ... }}

Page 18: Symfony2 and Doctrine2 Integration

Doctrine 2 www.doctrine-project.org www.sensiolabs.com

ORM• Get a configured entity manager service by its

name:

class MyController extends DoctrineController{ public function indexAction() { $em = $this->getEntityManager('default'); // ... }}

Page 19: Symfony2 and Doctrine2 Integration

Doctrine 2 www.doctrine-project.org www.sensiolabs.com

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(); // ... }}

Page 20: Symfony2 and Doctrine2 Integration

Doctrine 2 www.doctrine-project.org www.sensiolabs.com

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(); // ... }}

Page 21: Symfony2 and Doctrine2 Integration

Doctrine 2 www.doctrine-project.org www.sensiolabs.com

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(); // ... }}

Page 22: Symfony2 and Doctrine2 Integration

Doctrine 2 www.doctrine-project.org www.sensiolabs.com

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;}

Page 23: Symfony2 and Doctrine2 Integration

Doctrine 2 www.doctrine-project.org www.sensiolabs.com

ORM• Run update command to update your

database schema from mapping information

• The above compares your current database schema to your new mapping information and executes the necessary queries to bring your database up-to-date.

$ php console doctrine:schema:update

Page 24: Symfony2 and Doctrine2 Integration

Doctrine 2 www.doctrine-project.org www.sensiolabs.com

Object Document Mapper• New Doctrine Project for persisting objects to

MongoDB

• Same architecture as ORM

• Transparently persist PHP5 objects to MongoDB

Page 25: Symfony2 and Doctrine2 Integration

Doctrine 2 www.doctrine-project.org www.sensiolabs.com

MongoDB ODM• The DocumentManager

• Central place for persisting and retrieving documents•Multiple instances allowed

•Dependency Injection handles the creation and management of document manager services

$config = new Configuration();

$config->setProxyDir(__DIR__ . '/Proxies');$config->setProxyNamespace('Proxies');$config->setDefaultDB('doctrine_odm_sandbox');

$reader = new AnnotationReader();$reader->setDefaultAnnotationNamespace('Doctrine\ODM\MongoDB\Mapping\\');$config->setMetadataDriverImpl(new AnnotationDriver($reader, __DIR__ . '/Documents'));

$dm = DocumentManager::create(new Mongo(), $config);

Page 26: Symfony2 and Doctrine2 Integration

• 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

MongoDB ODM

Page 27: Symfony2 and Doctrine2 Integration

Doctrine 2 www.doctrine-project.org www.sensiolabs.com

MongoDB ODM• If the defaults are good enough for you then

you can omit all the previous options:

doctrine_odm.mongodb: ~

Page 28: Symfony2 and Doctrine2 Integration

Doctrine 2 www.doctrine-project.org www.sensiolabs.com

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; }}

Page 29: Symfony2 and Doctrine2 Integration

Doctrine 2 www.doctrine-project.org www.sensiolabs.com

MongoDB ODM• Get the default configured document

manager:

class MyController extends DoctrineController{ public function indexAction() { $dm = $this->getDocumentManager(); // ... }}

Page 30: Symfony2 and Doctrine2 Integration

Doctrine 2 www.doctrine-project.org www.sensiolabs.com

MongoDB ODM• Get a configured document manager by its

name:

class MyController extends DoctrineController{ public function indexAction() { $dm = $this->getDocumentManager('default'); // ... }}

Page 31: Symfony2 and Doctrine2 Integration

Doctrine 2 www.doctrine-project.org www.sensiolabs.com

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(); // ... }}

Page 32: Symfony2 and Doctrine2 Integration

Doctrine 2 www.doctrine-project.org www.sensiolabs.com

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:

$user->setName('new name');$dm->flush();

Array( [$set] => Array ( [name] => new name ))

->

Page 33: Symfony2 and Doctrine2 Integration

Doctrine 2 www.doctrine-project.org www.sensiolabs.com

MongoDB ODM• Traditional MongoDB find() and findOne()

$users = $dm->find('User', $criteria);

$query = $dm->findOne('User', array('username' => 'jwage'));$user = $query->getSingleResult();

Page 34: Symfony2 and Doctrine2 Integration

Doctrine 2 www.doctrine-project.org www.sensiolabs.com

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(); // ... }}

Page 35: Symfony2 and Doctrine2 Integration

Doctrine 2 www.doctrine-project.org www.sensiolabs.com

MongoDB ODM• Using Query builder API

• where(), whereIn(), whereMod(), whereNot(), etc.

class MyController extends DoctrineController{ public function indexAction() { $dm = $this->getDocumentManager(); $query = $dm->createQuery('User') ->where('username', 'jwage');

$user = $query->getSingleResult(); // ... }}

Page 36: Symfony2 and Doctrine2 Integration

Doctrine 2 www.doctrine-project.org www.sensiolabs.com

MongoDB ODM• Fluent Query interface generates and

executes find() and findOne() methods internally

• Query information is collected via fluent oo interface and executed later

Page 37: Symfony2 and Doctrine2 Integration

Doctrine 2 www.doctrine-project.org www.sensiolabs.com

MongoDB ODM• Document Query Language (DQL)– SQL like grammar for querying MongoDB

• Query types supported– Find– Insert– Update– Remove

Page 38: Symfony2 and Doctrine2 Integration

Doctrine 2 www.doctrine-project.org www.sensiolabs.com

MongoDB ODM• Find query

$query = $dm->query('find all User');$users = $query->execute();

Page 39: Symfony2 and Doctrine2 Integration

Doctrine 2 www.doctrine-project.org www.sensiolabs.com

MongoDB ODM• Selecting fields

$query = $dm->query('find username, password User');

Page 40: Symfony2 and Doctrine2 Integration

Doctrine 2 www.doctrine-project.org www.sensiolabs.com

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 )

)

)

Page 41: Symfony2 and Doctrine2 Integration

Doctrine 2 www.doctrine-project.org www.sensiolabs.com

MongoDB ODM• Use atomic operators

$query = $dm->query("update User set password = 'changeme' where username = 'jwage'");

Array( [$set] => Array ( [password] => changeme )

)

Page 42: Symfony2 and Doctrine2 Integration

Doctrine 2 www.doctrine-project.org www.sensiolabs.com

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 )

)

Page 43: Symfony2 and Doctrine2 Integration

Doctrine 2 www.doctrine-project.org www.sensiolabs.com

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]'");

Page 44: Symfony2 and Doctrine2 Integration

Doctrine 2 www.doctrine-project.org www.sensiolabs.com

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

Page 45: Symfony2 and Doctrine2 Integration

Doctrine 2 www.doctrine-project.org www.sensiolabs.com

Database Migrations• Migration classes:

class Version20100416130401 extends AbstractMigration{ public function up(Schema $schema) {

}

public function down(Schema $schema) {

}}

Page 46: Symfony2 and Doctrine2 Integration

Doctrine 2 www.doctrine-project.org www.sensiolabs.com

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'); }}

Page 47: Symfony2 and Doctrine2 Integration

Doctrine 2 www.doctrine-project.org www.sensiolabs.com

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'); }}

Page 48: Symfony2 and Doctrine2 Integration

Doctrine 2 www.doctrine-project.org www.sensiolabs.com

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

Page 49: Symfony2 and Doctrine2 Integration

Doctrine 2 www.doctrine-project.org www.sensiolabs.com

Database Migrations• Execute migration dry runs:

• Omit --dry-run to execute migration.

$ ./doctrine migrations:migrate --dry-runAre you sure you wish to continue?yExecuting 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

Page 50: Symfony2 and Doctrine2 Integration

Doctrine 2 www.doctrine-project.org www.sensiolabs.com

Database Migrations• Specify a version number to revert to or 0 to

revert all migrations:$ ./doctrine migrations:migrate 0Are you sure you wish to continue?yMigrating down to 0 from 20100416130401

-- reverting 20100416130401

-> DROP TABLE users

-- reverted

Page 51: Symfony2 and Doctrine2 Integration

Doctrine 2 www.doctrine-project.org www.sensiolabs.com

Database Migrations• Write migration SQL file instead of executing:

• It would produce a file like:

$ ./doctrine migrations:migrate --write-sqlExecuting 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"

# Doctrine Migration File Generated on 2010-04-16 13:04:05# Migrating from 0 to 20100416130422

# Version 20100416130401CREATE TABLE users (username VARCHAR(255) NOT NULL, password VARCHAR(255) NOT NULL) ENGINE = InnoDB;

Page 52: Symfony2 and Doctrine2 Integration

Doctrine 2 www.doctrine-project.org www.sensiolabs.com

Database Migrations• Integration with ORM for generating

migrations when you change your mapping information. Add a new property to your Entity:

• Run the migrations diff command:$ ./doctrine migrations:diffGenerated new migration class to "/path/to/migrations/DoctrineMigrations/Version20100416130459.php" from schema differences.

/** @Entity @Table(name="users") */class User{ /** * @var string $test */ private $test;

// ...}

Page 53: Symfony2 and Doctrine2 Integration

Doctrine 2 www.doctrine-project.org www.sensiolabs.com

Database Migrations• The generated migration class looks like:

• It contains the SQL statements required to update your database with the schema changes.

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'); }}

Page 54: Symfony2 and Doctrine2 Integration

Doctrine 2 www.doctrine-project.org www.sensiolabs.com

Database Migrations• Run migrate command to execute the

generated migration:

• Now your database is up to date and contains the new column named test.

$ ./doctrine migrations:migrate

Page 55: Symfony2 and Doctrine2 Integration

You can contact Jonathan about Doctrine and Open-Source or for training, consulting, application development, or business related

questions at [email protected]

Doctrine 2 www.doctrine-project.org www.sensiolabs.com

Jonathan H. [email protected]

sensiolabs.com | doctrine-project.org | sympalphp.org | jwage.com

Questions?

You should follow me on http://www.twitter.com/jwage for updates about Symfony, Doctrine and related developments.