Development

sfDoctrinePlugin

You must first sign up to be able to contribute.

sfDoctrinePlugin

Doctrine is a PHP ORM (object relational mapper) for PHP 5.2.3+ that sits on top of a powerful PHP DBAL (database abstraction layer). One of its key features is the ability to optionally write database queries in an OO (object oriented) SQL-dialect called DQL inspired by Hibernate's HQL. This provides developers with a powerful alternative to SQL that maintains a maximum of flexibility without requiring needless code duplication.

This symfony plugin allows you to use Doctrine as your ORM instead of Propel in your symfony projects. Below are the exact details on how to get your project converted to Doctrine.

Versions

sfDoctrinePlugin is available for both symfony 1.0.x and symfony 1.1-x (work in progress).

Installation

The sfDoctrinePlugin can be installed only with svn currently. Use the commands below to get your symfony project running with Doctrine instead of Propel.

Create new symfony app

$ mkdir symfony_app
$ cd symfony_app
$ symfony new symfony_app
$ symfony init-app frontend

Check out the sfDoctrinePlugin to your plugins folder

symfony 1.0.x

$ cd plugins
$ svn co http://svn.symfony-project.com/plugins/sfDoctrinePlugin/branches/1.0 sfDoctrinePlugin

symfony 1.1-x

$ cd plugins
$ svn co http://svn.symfony-project.com/plugins/sfDoctrinePlugin/trunk sfDoctrinePlugin

Now you must setup a few files and directories.

$ cd ..
$ mkdir config/doctrine
$ mkdir data/fixtures
$ vi config/databases.yml

Inside of databases.yml, place the following yaml syntax.

all:
  connection_name:
    class:          sfDoctrineDatabase
    param:
      dsn:          mysql://root:@localhost/dbname

Now the plugin is setup and ready to go inside of your symfony application. If you run the symfony command with no arguments, it will now show you the additional command line tasks available. The commands are listed below:

$ symfony
available pake tasks:
  clear-cache                          > clear cached information
  clear-controllers                    > clear controllers
  disable                              > disables an application in a given environment
  doctrine-build-all                   > Create database, generate models, insert sql
  doctrine-build-all-load              > Create database, generate models, insert sql, and load data from fixtures.
  doctrine-build-all-reload            > Drops database, creates database, generate models, and loads data from fixtures.
  doctrine-build-all-reload-test-all   > Drops database, creates database, generate models, loads data from fixtures, and runs all tests.
  doctrine-build-db                    > Create database
  doctrine-build-model                 > Build all Doctrine records
  doctrine-build-schema                > Build yaml schema from an existing database
  doctrine-build-sql                   > Export sql for doctrine schemas to data/sql
  doctrine-convert-schema              > Convert 0.1 schema to new Doctrine schema syntax
  doctrine-dql                         > Execute dql from the command line
  doctrine-drop-db                     > Drop database
  doctrine-dump-data                   > Dump data to yaml fixtures file
  doctrine-generate-crud               > Creates Doctrine CRUD Module
  doctrine-generate-migration          > Generate migration class template
  doctrine-generate-migrations-db      > Generate migration classes from databases
  doctrine-generate-migrations-models  > Generate migration classes from models
  doctrine-init-admin                  > Initialize a new doctrine admin module
  doctrine-insert-sql                  > Insert sql for doctrine schemas in to database
  doctrine-load-data                   > Load data from yaml fixtures file
  doctrine-migrate                     > Migrate database to current version or a specified version.
  doctrine-rebuild-db                  > Drop database and rebuild it
  downgrade                            > downgrade to a previous symfony release
  enable                               > enables an application in a given environment
  fix-perms                            > fix directories permissions
  freeze                               > freeze symfony libraries
  init-app                             > initialize a new symfony application
  init-batch                           > initialize a new symfony batch script
  init-controller                      > initialize a new symfony controller script
  init-module                          > initialize a new symfony module
  init-project                         > initialize a new symfony project
  log-purge                            > purges an applications log files
  log-rotate                           > rotates an applications log files
  plugin-install                       > install a new plugin
  plugin-list                          > list installed plugins
  plugin-uninstall                     > uninstall a plugin
  plugin-upgrade                       > upgrade a plugin
  propel-build-all                     > generate propel model and sql and initialize database
  propel-build-all-load                > generate propel model and sql and initialize database, and load data
  propel-build-db                      > create database for current model
  propel-build-model                   > create classes for current model
  propel-build-schema                  > create schema.xml from existing database
  propel-build-sql                     > create sql for current model
  propel-convert-xml-schema            > create schema.yml from schema.xml
  propel-convert-yml-schema            > create schema.xml from schema.yml
  propel-dump-data                     > dump data to fixtures directory
  propel-generate-crud                 > generate a new propel CRUD module
  propel-init-admin                    > initialize a new propel admin module
  propel-init-crud                     > initialize a new propel CRUD module
  propel-insert-sql                    > insert sql for current model
  propel-load-data                     > load data from fixtures directory
  sync                                 > synchronise project with another machine
  test-all                             > launch all tests
  test-functional                      > launch functional tests for an application
  test-unit                            > launch unit tests
  unfreeze                             > unfreeze symfony libraries
  upgrade                              > upgrade to a new symfony release

