Techno, Développement, Entreprendre et au-delà !
Dans: Tutoriel|Zend Framework
27 nov 2008Cet article est une traduction du billet de Ruben Vermeersch.
Ce tutoriel vous permettra à l’aide de plusieurs étapes de mettre en place un projet utilisant à la fois Zend Framework et Doctrine. Pas à pas, nous allons réaliser une simple application permettant de poster des messages.
Bien que j’ai essayé de conserver cet article très simple, il ne s’agit pas d’une introduction aux deux technologies précitées. Je vous recommande de prendre en main ces deux technologies séparément, avant d’essayer de les combiner ensemble.
Les deux possèdent une bonne documentation vous permettant de débuter :
Le tutoriel d’Akra sur le Zend Framework permet également de bien débuter.
(Note du traducteur : pour la communauté française, vous pouvez trouver de nombreux tutoriels pour débuter sur le site de la communauté française du Zend Framework)
Le Zend framework propose une architecture à utiliser à la carte. Cela veut dire que vous êtes libre d’utiliser uniquement les composants qui vous sont nécessaires, alors que dans d’autres frameworks, la décision est plutôt du type tout ou rien. Cette utilisation ‘à la carte’ est une bonne chose : cela nous permet de développer de véritables applications Zend Framework, sans utiliser le composant Zend_Db (abstraction de base de données).
Le Zend Framework vous laisse une grande liberté dans la façon de construire vos applications. En d’autres termes : il ne vous oblige pas à avoir une structure figée pour votre projet. Dans cet article, j’ai essayé de suivre au plus près la structure recommandée par défaut. Cependant, tout cela n’est qu’une question de goût personnel.
En premier, nous allons créer la structure par défaut du projet et installer les librairies. Ouvrez un gestionnaire de fichier et créez une structure de dossiers comme ci-dessous. J’expliquerai le rôle de ces dossiers dans un instant.
Structure basique des dossiers

Cela fait beaucoup de dossiers, mais la plupart d’entre eux vous sont familiers si vous avez déjà construit une application Zend Framework auparavant. Ce qui suit est différent :
application/doctrine/: Celui-ci contient tous les fichiers de données de Doctrine, comme les schéma sql et yaml, migrations, dump de données…application/models/: Doctrine génèrera automatiquement les fichiers de modèles dans ce répertoire, qui seront facilement utilisables au sein de votre application Zend Framework.library/: Normallement, vous n’installez que la librairie Zend Framework dans ce dossier library. Dans notre application, nous aurons besoin de deux librairies : le Zend Framework et Doctrine.
scripts/: Doctrine est fournit avec un script en ligne de commande, nous le stockerons ici (comme indiqué dans la proposition mentionnée ci-dessus).Notre prochaine étape sera d’installer le Zend Framework et Doctrine. Télécharger les dernières versions depuis les sites respectifs et décompresser le dossier library (pour Zend Framework) ou lib (pour Doctrine) dans les dossiers que nous venons juste de créer. Cela devrait ressemblait à quelque chose comme cela :
Zend Framework et Doctrine installés

