Doctrine et le Zend Framework : Présentation, intégration et utilisation

Créer automatiquement les relations objets - base de données.

03 septembre 2011

Le but de ce tutoriel est de présenter l'ORM Doctrine et de l'intégrer dans le Zend Framework.

Quelques définitions

  • ORM : Le Mapping d'Objet Relationnel (Object-Relational Mapping) est une technique de programmation informatique qui donne l'illusion d'une base de données orientée objet à partir d'une base de données relationnelle en définissant des correspondances entre cette base de données et les objets du langage utilisé. C'est un travail long et fastidieux de devoir créer ces objets à la main, surtout si la base de données est conséquente et change régulièrement.
  • Modèle : Dans le design pattern MVC, le modèle est la partie qui contient ou décrit les données. La plupart du temps le modèle est un ensemble de classes qui permet la relation avec une base de données.

Présentation de Doctrine

Doctrine est l'un des meilleurs ORM existants à ce jour. Sa notoriété et ses compétences ont fait de lui l'ORM par défaut du framework Symfony.

Le Zend Framework est le framework utilisé pour le développement d'Informatix. Il possède un composant (Zend_Db) qui permet de lancer des requêtes vers une BDD, néanmoins ce composant n'est pas un générateur ORM (toutes les classes du modèle doivent toujours être faites à la main) et il a quelques limitations.

Des limitations ? Eh oui ! lors du développement d'Informatix (qui n'est pourtant pas un projet complexe) j'ai eu le malheur de constater que Zend_Db était dans l'incapacité d'exécuter certaines de mes requêtes (ne me demandez pas lesquelles, je ne m'en souviens plus).

Ayant quelques connaissances en Symfony, je me suis rappelé du mode de fonctionnement de son modèle et de son extraordinaire ORM. J'ai par la suite décidé d'adopter Doctrine, il ne me restait plus qu'à réussir à l'intégrer dans le Zend Framework.

Notez qu'il est prévu que Doctrine devienne aussi l'ORM du Zend Framework dans les prochaines versions.

Intégration de Doctrine dans le Zend Framework

La première chose à faire est de télécharger Doctrine. J'utilise actuellement la version 1.2.4, ce n'est pas la dernière version et je ne pense pas que les manipulations qui vont suivre fonctionnent toutes avec les versions postérieures.

Placez le fichier "Doctrine.php" et le répertoire "Doctrine" dans le dossier "library" de votre application, aux côtés des répertoires "Zend" et "ZendX".

Créez l'arborescence de dossiers suivante :

Arborescence de dossiers Doctrine



Il faut maintenant créer la variable d'environnement APPLICATION_MODELS. La solution la plus simple est de l'ajouter dans l'index à la suite des autres déclarations.

/public/index.php

/* Utile pour Doctrine */
defined('APPLICATION_MODELS')
    || define('APPLICATION_MODELS', (getenv('APPLICATION_MODELS') ? getenv('APPLICATION_MODELS') : APPLICATION_PATH.'/models'));
	

Il y a bien sûr une petite phase de configuration dans laquelle nous indiquons l'arborescence créée précédemment.

/application/configs/application.ini

doctrine.data_fixtures_path = APPLICATION_PATH "/doctrine/data/fixtures"
doctrine.models_path = APPLICATION_PATH "/models"
doctrine.migrations_path = APPLICATION_PATH "/doctrine/migrations"
doctrine.sql_path = APPLICATION_PATH "/doctrine/data/sql"
doctrine.yaml_schema_path = APPLICATION_PATH "/doctrine/schema"

; on génère les classes de table
doctrine.generate_models_options.generateTableClasses       = true

; Définition de la Data Source Name.
; Evidemment il faut remplacer les mots en majuscules par vos propres valeurs.
; Par exemple pour MySQL.
doctrine.dsn = "mysql://LOGIN ASS@URL/BASE"
	

Comme pour beaucoup de composants avec Zend Framework, il nous faut l'initialiser. C'est sûrement la partie la plus compliquée de ce tutoriel, je vous demande de me faire confiance et de copier-coller bêtement pour le moment. Direction le bootstrap.

/application/Bootstrap.php



protected function _initDoctrine()
	{
	/* On met Doctrine en autoload */
	$this->getApplication()
	->getAutoloader()
	->pushAutoloader ( array ('Doctrine', 'autoload' ) );
	
	spl_autoload_register(array('Doctrine', 'modelsAutoload'));
	
	/* On récupère une instance de Doctrine */
	$manager = Doctrine_Manager::getInstance ();
	
	/* Permet de valider automatiquement l'intégrité des données
	** ce qui veut dire que l'on ne peut pas mettre une variable de type string
	** dans un champs de type int. 
	*/
	$manager->setAttribute (Doctrine::ATTR_VALIDATE, Doctrine::VALIDATE_ALL);
	
	/* AUTO_ACCESSOR_OVERRIDE va nous permettre de personnaliser l'assignation de données. */
	$manager->setAttribute ( Doctrine::ATTR_AUTO_ACCESSOR_OVERRIDE, true );
	
	/* Doctrine permet de personnaliser également les classes de table en permettant
	** de créer des méthodes propres à une table.
	**
	** Ce paramètre permet de charger le fichier contenant nos méthodes personnalisées.
	*/
	$manager->setAttribute (
	Doctrine::ATTR_MODEL_LOADING,
	Doctrine::MODEL_LOADING_CONSERVATIVE
	);
	
	/* On permet le chargement des classes de table. */
	$manager->setAttribute ( Doctrine::ATTR_AUTOLOAD_TABLE_CLASSES, true );
	
	$doctrineConfig = $this->getOption('doctrine');
	
	Doctrine::loadModels($doctrineConfig['models_path']);
	
	$conn = Doctrine_Manager::connection($doctrineConfig['dsn'],'doctrine');
	
	$conn->setAttribute(Doctrine::ATTR_USE_NATIVE_ENUM,true);
	
	$conn->setCharset('utf8');
	$conn->setCollate('utf8_general_ci');

	
	return ($conn);
	}




	