task aliases:
  app                                  = pake init-app
  batch                                = pake init-batch
  cc                                   = pake clear-cache
  controller                           = pake init-controller
  module                               = pake init-module
  new                                  = pake init-project

Now we need to setup some schema files and some data fixtures.

Create and edit config/doctrine/schema.yml. Place the following yaml syntax in schema.yml

---
User:
  columns:
    id:
      primary: true
      autoincrement: true
      type: integer(4)
    username:
      type: string(255)
    password:
      type: string(255)
  relations:
    Groups:
      class: Group
      refClass: UserGroup
      foreignAlias: Users

Group:
  tableName: groups
  columns:
    id:
      primary: true
      autoincrement: true
      type: integer(4)
    name:
      type: string(255)

UserGroup:
  columns:
    user_id:
      type: integer(4)
    group_id:
      type: integer(4)
  relations:
    User:
      onDelete: CASCADE
    Group:
      onDelete: CASCADE

Now place the followig yaml syntax in the data/fixtures/data.yml file

---
User:
  zyne:
    username: zYne-
    password: changeme
    Groups: [founder, lead, documentation]
  jwage:
    username: jwage
    password: changeme
    Groups: [lead, documentation]

Group:
  founder:
    name: Founder
  lead:
    name: Lead
  documentation:
    name: Documentation

Now that your schema files and data fixtures are in place you can run a few commands to get your database setup.

$ symfony doctrine-build-model
>> doctrine  Generated models successfully
$ symfony cc
$ symfony doctrine-build-all-reload
>> doctrine  Are you sure you wish to drop your databases? (y/n)
y
>> doctrine  Could not drop database for con... Unknown database 'symfony_app'
>> doctrine  Successfully created database f...ction_name" named "symfony_app"
>> doctrine  Generated models successfully
>> doctrine  Created tables successfully
>> doctrine  Data was successfully loaded

Now you can run this DQL query from the command line to see the data that was loaded in the database

$ symfony doctrine-dql "FROM User u, u.Groups g"
>> doctrine  executing: "FROM User u, u.Groups g" ()
>> doctrine  - 
>> doctrine    id: 1
>> doctrine    username: zYne-
>> doctrine    password: changeme
>> doctrine    Groups: 
>> doctrine      - 
>> doctrine        id: 1
>> doctrine        name: Founder
>> doctrine      - 
>> doctrine        id: 2
>> doctrine        name: Lead
>> doctrine      - 
>> doctrine        id: 3
>> doctrine        name: Documentation
>> doctrine  - 
>> doctrine    id: 2
>> doctrine    username: jwage
>> doctrine    password: changeme
>> doctrine    Groups: 
>> doctrine      - 
>> doctrine        id: 2
>> doctrine        name: Lead
>> doctrine      - 
>> doctrine        id: 3
>> doctrine        name: Documentation