Si vous vous souvenez correctement du Zend Framework Quick Start, nous avons besoin de créer un fichier bootstrap.php. Occupons nous de cela maintenant, avec les quelques modifications permettant d’utiliser Doctrine.
Tout d’abord, nous allons créer les fichiers public/index.php et public/.htaccess . Lancez votre éditeur préféré et récupérez les morceaux de code ci-dessous :
public/index.php
<?php
require '../application/bootstrap.php';
public/.htaccess
RewriteEngine on
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteRule ^(.*)$ index.php/$1
Comme vous pouvez le voir, ce sont les mêmes que dans n’importe quelle autre application Zend Framework. Le fichier application/bootstrap.php est légèrement différent.
Je l’ai divisé en deux fichiers: application/bootstrap.php et application/global.php. Le premier prend en charge les requêtes client, le second inclut tous les fichiers nécessaires.
J’ai divisé ainsi car le code de global.php est également nécessaire dans le script en ligne de commande de Doctrine (que nous allons voir dans une minute).
application/global.php
<?php
error_reporting(E_ALL | E_STRICT);
ini_set('display_startup_errors', 1);
ini_set('display_errors', 1);
date_default_timezone_set('Europe/Brussels');
/*
* Setup libraries & autoloaders
*/
set_include_path(dirname(__FILE__).‘/../library/zendframework’
. PATH_SEPARATOR . dirname(__FILE__).‘/../library/doctrine’
. PATH_SEPARATOR . dirname(__FILE__).‘/models’
. PATH_SEPARATOR . dirname(__FILE__).‘/models/generated’
. PATH_SEPARATOR . get_include_path());
require ‘Zend/Loader.php’;
Zend_Loader::registerAutoload(‘Zend_Loader’);
/*
* Set super-global data
*/
Doctrine_Manager::connection(« mysql://user:pass@localhost/database »);
/*
* Configure Doctrine
*/
Zend_Registry::set(‘doctrine_config’, array(
‘data_fixtures_path’ => dirname(__FILE__).‘/doctrine/data/fixtures’,
‘models_path’ => dirname(__FILE__).‘/models’,
‘migrations_path’ => dirname(__FILE__).‘/doctrine/migrations’,
‘sql_path’ => dirname(__FILE__).‘/doctrine/data/sql’,
‘yaml_schema_path’ => dirname(__FILE__).‘/doctrine/schema’
));
application/bootstrap.php
<?php
require dirname(__FILE__).'/global.php';
Zend_Controller_Front::run(dirname(__FILE__).‘/controllers’);
?>
Regardons cela pas à pas :
<?php
error_reporting(E_ALL | E_STRICT);
ini_set('display_startup_errors', 1);
ini_set('display_errors', 1);
date_default_timezone_set('Europe/Brussels');
?>
<?php
/*
* Setup libraries & autoloaders
*/
set_include_path(dirname(__FILE__).'/../library/zendframework'
. PATH_SEPARATOR . dirname(__FILE__).'/../library/doctrine'
. PATH_SEPARATOR . dirname(__FILE__).'/models'
. PATH_SEPARATOR . dirname(__FILE__).'/models/generated'
. PATH_SEPARATOR . get_include_path());
require 'Zend/Loader.php';
Zend_Loader::registerAutoload('Zend_Loader');
?>
<?php
/*
* Set super-global data
*/
Doctrine_Manager::connection("mysql://user:pass@localhost/database");
/*
* Configure Doctrine
*/
Zend_Registry::set(‘doctrine_config’, array(
‘data_fixtures_path’ => dirname(__FILE__).‘/doctrine/data/fixtures’,
‘models_path’ => dirname(__FILE__).‘/models’,
‘migrations_path’ => dirname(__FILE__).‘/doctrine/migrations’,
‘sql_path’ => dirname(__FILE__).‘/doctrine/data/sql’,
‘yaml_schema_path’ => dirname(__FILE__).‘/doctrine/schema’
));
?>
Le fichier application/bootstrap.php ne contient rien de surprenant. Encore une fois, j’essaie de garder cet exemple le plus simple possible.
Enfin, nous allons définir l’interface de ligne de commande Doctrine :
scripts/doctrine-cli
#!/usr/bin/env php
<?php
require dirname(__FILE__).'/../application/global.php';
$cli = new Doctrine_Cli(Zend_Registry::get(‘doctrine_config’));
$cli->run($_SERVER['argv']);
Rendez ce script exécutable :
chmod +x scripts/doctrine-cli
et vous êtes prêt à commencer.
A présent que nous avons les scripts de base en place, nous allons construire une application simple utilisant le Zend Framework et Doctrine. Nous allons construire un mur de message très simple, un endroit où les utilisateurs pourront poster un message et voir les autres messages.
Nous ferons cela très simplement : seulement un contrôleur et un script de vue. Recopier les fichiers suivants :
application/views/scripts/index/index.phtml
<html>
<head
<title>ZF & Doctrine example</title>
</head>
<body>
<h1>Submit a message:</h1>
<?=$this->form?>
<hr />
<h1>Messages posted:</h1>
<!– TODO: Show messages here –>
</body>
</html>
application/controllers/IndexController.php
<?php
class IndexController extends Zend_Controller_Action
{
public function indexAction(
{
$form = $this->getForm();
$req = $this->getRequest();
if ($req->getPost() && $form->isValid($req->getPost())) {
// TODO: Insert message into database
}
$this->view->form = $form;
// TODO: Retrieve all messages.
}
private function getForm()
{
$form = new Zend_Form();
$form->addElement(‘text’, ‘name’, array(
‘label’ => ‘Your name’,
‘required’ => true
));
$form->addElement(‘textarea’, ‘message’, array(
‘label’ => ‘Message’,
‘required’ => true,
‘rows’ => 4
));
$form->addElement(‘submit’, ‘send’);
return $form;
}
}
?>
Comme vous pouvez le voir, il y a trois grands points TODO : l’un dans le script de vue et deux dans le contrôleur. Ce sont les endroits où nous devrons raccorder Doctrine. Mais pour ce faire, nous avons besoin tout d’abord de définir des objets de données. Nous allons revenir sur le contrôleur et le script de vue plus tard, mais à présent, il est temps de créer un schéma de base de données.
application/doctrine/schema/schema.yml (attention à l’indentation, YAML y est très sensible)
---
Message:
columns:
id:
primary: true
autoincrement: true
type: integer(4)
posted:
type: timestamp
name:
type: string(255)
message:
type: string
Dans cette application, nous n’avons besoin que d’un objet très simple: Message, avec quatre colonnes: l’identifiant unique obligatoire, la date et l’heure lorsque le message a été envoyé, le nom de l’utilisateur et le message lui-même.
Nous pouvons à présent utiliser la ligne de commande de Doctrine afin de générer les fichiers de modèles et les tables de la base de données. Depuis le shell, exécutez ceci :
$ ./scripts/doctrine-cli generate-models-yaml
generate-models-yaml - Generated models successfully from YAML schema
$ ./scripts/doctrine-cli generate-sql
generate-sql - Generated SQL successfully for models
$ ./scripts/doctrine-cli create-tables
create-tables - Created tables successfully
Si tout se passe bien, aucune erreur ne doit s’afficher. Si c’est le cas, assurez-vous que vos informations de connexion sont correctement définies.
<?php
// TODO: Insert message into database
?>
Par celui là (ne tenez pas compte des balises <?php et ?> ) :
<?php
$message = new Message();
$message->fromArray($form->getValues(true));
$message->posted = new Doctrine_Expression('NOW()');
$message->save();
?>
application/models/. L’autoloader prend en charge tous les besoins de chargement.Nous avons également besoin de pouvoir récupérer les messages afin de les afficher.Tout d’abord, le contrôleur.
Remplacez :
<?php
// TODO: Retrieve all messages.
?>
Par :
<?php
$messages = Doctrine_Query::create()
->from('Message m')
->orderBy('m.posted DESC')
->execute();
$this->view->messages = $messages;
?>
Encore une fois, très simple. J’ai utilisé une requête DQL (Doctrine Query Language) pour trier par ordre anti-chronologique.
Maintenant, tout ce qu’il reste à faire est l’affichage de ces messages dans notre script de vue. Encore une fois, remplacer:
<!-- TODO: Show messages here -->
Par :
<?php foreach ($this->messages as $message): ?>
<h2><?=$message->name?> (<?=$message->posted?>)</h2>
<?=$message->message?>
<?php endforeach; ?>
Et voilà, nous avons fini, le résultat devrait ressembler à quelquechose comme cela :
L’application terminée

Donc vous l’avez, une application claire et simple utilisant à la fois le Zend Framework et Doctrine. Comme les deux suivent un peu la même philosophie, il est possible d’intégrer ces derniers d’une manière très propre, de prendre un réel plaisir à la construction d’une application.
Si vous avez une remarque, un commentaire ou des questions, n’hésitez pas à m’envoyer un mail (ruben@savanne.be), ou un commentaire sur mon blog.
Note du traducteur : Si vous avez une remarque, un commentaire ou des questions sur cette traduction, n’hésitez pas à m’envoyer un mail (fred [point] blanc [arobase] gmail [point] com, ou à poster un commentaire ci-dessous.
application/controllers/IndexController.php
<?php
class IndexController extends Zend_Controller_Action
{
public function indexAction()
{
$form = $this->getForm();
$req = $this->getRequest();
if ($req->getPost() && $form->isValid($req->getPost())) {
$message = new Message();
$message->fromArray($form->getValues(true));
$message->posted = new Doctrine_Expression('NOW()');
$message->save();
}
$this->view->form = $form;
$messages = Doctrine_Query::create()
->from(‘Message m’)
->orderBy(‘m.posted DESC’)
->execute();
$this->view->messages = $messages;
}
private function getForm()
{
$form = new Zend_Form();
$form->addElement(‘text’, ‘name’, array(
‘label’ => ‘Your name’,
‘required’ => true
));
$form->addElement(‘textarea’, ‘message’, array(
‘label’ => ‘Message’,
‘required’ => true,
‘rows’ => 4
));
$form->addElement(‘submit’, ‘send’);
return $form;
}
}
?>
application/views/scripts/index/index.phtml
<html>
<head>
<title>ZF & Doctrine example</title>
</head>
<body>
<h1>Submit a message:</h1>
<?=$this->form?>
<hr />
<h1>Messages posted:</h1>
<?php foreach ($this->messages as $message): ?>
<h2><?=$message->name?> (<?=$message->posted?>)</h2>
<?=$message->message?>
<?php endforeach; ?>
</body>
</html>
Un blog technologique, sur le développement, sur le Zend Framework, sur PHP et aussi une petite touche d'entreprenariat.
9 réponse to Zend framework : Utiliser Zend Framework et Doctrine (Auteur Ruben Vermeersch, Traduction Fred Blanc)
miboo
novembre 27th, 2008 at 14 h 04 min
Beau travail !
Juste pour savoir, quel logiciel tu utilises pour afficher ton arborescence ?
Frédéric Blanc
novembre 27th, 2008 at 15 h 49 min
Merci Miboo… même si je n’ai que très peu de mérite vu que je n’ai fait que traduire l’article de Ruben.
Pour l’arborescence, je pense que ce sont des captures réalisées sous Mac.
Personnellement, pour mes captures d’images ou vidéo, j’utilise Jing qui répond très bien à mes besoins.
Cordialement,
Fred
RubenV
novembre 30th, 2008 at 17 h 38 min
Non non, c’est absolutement pas un Mac!
J’utilise Linux, Ubuntu 8.10 et l’arborescence, c’est Nautilus (qui fait partie de GNOME).
Ruben
Frédéric Blanc
décembre 1st, 2008 at 1 h 00 min
Oui Ruben, je te prie de m’excuser. Je me suis laissé berner par le fait que l’affichage des dossiers était proche de ce que j’ai sous Mac.
1000 excuses à toi et à Nautilus
Stéphan Claveirolle
novembre 12th, 2009 at 11 h 52 min
Bonjour,
Toute d’abord merci Ruben pour cet article et merci Fred pour la traduction française.
L’ensemble est relativement clair et agréable à lire.
Cela donne la motivation nécessaire pour se lancer dans un projet ZF/Doctrine sans plus attendre.
Toutefois, depuis l’édition de cet article, le 30 novembre 2008, il y a eu pas mal d’évolution sur le ZF (et j’imagine aussi en ce qui concernent Doctrine). Ces modifications ne rendent-elles pas caduque certains aspects du code proposé ?
La dernière annonce de « fusion » Zend Framework / Doctrine laisse également penser que l’intégration sera plus simple et intuitive dans le futur (proche ?).
Qu’en est-il de l’utilisation du ZF sous Zend Studio (Eclipse), au niveau des « wizards » de création des classes/fichiers ?
Cordialement,
S.C.
Stéphan Claveirolle
novembre 12th, 2009 at 14 h 58 min
Apparemment d’autres se sont penchés sur la question :
http://www.danceric.net/2009/06/06/doctrine-orm-and-zend-framework/
Cordialement,
S.C.
abdellah
décembre 14th, 2009 at 14 h 36 min
salut tout le monde et merci rubenV et Frédéric Blanc de l’explication que vous avez fait
je veut seulement connaitre commet je fait pour supprimer ou modifier un enregistrement avec doctrine et zend
merci d’avance
Stéphan Claveirolle
janvier 7th, 2010 at 18 h 54 min
Bonjour,
Je viens de mettre en place un début de projet PHP utilisant à la fois Zend Framework et Doctrine
Je travaille actuellement avec l’IDE Zend Studio et parfois je n’ai pas l’auto-complétion du code concernant les objets du modèle Doctrine.
Est-ce que quelqu’un ici a déjà eu ce genre de problème ?
Exemple :
$user = new User();
$user->name = ‘stephan’;
// La complétion de code fonctionne bien et lorsque je fais un + après $user, Zend Studio me propose bien les propriétés de mon objet $user (donc entre autre $user->name).
Si je récupère un Doctrine_Record via une requête DQL de sélection de mes utilisateurs et que je fais un foreach dessus pour traiter chaque utilisateur, je ne peux plus accéder à leurs propriétés via l’auto-complétion.
En même temps, il y a une différence entre l’objet métier lui même et un objet Doctrine_Record.
Mais peut-on s’arranger afin de conserver tout de même l’auto-complétion à votre avis ?
Cordialement,
S.C.
Ludovic
mai 26th, 2010 at 14 h 30 min
Un grand merci pour ce super tutoriel qui m’a permis d’intégrer sans difficultés Doctrine à Zend Framework.
Cependant, une question persiste, j’ai vu que les clés étrangères des tables de la base de données n’étaient pas générées avec le script de Doctrine_Cli dans les modèles ou le fichier YAML.
Savez-vous s’il est possible de les générer automatiquement ? Ou faut-il que je le fasse manuellement sur mes 90 classes modèles et le fichier YAML
?
Merci d’avance.