Reply to comment

How To Use Doctrine PHP ORM?

On my previous post I have write about doctrine usage with Zend Framework. On this post, I will try to give sample usage of doctrine that contain:
- Installation
- Configuration
- Models & Schema File
- Migration
The easiest way to learn and start to use doctrine is use Doctrine Sandbox with completed by configuration and directory structure.

Installation
Doctrine use PHP 5.2.3+, and make sure your php version have support first. When I write this post, the current stable version of doctrine is 1.1.4 and can be downloaded here and for doctrine sandbox here. Doctrine library also provided by Doctrine Sandbox, so you don't need Doctrine Installer more. If you have download and extract Doctrine Sandbox then it will produce files and folders like this:

config.php
data/
doctrine
doctrine.php
index.php
lib/
migrations/
models/
schema/

Here explanation about files and folders above
- config.php
Contain configuration of Doctrine. Path from library, models, migration, schema files, and path for export or import data.
- data/
This folder contain fixtures and sql folders. fixtures folder is used to save file that will be used to import data from yaml file. sql folder is used to save export of database in sql file.
- doctrine
This is an execution file, that used as tools for doctrine.
- doctrine.php
This file will include on doctrine tools above.
- index.php
This just sample file.
- lib/
This folder contain library of doctrine. On this library also contain doctrine installer. I suggest to move all folders and files on it to php include_path, for on every project that use doctrine, you just use library from include path, and don't need to include the library on every project.
- migrations/
This folder will contain of migration classes that will used by doctrine to make a migration.
- models/
This folder will contain of models classes
- schema/
This folder will contain of schema files in yaml file.

Configuration
For installation, doctrine don't need configuration. This library can be included on every projects. But I prefer to move Doctrine library to PHP include_path. Configuration will need when use doctrine. On this sandbox, configuration will be found on config.php

<?php 
// set path sandbox
define('SANDBOX_PATH'dirname(__FILE__));
// set path for doctrine library
define('DOCTRINE_PATH'SANDBOX_PATH DIRECTORY_SEPARATOR 'lib');
// set path for data fixtures. It intended to import data from yaml file
define('DATA_FIXTURES_PATH'SANDBOX_PATH DIRECTORY_SEPARATOR 'data' DIRECTORY_SEPARATOR 'fixtures');
// set path for models
define('MODELS_PATH'SANDBOX_PATH DIRECTORY_SEPARATOR 'models');
// set path for migration
define('MIGRATIONS_PATH'SANDBOX_PATH DIRECTORY_SEPARATOR 'migrations');
// set path to save sql file export database from doctrine
define('SQL_PATH'SANDBOX_PATH DIRECTORY_SEPARATOR 'data' DIRECTORY_SEPARATOR 'sql');
// set path to save schema file
define('YAML_SCHEMA_PATH'SANDBOX_PATH DIRECTORY_SEPARATOR 'schema');
// set database path (assumed to use sqlite)
define('DB_PATH'SANDBOX_PATH DIRECTORY_SEPARATOR 'sandbox.db');
// set DSN
define('DSN''sqlite:///' DB_PATH);
// if use mysql, user password and database (doctrine, doctrine, doctrine) 
// define('DSN', 'mysql://doctrine:doctrine@localhost/doctrine');

// if have move library to php include path, this require_once() can be ignored
require_once(DOCTRINE_PATH DIRECTORY_SEPARATOR 'Doctrine.php');
spl_autoload_register(array('Doctrine''autoload'));

// make database connection base on DSN
$manager Doctrine_Manager::getInstance();
$manager->openConnection(DSN'doctrine');
$manager->setAttribute('model_loading''conservative');
?>

Configuration above will make database connection and will need (require/include) on each file that need to make interaction to database. The config file above will be included on doctrine.php too.

<?php
require_once('config.php');

// save configuration that have made in config.php to an array
$config = array('data_fixtures_path'  =>  DATA_FIXTURES_PATH,
                
'models_path'         =>  MODELS_PATH,
                
'migrations_path'     =>  MIGRATIONS_PATH,
                
'sql_path'            =>  SQL_PATH,
                
'yaml_schema_path'    =>  YAML_SCHEMA_PATH);

// use array configuration to Doctrine_Cli
$cli = new Doctrine_Cli($config);
$cli->run($_SERVER['argv']);
?>

This tools can be run on command line

./doctrine

or

php doctrine.php

Command above will display list options from the tools that can be used:

Doctrine Command Line Interface
 
doctrine.php build-all
doctrine.php generate-migration
doctrine.php generate-sql
doctrine.php create-db
doctrine.php generate-models-db
doctrine.php generate-migrations-diff
doctrine.php generate-migrations-db
doctrine.php dump-data
doctrine.php build-all-reload
doctrine.php dql
doctrine.php rebuild-db
doctrine.php migrate
doctrine.php generate-models-yaml
doctrine.php create-tables
doctrine.php generate-yaml-db
doctrine.php generate-yaml-models
doctrine.php build-all-load
doctrine.php load-data
doctrine.php generate-migrations-models
doctrine.php drop-db
doctrine.php compile

Models & Schema Files
Dalam konsep MVC model merupakan abstraksi dari database. Jadi untuk mengakses tabel yang ada di database tidak perlu lagi melakukan query, tetapi cukup membuat object dari model tersebut dan mengakses (magic) method ataupun (magic) property dari model tersebut. Pada doctrine, model tersebut bisa dibuat manual dengan mengikuti petunjuk berikut. Saya lebih suka membuat model tersebut secara otomatis, dengan membuat schema file terlebih dahulu. Setelah schema file dibuat, dengan menjalankan perintah berikut maka model pun secara otomatis dibuat oleh doctrine.