Pour finir il nous faut un script pour communiquer avec Doctrine et exécuter des actions. Ce script lancera la CLI (l'interface de lignes de commandes) de Doctrine et nous permettra de lui passer des paramètres.

/application/scripts/Doctrine-cli.php

/*
** Comme vous pouvez le voir la majorité de ce code est le même que dans
** /public/index.php.
*/
defined('APPLICATION_PATH')
    || define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/..'));

defined('APPLICATION_ENV')
    || define('APPLICATION_ENV', (getenv('APPLICATION_ENV') ? getenv('APPLICATION_ENV') : 'devlocal'));

/* Utile pour Doctrine */
defined('APPLICATION_MODELS')
    || define('APPLICATION_MODELS', (getenv('APPLICATION_MODELS') ? getenv('APPLICATION_MODELS') : APPLICATION_PATH.'/models'));  
    
   
set_include_path(implode(PATH_SEPARATOR, array(
    realpath(APPLICATION_PATH . '/../library'),
    get_include_path(),
)));

require_once 'Doctrine.php';

/** Zend_Application */  
require_once 'Zend/Application.php';

$application = new Zend_Application(
    APPLICATION_ENV,
    APPLICATION_PATH . '/configs/application.ini'
);


date_default_timezone_set('Europe/Berlin');


$application->getBootstrap()->bootstrap('doctrine'); /* Initialisation de Doctrine */
$config = $application->getOption('doctrine');
 
$cli = new Doctrine_Cli($config);
$cli->run($_SERVER['argv']);
	

Pour utiliser notre CLI :

Lancement du générateur de classes

NlC0@informatix : cd /application/scripts
php5 Doctrine-cli.php generate-models-db # Création des classes du modèle
php5 Doctrine-cli.php # Permet de voir toutes les options possibles.
	

Après la génération, vous devriez avoir dans le dossier "/application/models" :

  • Des fichiers {nom de table}.php.
  • Des fichiers {nom de table}Table.php.
  • Un dossier "generated" contenant des fichiers Base{nom de table}.php.

Et voilà c'est fini pour l'intégration. Ouf !

Utilisation de Doctrine

Doctrine utilise un langage appelé DQL (Doctrine Query Langage). C'est un langage très simple qui permet de faire des requêtes SQL complexes.

Voici des exemples :

Exemples d'utilisation de Doctrine

/* Si j'ai une table "auteur" avec un champ "nom" */

/* Avec les finders magiques. */
$auteur = Doctrine_Core::getTable('Auteur')->findOneByNom($nom);

/* Avec du DQL. */
$auteurs = Doctrine::getTable('Auteur')
	->createQuery('a')
	->where('a.nom = ?', $nom)
	->orderby('a.nom ASC')
	->execute()
	

J'espère qu'après avoir lu ceci vous gagnerez en temps de développement.

Pour la moindre question ou remarque n'hésitez pas à laisser un commentaire.

Par
Créateur et administrateur.

Dans la même catégorie

Formater un tableau pour CURLOPT_POSTFIELDS
Email avec pièce jointe en PHP
PHP : modifier les attributs privés d'un objet
Tester l'existence d'un fichier dans l'include path
Convertir récursivement un objet PHP en tableau
PHP : formater un tableau en CSV
Comment envoyer un mail en ligne de commande ?
RSYNC : Comment synchroniser des fichiers à travers une connexion ssh ?
Exécuter un code PHP en ligne de commande
Doctrine 2 : générer les classes PHP depuis la base de données
Comment catcher les erreurs en PHP ?
Doctrine 2 : comment afficher la requête SQL ?
Comment construire une URL sans caractères spéciaux en PHP ?
Comment lister les fichiers PHP inclus sur ma page ?
Les fonctions anonymes récursives en PHP
Requête HTTP asynchrone en PHP
La résolution statique à la volée ou Late Static Bindings
Trouver les jours fériés français en PHP
Comment allumer son ordinateur à distance en PHP ?
Comment utiliser la balise meta viewport ?
Une version mobile de mon site avec le Zend Framework
Créer son flux RSS simplement avec Zend_Feed
Appliquer un layout sur un mail avec le Zend Framework
Comment lancer une requête multi-bases avec les fonctions MySQL ?
Implode / Explode : Du tableau à la chaine de caractères, de la chaine de caractères au tableau

Commentaire(s)