Example Usage

// Create new user and assign a new group
$user = new User();
$user->username = 'jwage';
$user->password = 'changeme';
$user->Groups[0]->name = 'New Group';
$user->save();

print_r($user->toArray(true)); // prints user data and all relationship data

$group = Doctrine::getTable('Group')->findOneByName('New Group'); // Find a Group record by its name
$users = $group->Users; // Get the groups users

print_r($users->toArray(true)); // Prints the users from the group

$userTable = Doctrine::getTable('User');

$user = $userTable->find(1);
$user = $userTable->findOneById(1);
$user = $userTable->findByUsername('jwage');

$user = $userTable->find(1);
$user->delete();

$query = new Doctrine_Query();
$user = $query->from('User u')->where("u.username = 'jwage'")->limit(1)->execute()->getFirst();

$query = new Doctrine_Query();
$query->delete('User')->from('User u')->where("u.username = 'jwage'")->execute();

/* Do a Transaction */
Doctrine_Manager::getInstance()->getCurrentConnection()->beginTransaction();

$user = new User();
$user->username = 'jwage';
$user->save();

$user = new User();
$user->username = 'isleshocky77';
$user->save();

// Neither have been written to the database yet
Doctrine_Manager::getInstance()->getCurrentConnection()->commit();
// Both have now been written to the database

Admin Generators

The sfDoctrinePlugin offers the ability to create admin generators powered by Doctrine, just like you can with propel. Run the commands below to setup the admin generators for the user and group models.

$ symfony doctrine-init-admin frontend users User
$ symfony doctrine-init-admin frontend groups Group

Using Doctrine in Batch files

define('SF_ROOT_DIR',    realpath(dirname(__FILE__).'/..'));
define('SF_APP',         'public');
define('SF_ENVIRONMENT', 'cli');
define('SF_DEBUG',       false);
 
require_once(SF_ROOT_DIR.DIRECTORY_SEPARATOR.'apps'.DIRECTORY_SEPARATOR.SF_APP.DIRECTORY_SEPARATOR.'config'.DIRECTORY_SEPARATOR.'config.php');

# This is needed to initialize the db connections
sfContext::getInstance()->getDatabaseManager()->initialize();

Community

Features

A praised feature of Doctrine is the low level of configuration that is needed to start a project. Doctrine can generate object classes from an existing database, and the programmer can then specify relations and add custom functionality to the generated classes. There is no need to generate or maintain complex XML database schemas, as seen in many other frameworks.

Another key feature of Doctrine is the ability to optionally write database queries in an OO (object oriented) SQL dialect called DQL (Doctrine Query Language) inspired by Hibernate's HQL. Alternatively, the Doctrine_Query class allows one to construct queries through a fluent interface. These interfaces provide developers with powerful alternatives to SQL which maintain flexibility and still allow for switching of database back-ends, without requiring any code duplication.

Writing queries explicitly however is not always necessary, as Doctrine performs joins and fetches related objects automatically. Small projects can be easily constructed without writing queries.

Other notable features of Doctrine are:

  • support for hierarchical (tree-structured) data;
  • support for hooks (methods which can validate or modify database input and output) and event listeners to structure business-related logic;
  • column aggregation inheritance (similar objects can be stored in one database table, with one type-column specifying the subtype of the particular object - the correct subclass is always returned when a query is done);
  • a caching framework, making use of several backends such as memcached, SQLite or APC;
  • ACID transactions;
  • model behaviors (sluggable, timestampable, nested set, internationalization, audit log, search index);
  • database migrations;
  • a "compile" function to combine many PHP files of the framework into one, to avoid the performance hit usually incurred by including the many PHP files of a framework.