In MVC concept, model is abstraction from table on database. So, you don't need make a query to access table on database, but just make an object from that model and access (magic) method or (magic) property from that model. On doctrine, that model can be made with follow this guideline. I prefer to make that model automatically with make schema file first. Then, with run this command Doctrine will generate automatically.

./doctrine generate-models-db

Just make models don't mean you have interact with database. Because all tables on database have no created. You can insert, update, or delete from that model still saved on computer memory. To make table on database based on models, can be made automatically with this command

./doctrine create-tables

Saya akan memberikan contoh penggunaan doctrine yang menangani user dan group. Pada contoh ini user dan group mempunyai relasi many to many. Berikut ini adalah isi dari schema file.

I will give an example of doctrine usage that handle user and group. On this sample user and group have many to many relation. Here contain of schema file.

---
Group:
  tableName: groups
  columns:
    groupId:
      type: string(32)
      primary: true
    name: string(255)
  relations:
    Users:
      class: User
      local: groupId
      foreign: userId
      refClass: UserIsInGroup
 
User:
  tableName: user
  columns:
    userId:
      type: string(20)
      primary: true
    name: string(255)
    password: string(255)
  relations:
    Group:
      class: Group
      local: userId
      foreign: groupId
      refClass: UserIsInGroup
 
UserIsInGroup:
  tableName: user_is_in_groups
  columns:
    userId:
      type: string(20)
    groupId:
      type: string(32)

To make model and table on database can be done with this command

./doctrine build-all

Make sure that model have been created by doctrine, you can check the model have exists on models folder. For table on database, you can check directly in database. Doctrine also give tools to import data. But data must be prepared in data/fixtures folder in yaml format. Here data that will be imported to table on database.

---
Group:
     admin:
       groupId: admin
       name: admin
     project:
       groupId: project
       name: project
     sudo:
       groupId: sudo
       name: sudo
     user:
       groupId: user
       name: user
User:
    dolly:
       userId: dolly
       name: Dolly Aswin Harahap
       password: e10adc3949ba59abbe56e057f20f883e
    root:
       userId: root
       name: root
       password: e10adc3949ba59abbe56e057f20f883e
UserIsInGroup:
     rootadmin:
       userId: root
       groupId: admin
     dollysudo: 
       userId: dolly
       groupId: sudo
     dollyuser: 
       userId: dolly
       groupId: user

Here command to import data

./doctrine load-data

We have successfull to make models and table also import data with doctrine. Now, we can interact with models. I will give sample code to retrieve user and group with user id dolly.

<?php
// retrieve user with user id dolly
$user Doctrine::getTable('User')->find('dolly');
echo 
$user->userId ': ';

// retrieve all groups from user dolly
foreach ($user->Group as $group) {
    echo 
$group->groupId ',';
}

echo 
PHP_EOL;
?>

To insert data to user table can use the way below. This code will add user id programmer to user table.

<?php
$user 
= new User;
$user->userId 'programmer';
$user->name   'Programmer';
$user->password md5('asdf');
// add user and project to group
$user->UserIsInGroup[0]->groupId 'user';
$user->UserIsInGroup[1]->groupId 'project';
$user->save();
?>

Berikut ini contoh kode program untuk mengubah data di tabel user. Jika dijalankan maka kode program tersebut akan mengubah password dari user id dolly dan menambahkan group id project.
Here are sample code to update data on user table. If it is ran will change password from user id dolly and add project to group

<?php
user 
Doctrine::getTable('User')->find('dolly');
$user->password md5('asdf');
// add project to group
$user->UserIsInGroup[2]['groupId'] = 'project';
$user->save();
?>

Here code to delete user programmer and its relation.

<?php
$user 
Doctrine::getTable('User')->find('programmer');
// delete relation
$user->UserIsInGroup->delete();
// delete user
$user->delete();
?>

Migrations
Migration is my favourite feature on Doctrine. Migration is make change to database structure without destroy data on database. Doctrine will migrate based on migration classes that have made. But I prefer to make migration classes automatically. Doctrine will make it with diff schema file with the current models.

I assume we have made project release, with user, groups, and user_is_in_groups table. We want to add emailAddress field on user table for next release. To make it, just add the emailAddress field on user table structure on schema file.

User:
  tableName: user
  columns:
    userId:
      type: string(20)
      primary: true
    name: string(255)
    password: string(255)
    # tambahan field email address
    emailAddres: string(125)
  relations:
    Group:
      class: Group
      local: userId
      foreign: groupId
      refClass: UserIsInGroup

After added, just run this command

./doctrine generate-migrations-diff

The command above will produce migration class, and will exist in migrations folder. Here are contain of migration class that be generated by Doctrine automatically that saved with file name 1256232283_version1.php (the prefix number will different on your computer).


<?php
/**
 * This class has been auto-generated by the Doctrine ORM Framework
 */
class Version1 extends Doctrine_Migration_Base
{
    public function 
up()
    {
        
$this->addColumn('user''emailaddres''string''125', array(
             ));
    }

    public function 
down()
    {
        
$this->removeColumn('user''emailaddres');
    }
}
?>

Migration class have been created and to affect change to model or table structure on database, just run this command

 
./doctrine migrate

The command above will change model and table structure on database. Doctrine also make migration_version table on database to save version of migration that have been ran.
Ok, I think that's all my explanation about doctrine usage. Thanks

Reply

The content of this field is kept private and will not be shown publicly.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Lines and paragraphs break automatically.

More information about formatting options