Przeglądaj źródła

Added some french doc

git-svn-id: http://framework.zend.com/svn/framework/standard/trunk@22345 44c647ce-9c0f-0410-b52a-842ac1e357ba
doctorrock83 15 lat temu
rodzic
commit
02efa523c6

+ 753 - 0
documentation/manual/fr/tutorials/quickstart-create-model.xml

@@ -0,0 +1,753 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- EN-Revision: 22312 -->
+<!-- Reviewed: no -->
+<sect1 id="learning.quickstart.create-model">
+    <title>Créer un modèle et une table en base de données</title>
+
+    <para>
+        Avant de démarrer, considérons ceci: où vont se trouver ces classes et comment les retrouver?
+        Le projet par défaut que nous avons conçu instancie un autoloader. Nous pouvons lui attacher
+        d'autres autoloaders pour qu'il puisse trouver des classes différentes. Typiquement nous
+        voulons que nos classes MVC soient groupées sous une même arborescence -- dans ce cas,
+        <filename>application/</filename> -- et nous utiliserons un préfixe commun.
+    </para>
+
+    <para>
+        <classname>Zend_Controller_Front</classname> a une notion de "modules", qui sont des
+        mini-applications individuelles. Les modules reflètent la structure de répertoires que la
+        commande <command>zf</command> crée sous <filename>application/</filename>, et toutes les
+        classes à l'intérieur sont supposées commencer par un préfixe étant le nom du module.
+        <filename>application/</filename> est lui-même un module -- le module "default" ou
+        "application". Ainsi, nous allons vouloir configurer un autoload pour les ressources sous
+        ce dossier.
+    </para>
+
+    <para>
+        <classname>Zend_Application_Module_Autoloader</classname> propose la fonctionnalité nécessaire
+        à la correspondance entre les ressources d'un module et ses dossiers, il propose pour cela
+        un mécanisme de nommage standard. Une instance de la classe est créee par défaut pendant
+        l'initialisation de l'objet de bootstrap et utilisera le préfixe de module "Application".
+        De ce fait, nos classes de modèles, formulaires, et tables commenceront toutes par le préfixe
+        de classe "Application_".
+    </para>
+
+   <para>
+        Maintenant voyons de quoi est fait un livre d'or. Typiquement il existe simplement une liste
+        d'entrées avec un <emphasis>commentaire</emphasis>, <emphasis>timestamp</emphasis>, et souvent
+        une <emphasis>adresse email</emphasis>. En supposant que nous stockons cela dans une base de
+        données, nous aurons aussi besoin d'un <emphasis>identifiant unique</emphasis> pour chaque
+        entrée. Nous voudrons aussi sauvegarder une entrée, récupérer une entrée individuelle ou encore
+        récupérer toutes les entrées. De ce fait, l'<acronym>API</acronym> du modèle d'un simple livre
+        d'or ressemblerait à ceci:
+    </para>
+
+    <programlisting language="php"><![CDATA[
+// application/models/Guestbook.php
+
+class Application_Model_Guestbook
+{
+    protected $_comment;
+    protected $_created;
+    protected $_email;
+    protected $_id;
+
+    public function __set($name, $value);
+    public function __get($name);
+
+    public function setComment($text);
+    public function getComment();
+
+    public function setEmail($email);
+    public function getEmail();
+
+    public function setCreated($ts);
+    public function getCreated();
+
+    public function setId($id);
+    public function getId();
+}
+
+class Application_Model_GuestbookMapper
+{
+    public function save(Application_Model_Guestbook $guestbook);
+    public function find($id);
+    public function fetchAll();
+}
+]]></programlisting>
+
+    <para>
+        <methodname>__get()</methodname> et <methodname>__set()</methodname> nous simpliferons l'accès
+        aux attributs et proxieront vers les autres getters et setters. Ils nous permettront de même
+        de nous assurer que seuls les attributs que nous avons définis seront accessibles dans l'objet.
+    </para>
+
+    <para>
+        <methodname>find()</methodname> et <methodname>fetchAll()</methodname> permettent de récupérer
+        une seule entrée ou toutes les entrées alors que <methodname>save()</methodname> offrira la
+        possibilité de stocker une entrée dans le support de stockage.
+    </para>
+
+    <para>
+        Maintenant à partir de là, nous pouvons commecer à penser en terme de base de données.
+    </para>
+
+    <para>
+        Nous devons d'abord intialiser une ressource <classname>Db</classname>. Comme pour les
+        ressources <classname>Layout</classname> et <classname>View</classname>, nous pouvons utiliser
+        de la configuration pour <classname>Db</classname>. Cela est possible au moyen de la commande
+        <command>zf configure db-adapter</command>:
+    </para>
+
+    <programlisting language="shell"><![CDATA[
+% zf configure db-adapter \
+> 'adapter=PDO_SQLITE&dbname=APPLICATION_PATH "/../data/db/guestbook.db"' \
+> production
+A db configuration for the production has been written to the application config file.
+
+% zf configure db-adapter \
+> 'adapter=PDO_SQLITE&dbname=APPLICATION_PATH "/../data/db/guestbook-testing.db"' \
+> testing
+A db configuration for the production has been written to the application config file.
+
+% zf configure db-adapter \
+> 'adapter=PDO_SQLITE&dbname=APPLICATION_PATH "/../data/db/guestbook-dev.db"' \
+> development
+A db configuration for the production has been written to the application config file.
+]]></programlisting>
+
+    <para>
+        Editez maintenant le fichier <filename>application/configs/application.ini</filename>, vous
+        verrez que les lignes suivantes ont été ajoutées dans les sections appropriées:
+    </para>
+
+    <programlisting language="ini"><![CDATA[
+; application/configs/application.ini
+
+[production]
+; ...
+resources.db.adapter = "PDO_SQLITE"
+resources.db.params.dbname = APPLICATION_PATH "/../data/db/guestbook.db"
+
+[testing : production]
+; ...
+resources.db.adapter = "PDO_SQLITE"
+resources.db.params.dbname = APPLICATION_PATH "/../data/db/guestbook-testing.db"
+
+[development : production]
+; ...
+resources.db.adapter = "PDO_SQLITE"
+resources.db.params.dbname = APPLICATION_PATH "/../data/db/guestbook-dev.db"
+]]></programlisting>
+
+    <para>
+        Votre fichier de configuration final devrait ressembler à ceci:
+    </para>
+
+    <programlisting language="ini"><![CDATA[
+; application/configs/application.ini
+
+[production]
+phpSettings.display_startup_errors = 0
+phpSettings.display_errors = 0
+bootstrap.path = APPLICATION_PATH "/Bootstrap.php"
+bootstrap.class = "Bootstrap"
+appnamespace = "Application"
+resources.frontController.controllerDirectory = APPLICATION_PATH "/controllers"
+resources.frontController.params.displayExceptions = 0
+resources.layout.layoutPath = APPLICATION_PATH "/layouts/scripts"
+resources.view[] =
+resources.db.adapter = "PDO_SQLITE"
+resources.db.params.dbname = APPLICATION_PATH "/../data/db/guestbook.db"
+
+[staging : production]
+
+[testing : production]
+phpSettings.display_startup_errors = 1
+phpSettings.display_errors = 1
+resources.db.adapter = "PDO_SQLITE"
+resources.db.params.dbname = APPLICATION_PATH "/../data/db/guestbook-testing.db"
+
+[development : production]
+phpSettings.display_startup_errors = 1
+phpSettings.display_errors = 1
+resources.db.adapter = "PDO_SQLITE"
+resources.db.params.dbname = APPLICATION_PATH "/../data/db/guestbook-dev.db"
+]]></programlisting>
+
+    <para>
+        Notez que la/les base(s) de données seront stockées sous <filename>data/db/</filename>. Créez ces dossiers
+        et affectez leur les bons droits. Sur les systèmes Unix utilisez:
+    </para>
+
+    <programlisting language="shell"><![CDATA[
+% mkdir -p data/db; chmod -R a+rwX data
+]]></programlisting>
+
+    <para>
+        Sur Windows, vous devrez créer le dossier avec l'explorateur et lui donner les bonnes permissions pour que
+        tout le monde puisse y écrire.
+    </para>
+
+    <para>
+        Dès lors, nous possédons une connexion à une base de données, dans notre cas il s'agit de Sqlite et la base
+        est placée sous le dossier <filename>application/data/</filename>. Créons maintenant une table pour
+        stocker nos entrées de livre d'or.
+    </para>
+
+    <programlisting language="sql"><![CDATA[
+-- scripts/schema.sqlite.sql
+--
+-- You will need load your database schema with this SQL.
+
+CREATE TABLE guestbook (
+    id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
+    email VARCHAR(32) NOT NULL DEFAULT 'noemail@test.com',
+    comment TEXT NULL,
+    created DATETIME NOT NULL
+);
+
+CREATE INDEX "id" ON "guestbook" ("id");
+]]></programlisting>
+
+    <para>
+        Puis pour ne pas travailler dans le vide, créons quelques enregistrements de départ.
+    </para>
+
+    <programlisting language="sql"><![CDATA[
+-- scripts/data.sqlite.sql
+--
+-- You can begin populating the database with the following SQL statements.
+
+INSERT INTO guestbook (email, comment, created) VALUES
+    ('ralph.schindler@zend.com',
+    'Hello! Hope you enjoy this sample zf application!',
+    DATETIME('NOW'));
+INSERT INTO guestbook (email, comment, created) VALUES
+    ('foo@bar.com',
+    'Baz baz baz, baz baz Baz baz baz - baz baz baz.',
+    DATETIME('NOW'));
+]]></programlisting>
+
+    <para>
+        Maintenant que nous avons la définition de la base de données ainsi que des données, créons un
+        script qui pourra être lancé pour entièrement initialiser la base de données de manière
+        autonomme. Bien sûr cela ne sera pas nécessaire en production. Créez le script
+        <filename>scripts/load.sqlite.php</filename> avec le contenu suivant:
+    </para>
+
+    <programlisting language="php"><![CDATA[
+// scripts/load.sqlite.php
+
+/**
+ * Script pour créer et charger la base
+ */
+
+// Initialise le chemin vers l'application et l'autoload
+defined('APPLICATION_PATH')
+    || define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../application'));
+set_include_path(implode(PATH_SEPARATOR, array(
+    APPLICATION_PATH . '/../library',
+    get_include_path(),
+)));
+require_once 'Zend/Loader/Autoloader.php';
+Zend_Loader_Autoloader::getInstance();
+
+// Definit des options CLI
+$getopt = new Zend_Console_Getopt(array(
+    'withdata|w' => 'Load database with sample data',
+    'env|e-s'    => 'Application environment for which to create database (defaults to development)',
+    'help|h'     => 'Help -- usage message',
+));
+try {
+    $getopt->parse();
+} catch (Zend_Console_Getopt_Exception $e) {
+    // Mauvaises options passées: afficher l'aide
+    echo $e->getUsageMessage();
+    return false;
+}
+
+// Si l'aid eest demandée, l'afficher
+if ($getopt->getOption('h')) {
+    echo $getopt->getUsageMessage();
+    return true;
+}
+
+// Initialise des valeurs selon la présence ou absence d'options CLI
+$withData = $getopt->getOption('w');
+$env      = $getopt->getOption('e');
+defined('APPLICATION_ENV')
+    || define('APPLICATION_ENV', (null === $env) ? 'development' : $env);
+
+// Initialise Zend_Application
+$application = new Zend_Application(
+    APPLICATION_ENV,
+    APPLICATION_PATH . '/configs/application.ini'
+);
+
+// Initialise et récupère la ressoucre DB
+$bootstrap = $application->getBootstrap();
+$bootstrap->bootstrap('db');
+$dbAdapter = $bootstrap->getResource('db');
+
+// Informons l'utilisateur de ce qui se passe (nous créons une base de données
+// ici)
+if ('testing' != APPLICATION_ENV) {
+    echo 'Writing Database Guestbook in (control-c to cancel): ' . PHP_EOL;
+    for ($x = 5; $x > 0; $x--) {
+        echo $x . "\r"; sleep(1);
+    }
+}
+
+// Vérifions si un fichier pour la base existe déja
+$options = $bootstrap->getOption('resources');
+$dbFile  = $options['db']['params']['dbname'];
+if (file_exists($dbFile)) {
+    unlink($dbFile);
+}
+
+// Chargement du fichier de la base de données.
+try {
+    $schemaSql = file_get_contents(dirname(__FILE__) . '/schema.sqlite.sql');
+    // utilise la connexion directement pour charger le sql
+    $dbAdapter->getConnection()->exec($schemaSql);
+    chmod($dbFile, 0666);
+
+    if ('testing' != APPLICATION_ENV) {
+        echo PHP_EOL;
+        echo 'Database Created';
+        echo PHP_EOL;
+    }
+
+    if ($withData) {
+        $dataSql = file_get_contents(dirname(__FILE__) . '/data.sqlite.sql');
+        // utilise la connexion directement pour charger le sql
+        $dbAdapter->getConnection()->exec($dataSql);
+        if ('testing' != APPLICATION_ENV) {
+            echo 'Data Loaded.';
+            echo PHP_EOL;
+        }
+    }
+
+} catch (Exception $e) {
+    echo 'AN ERROR HAS OCCURED:' . PHP_EOL;
+    echo $e->getMessage() . PHP_EOL;
+    return false;
+}
+
+// Ce script sera lancé depuis la ligne de commandes
+return true;
+]]></programlisting>
+
+    <para>
+        Exécutons ce script. Depuis un terminal ou un invite DOS, effectuez:
+    </para>
+
+    <programlisting language="shell"><![CDATA[
+% php scripts/load.sqlite.php --withdata
+]]></programlisting>
+
+    <para>
+        Vous devriez voir ceci:
+    </para>
+
+    <programlisting language="text"><![CDATA[
+path/to/ZendFrameworkQuickstart/scripts$ php load.sqlite.php --withdata
+Writing Database Guestbook in (control-c to cancel):
+1
+Database Created
+Data Loaded.
+]]></programlisting>
+
+    <para>
+        Nous avons maintenant une base de données et une table pour notre application de livre d'or.
+        Les prochaines étapes seront de créer le code applicatif. Ceci incluera une source de données
+        (dans notre cas nous utiliserons <classname>Zend_Db_Table</classname>), un datamapper pour
+        connecter cette source à notre modèle et enfin un contrôleur pour intéragir avec le modèle
+        et afficher du contenu divers.
+    </para>
+
+    <para>
+        Nous allons utiliser un <ulink url="http://martinfowler.com/eaaCatalog/tableDataGateway.html">Table
+        Data Gateway</ulink> pour se connecter à notre source de données; <classname>Zend_Db_Table</classname>
+        propose cette fonctionnalité. Créons les classes basées sur <classname>Zend_Db_Table</classname>.
+        Comme nous avons opéré pour les layouts ou la base, nous pouvons utiliser la commande
+        <command>zf</command> pour nous aider, avec la commande complète
+        <command>create db-table</command>. Celle-ci prend deux arguments au minimum, le nom de la classe à
+        créer et la table qui y fera référence.
+    </para>
+
+    <programlisting language="shell"><![CDATA[
+% zf create db-table Guestbook guestbook
+Creating a DbTable at application/models/DbTable/Guestbook.php
+Updating project profile 'zfproject.xml'
+]]></programlisting>
+
+    <para>
+        En regardant l'orborescence du projet, un nouveau dossier
+        <filename>application/models/DbTable/</filename> a été crée contenant le fichier
+        <filename>Guestbook.php</filename>. Si vous ouvrez ce fichier, vous y verrez le contenu suivant:
+    </para>
+
+    <programlisting language="php"><![CDATA[
+// application/models/DbTable/Guestbook.php
+
+/**
+ * This is the DbTable class for the guestbook table.
+ */
+class Application_Model_DbTable_Guestbook extends Zend_Db_Table_Abstract
+{
+    /** Table name */
+    protected $_name    = 'guestbook';
+}
+]]></programlisting>
+
+    <para>
+        Notez le préfixe de classe: <classname>Application_Model_DbTable</classname>. Le premier segment
+        est "Application", le nom du module, puis vient le nom du composant "Model_DbTable" qui est lié
+        au dossier <filename>models/DbTable/</filename> du module.
+    </para>
+
+    <para>
+        Pour étendre <classname>Zend_Db_Table</classname>, seuls un nom de table et éventuellement un
+        nom de clé primaire (si ce n'est pas "id") sont nécessaires.
+    </para>
+
+    <para>
+        Créons maintenant un <ulink url="http://martinfowler.com/eaaCatalog/dataMapper.html">Data
+            Mapper</ulink>. Un <emphasis>Data Mapper</emphasis> fait correspondre un objet métier à la
+        base de données. Dans notre cas <classname>Application_Model_Guestbook</classname> vers la
+        source de données <classname>Application_Model_DbTable_Guestbook</classname>. Une
+        <acronym>API</acronym> typique pour un data mapper est:
+    </para>
+
+    <programlisting language="php"><![CDATA[
+// application/models/GuestbookMapper.php
+
+class Application_Model_GuestbookMapper
+{
+    public function save($model);
+    public function find($id, $model);
+    public function fetchAll();
+}
+]]></programlisting>
+
+    <para>
+        En plus de ces méthodes nous allons ajouter des méthodes pour affecter/récupérer l'objet
+        Table Data Gateway. Pour créer la classe initiale, utilsez l'outil CLI
+        <command>zf</command>:
+    </para>
+
+    <programlisting language="shell"><![CDATA[
+% zf create model GuestbookMapper
+Creating a model at application/models/GuestbookMapper.php
+Updating project profile '.zfproject.xml'
+]]></programlisting>
+
+    <para>
+        Maintenant, éditez la classe <classname>Application_Model_GuestbookMapper</classname> dans
+        <filename>application/models/GuestbookMapper.php</filename> pour y voir ceci:
+    </para>
+
+    <programlisting language="php"><![CDATA[
+// application/models/GuestbookMapper.php
+
+class Application_Model_GuestbookMapper
+{
+    protected $_dbTable;
+
+    public function setDbTable($dbTable)
+    {
+        if (is_string($dbTable)) {
+            $dbTable = new $dbTable();
+        }
+        if (!$dbTable instanceof Zend_Db_Table_Abstract) {
+            throw new Exception('Invalid table data gateway provided');
+        }
+        $this->_dbTable = $dbTable;
+        return $this;
+    }
+
+    public function getDbTable()
+    {
+        if (null === $this->_dbTable) {
+            $this->setDbTable('Application_Model_DbTable_Guestbook');
+        }
+        return $this->_dbTable;
+    }
+
+    public function save(Application_Model_Guestbook $guestbook)
+    {
+        $data = array(
+            'email'   => $guestbook->getEmail(),
+            'comment' => $guestbook->getComment(),
+            'created' => date('Y-m-d H:i:s'),
+        );
+
+        if (null === ($id = $guestbook->getId())) {
+            unset($data['id']);
+            $this->getDbTable()->insert($data);
+        } else {
+            $this->getDbTable()->update($data, array('id = ?' => $id));
+        }
+    }
+
+    public function find($id, Application_Model_Guestbook $guestbook)
+    {
+        $result = $this->getDbTable()->find($id);
+        if (0 == count($result)) {
+            return;
+        }
+        $row = $result->current();
+        $guestbook->setId($row->id)
+                  ->setEmail($row->email)
+                  ->setComment($row->comment)
+                  ->setCreated($row->created);
+    }
+
+    public function fetchAll()
+    {
+        $resultSet = $this->getDbTable()->fetchAll();
+        $entries   = array();
+        foreach ($resultSet as $row) {
+            $entry = new Application_Model_Guestbook();
+            $entry->setId($row->id)
+                  ->setEmail($row->email)
+                  ->setComment($row->comment)
+                  ->setCreated($row->created);
+            $entries[] = $entry;
+        }
+        return $entries;
+    }
+}
+]]></programlisting>
+
+    <para>
+        Maintenant il faut créer la classe de modèle. Une fois de plus, nous utiliserons la commande
+        <command>zf create model</command>:
+    </para>
+
+    <programlisting language="shell"><![CDATA[
+% zf create model Guestbook
+Creating a model at application/models/Guestbook.php
+Updating project profile '.zfproject.xml'
+]]></programlisting>
+
+    <para>
+        Nous allons modifier cette classe <acronym>PHP</acronym> vide pour simplifier le remplissage
+        du modèle via un tableau dans le constructeur ou une méthode
+        <methodname>setOptions()</methodname>. Le code final de la classe de modèle stockée dans
+        <filename>application/models/Guestbook.php</filename> devrait ressembler à ceci:
+    </para>
+
+    <programlisting language="php"><![CDATA[
+// application/models/Guestbook.php
+
+class Application_Model_Guestbook
+{
+    protected $_comment;
+    protected $_created;
+    protected $_email;
+    protected $_id;
+
+    public function __construct(array $options = null)
+    {
+        if (is_array($options)) {
+            $this->setOptions($options);
+        }
+    }
+
+    public function __set($name, $value)
+    {
+        $method = 'set' . $name;
+        if (('mapper' == $name) || !method_exists($this, $method)) {
+            throw new Exception('Invalid guestbook property');
+        }
+        $this->$method($value);
+    }
+
+    public function __get($name)
+    {
+        $method = 'get' . $name;
+        if (('mapper' == $name) || !method_exists($this, $method)) {
+            throw new Exception('Invalid guestbook property');
+        }
+        return $this->$method();
+    }
+
+    public function setOptions(array $options)
+    {
+        $methods = get_class_methods($this);
+        foreach ($options as $key => $value) {
+            $method = 'set' . ucfirst($key);
+            if (in_array($method, $methods)) {
+                $this->$method($value);
+            }
+        }
+        return $this;
+    }
+
+    public function setComment($text)
+    {
+        $this->_comment = (string) $text;
+        return $this;
+    }
+
+    public function getComment()
+    {
+        return $this->_comment;
+    }
+
+    public function setEmail($email)
+    {
+        $this->_email = (string) $email;
+        return $this;
+    }
+
+    public function getEmail()
+    {
+        return $this->_email;
+    }
+
+    public function setCreated($ts)
+    {
+        $this->_created = $ts;
+        return $this;
+    }
+
+    public function getCreated()
+    {
+        return $this->_created;
+    }
+
+    public function setId($id)
+    {
+        $this->_id = (int) $id;
+        return $this;
+    }
+
+    public function getId()
+    {
+        return $this->_id;
+    }
+}
+]]></programlisting>
+
+    <para>
+        Enfin, pour connecter tous ces éléments ensemble, créons un contrôleur qui listera les entrées
+        de la base de données.
+    </para>
+
+    <para>
+        Pour créer le nouveau contrôleur, utilisez la commande <command>zf create controller</command>:
+    </para>
+
+    <programlisting language="shell"><![CDATA[
+% zf create controller Guestbook
+Creating a controller at
+    application/controllers/GuestbookController.php
+Creating an index action method in controller Guestbook
+Creating a view script for the index action method at
+    application/views/scripts/guestbook/index.phtml
+Creating a controller test file at
+    tests/application/controllers/GuestbookControllerTest.php
+Updating project profile '.zfproject.xml'
+]]></programlisting>
+
+    <para>
+        Ceci va créer <classname>GuestbookController</classname> dans
+        <filename>application/controllers/GuestbookController.php</filename>, avec une seule action
+        <methodname>indexAction()</methodname>. Un script de vue sera aussi crée pour ce contrôleur,
+        il sera logé dans <filename>application/views/scripts/guestbook/</filename>, avec une vue
+        pour l'action index.
+    </para>
+
+    <para>
+        Nous allons utiliser l'action "index" pour lister toutes les entrées du livre d'or.
+    </para>
+
+    <para>
+        Un aterrissage sur <methodname>indexAction()</methodname> devra lister toutes les
+        entrées du livre d'or. Ceci ressemblera à ce qui suit:
+    </para>
+
+    <programlisting language="php"><![CDATA[
+// application/controllers/GuestbookController.php
+
+class GuestbookController extends Zend_Controller_Action
+{
+    public function indexAction()
+    {
+        $guestbook = new Application_Model_GuestbookMapper();
+        $this->view->entries = $guestbook->fetchAll();
+    }
+}
+]]></programlisting>
+
+    <para>
+        Et bien sûr un script de vue sera nécessaire. Editez
+        <filename>application/views/scripts/guestbook/index.phtml</filename> pour y
+        inclure ceci:
+    </para>
+
+    <programlisting language="php"><![CDATA[
+<!-- application/views/scripts/guestbook/index.phtml -->
+
+<p><a href="<?php echo $this->url(
+    array(
+        'controller' => 'guestbook',
+        'action'     => 'sign'
+    ),
+    'default',
+    true) ?>">Sign Our Guestbook</a></p>
+
+Guestbook Entries: <br />
+<dl>
+    <?php foreach ($this->entries as $entry): ?>
+    <dt><?php echo $this->escape($entry->email) ?></dt>
+    <dd><?php echo $this->escape($entry->comment) ?></dd>
+    <?php endforeach ?>
+</dl>
+]]></programlisting>
+
+    <note>
+        <title>Checkpoint</title>
+
+        <para>
+            Naviguez maintenant vers "http://localhost/guestbook". Vous devriez voir ceci
+            apparaitre dans votre navigateur:
+        </para>
+
+        <para>
+            <inlinegraphic width="525" scale="100" align="center" valign="middle"
+                fileref="figures/learning.quickstart.create-model.png" format="PNG" />
+        </para>
+    </note>
+
+    <note>
+        <title>Utiliser le script de chargement des données</title>
+
+        <para>
+            Le script de chargement des données montré dans la section en question
+            (<filename>scripts/load.sqlite.php</filename>) peut être utilisé pour créer une base
+            de données pour chaque environnement défini et la remplir de données d'exemple. En
+            interne, il utilise <classname>Zend_Console_Getopt</classname>, qui permet de préciser
+            des options à la commande. Si vous passez "-h" ou "--help", toutes les options
+            disponibles seront affichées:
+        </para>
+
+        <programlisting language="php"><![CDATA[
+Usage: load.sqlite.php [ options ]
+--withdata|-w         Load database with sample data
+--env|-e [  ]         Application environment for which to create database
+                      (defaults to development)
+--help|-h             Help -- usage message)]]
+]]></programlisting>
+
+        <para>
+            L'option "-e" permet de préciser la valeur de la constante
+            <constant>APPLICATION_ENV</constant> -- ce qui en effet permet de créer une base de
+            données SQLite pour chaque environnement défini. N'oubliez pas l'envrionnement
+            lorsque vous utilisez ce script.
+        </para>
+    </note>
+</sect1>

+ 524 - 0
documentation/manual/fr/tutorials/quickstart-create-project.xml

@@ -0,0 +1,524 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- EN-Revision: 22312 -->
+<!-- Reviewed: no -->
+<sect1 id="learning.quickstart.create-project">
+    <title>Créer votre projet</title>
+
+    <para>
+        Afin de créer un projet, vous devez d'abord télécharger et extraire Zend Framework.
+    </para>
+
+    <sect2 id="learning.quickstart.create-project.install-zf">
+        <title>Installer Zend Framework</title>
+
+        <para>
+            La manière la plus simple d'obtenir Zend Framework avec une pile <acronym>PHP</acronym>
+            complète est d'installer <ulink url="http://www.zend.com/en/products/server-ce/downloads">
+            Zend Server</ulink>. Zend Server possède des installeurs natifs pour Mac OSX, Windows, Fedora Core,
+            et Ubuntu, ainsi qu'un installeur universel pour la plupart des distributions Linux.
+        </para>
+
+        <para>
+            Après avoir installé Zend Server, les fichiers du Framework devraient se trouver sous
+            <filename>/usr/local/zend/share/ZendFramework</filename> sur Mac OSX et Linux,
+            et <filename>C:\Program Files\Zend\ZendServer\share\ZendFramework</filename> sur
+            Windows. L'<constant>include_path</constant> aura déja été configuré pour inclure
+            Zend Framework.
+        </para>
+
+        <para>
+            Il reste bien sûr possible <ulink url="http://framework.zend.com/download/latest"> de télécharger
+            la dernière version de Zend Framework</ulink> et l'extraire; notez simplement où vous choisissez
+            de l'extraire.
+        </para>
+
+        <para>
+            Optionellement, vous pouvez ajouter le chemin vers le sous-dossier <filename>library/</filename>
+            de l'archive à l'<constant>include_path</constant> de votre <filename>php.ini</filename>.
+        </para>
+
+        <para>
+            Ca y est! Zend Framework est maintenant installé et prêt à l'emploi.
+        </para>
+    </sect2>
+
+    <sect2 id="learning.quickstart.create-project.create-project">
+        <title>Créer votre projet</title>
+
+        <note>
+            <title>Outil en ligne de commandes zf</title>
+
+            <para>
+                Dans la dossier <filename>bin/</filename> de votre installation de Zend Framework
+                se trouvent les scripts <filename>zf.sh</filename> et <filename>zf.bat</filename>
+                pour Unix et Windows respectivement. Notez le chemin absolu vers ces fichiers.
+            </para>
+
+            <para>
+                Partout ou vous voyez uyne référence à la commande <command>zf</command>, utilisez le chemin
+                absolu du script. Sur les système Unix, vous pouvez utiliser la fonctionnalité d'alias dans le
+                shell: <command>alias zf.sh=path/to/ZendFramework/bin/zf.sh</command>.
+            </para>
+
+            <para>
+                Si vous avez des problèmes pour configurer la commande <command>zf</command>, veuillez vous
+                référer <link linkend="zend.tool.framework.clitool">au manuel</link>.
+            </para>
+        </note>
+
+        <para>
+            Ouvrez un terminal (sous Windows, <command>Démarrer -> Exécuter</command>, puis
+            <command>cmd</command>). Naviguez vers un dossier dans lequel vous souhaitez démarrer un projet.
+            Puis, utilisez le chemin vers le script approprié et lancez:
+        </para>
+
+        <programlisting language="shell"><![CDATA[
+% zf create project quickstart
+]]></programlisting>
+
+        <para>
+            Cette commande crée un projet avec une structure basique incluant des contrôleurs et vues.
+            L'arbre va ressembler à ceci:
+        </para>
+
+        <programlisting language="text"><![CDATA[
+quickstart
+|-- application
+|   |-- Bootstrap.php
+|   |-- configs
+|   |   `-- application.ini
+|   |-- controllers
+|   |   |-- ErrorController.php
+|   |   `-- IndexController.php
+|   |-- models
+|   `-- views
+|       |-- helpers
+|       `-- scripts
+|           |-- error
+|           |   `-- error.phtml
+|           `-- index
+|               `-- index.phtml
+|-- library
+|-- public
+|   |-- .htaccess
+|   `-- index.php
+`-- tests
+    |-- application
+    |   `-- bootstrap.php
+    |-- library
+    |   `-- bootstrap.php
+    `-- phpunit.xml
+]]></programlisting>
+
+        <para>
+            Dès lors si vous n'avez pas ajouté Zend Framework à votre
+            <constant>include_path</constant>, nous vous recommandons de copier ou lier celui-ci dans
+            le dossier <filename>library/</filename> de votre projet. Dans ce cas vous devriez copier
+            récursivement (ou lier) <filename>library/Zend/</filename> de l'installation de
+            Zend Framework vers le dossier <filename>library/</filename> de votre projet. Sur les
+            systèmes Unix cela peut être effectué de la manière suivante:
+        </para>
+
+        <programlisting language="shell"><![CDATA[
+# Symlink:
+% cd library; ln -s path/to/ZendFramework/library/Zend .
+
+# Copy:
+% cd library; cp -r path/to/ZendFramework/library/Zend .
+]]></programlisting>
+
+        <para>
+            Sur Windows le plus simple sera d'utiliser l'explorateur.
+        </para>
+
+        <para>
+            Maintenant que le projet est crée, les principaux points à comprendre sont le
+            bootstrap, la configuration, les contrôleurs d'action et les vues.
+        </para>
+    </sect2>
+
+    <sect2 id="learning.quickstart.create-project.bootstrap">
+        <title>Le Bootstrap</title>
+
+        <para>
+            Votre classe <classname>Bootstrap</classname> définit les ressources (composants) à
+            initialiser. Par défaut, le <link linkend="zend.controller.front">contrôleur frontal
+            </link> est initialisé et il utilise <filename>application/controllers/</filename>
+            comme dossier de contrôleurs par défaut (nous reverrons cela). La classe ressemble à:
+        </para>
+
+        <programlisting language="php"><![CDATA[
+// application/Bootstrap.php
+
+class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
+{
+}
+]]></programlisting>
+
+        <para>
+            Comme vous le voyez, rien de plus n'est nécessaire pour commencer.
+        </para>
+    </sect2>
+
+    <sect2 id="learning.quickstart.create-project.configuration">
+        <title>Configuration</title>
+
+        <para>
+            Le Zend Framework lui-même n'a pas besoin de configuration, mais l'application oui. La
+            configuration par défaut est placée sous
+            <filename>application/configs/application.ini</filename> et contient des directives de base
+            pour régler l'environnement <acronym>PHP</acronym> (par exemple, activer ou désactiver le
+            rapport d'erreurs), indiquer le chemin vers votre classe de bootstrap (ainsi que son nom)
+            , et le chemin vers les contrôleurs d'action. Cela ressemble à:
+        </para>
+
+        <programlisting language="ini"><![CDATA[
+; application/configs/application.ini
+
+[production]
+phpSettings.display_startup_errors = 0
+phpSettings.display_errors = 0
+includePaths.library = APPLICATION_PATH "/../library"
+bootstrap.path = APPLICATION_PATH "/Bootstrap.php"
+bootstrap.class = "Bootstrap"
+appnamespace = "Application"
+resources.frontController.controllerDirectory = APPLICATION_PATH "/controllers"
+resources.frontController.params.displayExceptions = 0
+
+[staging : production]
+
+[testing : production]
+phpSettings.display_startup_errors = 1
+phpSettings.display_errors = 1
+
+[development : production]
+phpSettings.display_startup_errors = 1
+phpSettings.display_errors = 1
+]]></programlisting>
+
+        <para>
+            Plusieurs choses sont à connaitre concernant ce fichier. D'abord, si vous utilisez une
+            configuration basée sur des fichiers <acronym>INI</acronym>, vous pouvez faire usage des
+            constantes directement; <constant>APPLICATION_PATH</constant> est ici une constante. Aussi,
+            notez que plusieurs sections ont été définies: production, staging, testing, et
+            development. Les trois dernières héritent de la section "production". C'est une manière utile
+            d'organiser sa configuration et de s'assurer que les paramètres appropriés sont utilisés
+            pour chaque étape du développement de l'application.
+        </para>
+    </sect2>
+
+    <sect2 id="learning.quickstart.create-project.action-controllers">
+        <title>Contrôleurs d'action</title>
+
+        <para>
+            Les <emphasis>contrôleurs d'action</emphasis> de votre application contiennent la logique 'utile'
+            de celle-ci et font correspondre les requêtes aux bons modèles et aux bonnes vues.
+        </para>
+
+        <para>
+            Un contrôleur d'action devrait posséder une ou plusieurs méthodes se terminant par
+            "Action"; ces méthodes sont interrogées via le web. Par défaut, les URLs de Zend
+            Framework suivent le schéma <constant>/controller/action</constant>, où
+            "controller" correspond à la classe de contrôleur (sans le suffixe "Controller")
+            et "action" correspond à la méthode d'action (sans le suffixe "Action").
+        </para>
+
+        <para>
+            Typiquement, vous aurez toujours besoin d'un <classname>IndexController</classname>,
+            qui est utilisé par défaut et servira aussi la page d'accueil, et un
+            <classname>ErrorController</classname>, utilisé pour indiquer les erreurs
+            <acronym>HTTP</acronym> 404 (contrôleur ou action introuvable) et les erreurs
+            <acronym>HTTP</acronym> 500 (erreurs de l'application).
+        </para>
+
+        <para>
+            <classname>IndexController</classname> par défaut est défini comme suit:
+        </para>
+
+        <programlisting language="php"><![CDATA[
+// application/controllers/IndexController.php
+
+class IndexController extends Zend_Controller_Action
+{
+
+    public function init()
+    {
+        /* Initialisez le contrôleur et l'action ici */
+    }
+
+    public function indexAction()
+    {
+        // corps de l'action
+    }
+}
+]]></programlisting>
+
+        <para>
+            <classname>ErrorController</classname> par défaut est défini comme suit:
+        </para>
+
+        <programlisting language="php"><![CDATA[
+// application/controllers/ErrorController.php
+
+class ErrorController extends Zend_Controller_Action
+{
+
+    public function errorAction()
+    {
+        $errors = $this->_getParam('error_handler');
+
+        switch ($errors->type) {
+            case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ROUTE:
+            case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_CONTROLLER:
+            case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ACTION:
+
+                // 404 error -- controller or action not found
+                $this->getResponse()->setHttpResponseCode(404);
+                $this->view->message = 'Page not found';
+                break;
+            default:
+                // application error
+                $this->getResponse()->setHttpResponseCode(500);
+                $this->view->message = 'Application error';
+                break;
+        }
+
+        $this->view->exception = $errors->exception;
+        $this->view->request   = $errors->request;
+    }
+}
+]]></programlisting>
+
+        <para>
+            Notez que (1) <classname>IndexController</classname> ne contient pas de code réel,
+            et (2) <classname>ErrorController</classname> référence un attribut "view".
+            Ceci nous mène vers la section suivante.
+        </para>
+    </sect2>
+
+    <sect2 id="learning.quickstart.create-project.views">
+        <title>Vues</title>
+
+        <para>
+            Les vues dans Zend Framework sont écrites en <acronym>PHP</acronym> classique. Les scripts
+            de vues sont placés sous <filename>application/views/scripts/</filename>, ils sont
+            référencés plus tard dans les contrôleurs. Dans notre cas, nous avons un
+            <classname>IndexController</classname> et un <classname>ErrorController</classname>,
+            et nous avons ainsi des dossiers <filename>index/</filename> et
+            <filename>error/</filename> correspondants dans le dossier scripts des vues. Dans ces
+            dossiers, vous trouverez ou créerez des scripts de vue correspondants aux actions
+            exposées par les contrôleurs; dans le cas par défaut nous avons ainsi des scripts de
+            vue <filename>index/index.phtml</filename> et <filename>error/error.phtml</filename>.
+        </para>
+
+        <para>
+            Les scripts de vue peuvent contenir le code de présentation que vous voulez et utiliser
+            les tags <emphasis>&lt;?php</emphasis> ou <emphasis>?&gt;</emphasis> pour insérer du
+            <acronym>PHP</acronym>.
+        </para>
+
+        <para>
+            Ce qui suit présente le code par défaut de <filename>index/index.phtml</filename>:
+        </para>
+
+        <programlisting language="php"><![CDATA[
+<!-- application/views/scripts/index/index.phtml -->
+<style>
+
+    a:link,
+    a:visited
+    {
+        color: #0398CA;
+    }
+
+    span#zf-name
+    {
+        color: #91BE3F;
+    }
+
+    div#welcome
+    {
+        color: #FFFFFF;
+        background-image: url(http://framework.zend.com/images/bkg_header.jpg);
+        width:  600px;
+        height: 400px;
+        border: 2px solid #444444;
+        overflow: hidden;
+        text-align: center;
+    }
+
+    div#more-information
+    {
+        background-image: url(http://framework.zend.com/images/bkg_body-bottom.gif);
+        height: 100%;
+    }
+
+</style>
+<div id="welcome">
+    <h1>Welcome to the <span id="zf-name">Zend Framework!</span><h1 />
+    <h3>This is your project's main page<h3 />
+    <div id="more-information">
+        <p>
+            <img src="http://framework.zend.com/images/PoweredBy_ZF_4LightBG.png" />
+        </p>
+
+        <p>
+            Helpful Links: <br />
+            <a href="http://framework.zend.com/">Zend Framework Website</a> |
+            <a href="http://framework.zend.com/manual/en/">Zend Framework
+                Manual</a>
+        </p>
+    </div>
+</div>
+]]></programlisting>
+
+        <para>
+            Le script de vue <filename>error/error.phtml</filename> est plus intéréssant car il
+            inclut des conditions écrites en <acronym>PHP</acronym>:
+        </para>
+
+        <programlisting language="php"><![CDATA[
+<!-- application/views/scripts/error/error.phtml -->
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN";
+    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+  <title>Zend Framework Default Application</title>
+</head>
+<body>
+  <h1>An error occurred</h1>
+  <h2><?php echo $this->message ?></h2>
+
+  <?php if ('development' == $this->env): ?>
+
+  <h3>Exception information:</h3>
+  <p>
+      <b>Message:</b> <?php echo $this->exception->getMessage() ?>
+  </p>
+
+  <h3>Stack trace:</h3>
+  <pre><?php echo $this->exception->getTraceAsString() ?>
+  </pre>
+
+  <h3>Request Parameters:</h3>
+  <pre><?php echo var_export($this->request->getParams(), 1) ?>
+  </pre>
+  <?php endif ?>
+
+</body>
+</html>
+]]></programlisting>
+    </sect2>
+
+    <sect2 id="learning.quickstart.create-project.vhost">
+        <title>Creation d'un hôte virtuel</title>
+
+        <para>
+            Pour le quickstart nous supposerons que vous utilisez le <ulink
+                url="http://httpd.apache.org/">serveur web Apacher</ulink>. Zend Framework fonctionne
+                très bien avec d'autres serveurs -- y compris Microsoft Internet Information
+            Server, lighttpd, nginx, et plus -- mais la plupart des développeurs devraient être familiers
+            à Apache, et cela permet d'introduire la structure de dossiers de Zend Framework et les
+            capacités de réécriture.
+        </para>
+
+        <para>
+            Pour créer un vhost, vous devez connaitre l'emplacement du fichier
+            <filename>httpd.conf</filename>, et les emplacements des autres fichiers de configuration
+            protenciels. Voici quelques emplacements classiques:
+        </para>
+
+        <itemizedlist>
+            <listitem>
+                <para>
+                    <filename>/etc/httpd/httpd.conf</filename> (Fedora, RHEL, et autres)
+                </para>
+            </listitem>
+
+            <listitem>
+                <para>
+                    <filename>/etc/apache2/httpd.conf</filename> (Debian, Ubuntu, et autres)
+                </para>
+            </listitem>
+
+            <listitem>
+                <para>
+                    <filename>/usr/local/zend/etc/httpd.conf</filename> (Zend Server sur *nix)
+                </para>
+            </listitem>
+
+            <listitem>
+                <para>
+                    <filename>C:\Program Files\Zend\Apache2\conf</filename> (Zend Server sur Windows)
+                </para>
+            </listitem>
+        </itemizedlist>
+
+        <para>
+            Au sein de <filename>httpd.conf</filename> (ou <filename>httpd-vhosts.conf</filename>
+            sur certains systèmes), vous aurez besoin de deux choses. D'abord s'assurer que
+            <varname>NameVirtualHost</varname> est défini; typiquement à une valeur de "*:80".
+            Ensuite, définir les hôtes virtuels:
+        </para>
+
+        <programlisting language="apache"><![CDATA[
+<VirtualHost *:80>
+    ServerName quickstart.local
+    DocumentRoot /path/to/quickstart/public
+
+    SetEnv APPLICATION_ENV "development"
+
+    <Directory /path/to/quickstart/public>
+        DirectoryIndex index.php
+        AllowOverride All
+        Order allow,deny
+        Allow from all
+    </Directory>
+</VirtualHost>
+]]></programlisting>
+
+        <para>
+            Notons plusieurs points. D'abord le <varname>DocumentRoot</varname> pointe vers le dossier
+            <filename>public</filename> du projet; ceci signifie que seuls les fichiers sous cette
+            arborescence peuvent être servis directement par le serveur. Ensuite,
+            <varname>AllowOverride</varname>, <varname>Order</varname>, et
+            <varname>Allow</varname>; ces directives servent à autoriser l'utilisation de fichiers
+            <filename>htacess</filename> dans le projet. Pendant le développement, c'est une bonne
+            pratique car ça évite de redémarrer sans arrêt le serveur dès qu'un changement y est opéré;
+            cependant en production le contenu de <filename>htaccess</filename> devrait être reproduit
+            dans la configuration puis désactivé. Enfin notez <varname>SetEnv</varname>. Ici nous
+            renseignons une variable d'environnement pour l'hôte virtuel, celle-ci sera récupérée
+            dans <filename>index.php</filename> et utilisée pour affecter la constante
+            <constant>APPLICATION_ENV</constant> de l'application Zend Framework. En
+            production, vous pouvez oublier cette directive (dans un tel cas la valeur par défaut sera
+            "production") ou la préciser explicitement à la valeur "production".
+        </para>
+
+        <para>
+            Finalement, vous devrez ajouter une entrée au DNS ou au fichier d'hôtes
+            (<filename>hosts</filename>) pour la valeur de <varname>ServerName</varname>. Sur les
+            systèmes *nix, il s'agit de <filename>/etc/hosts</filename>; sur Windows, vous trouverez
+            normalement ce fichier sous <filename>C:\WINDOWS\system32\drivers\etc</filename>. Quel que
+            soit le système, l'entrée sera de la forme:
+        </para>
+
+        <programlisting language="text"><![CDATA[
+127.0.0.1 quickstart.local
+]]></programlisting>
+
+        <para>
+            Démarrez votre serveur web (ou redémarrez le), et tout devrait être prêt.
+        </para>
+    </sect2>
+
+    <sect2 id="learning.quickstart.create-project.checkpoint">
+        <title>Checkpoint</title>
+
+        <para>
+            Dès lors, vous devriez pouvoir démarrer votre application Zend Framework. Faites pointer votre
+            navigateur vers l'hôte configuré dans la section précédente et une page d'accueil devrait
+            s'afficher.
+        </para>
+    </sect2>
+</sect1>

+ 17 - 0
documentation/manual/fr/tutorials/view-placeholders-conclusion.xml

@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- EN-Revision: 22312 -->
+<!-- Reviewed: no -->
+<sect1 id="learning.view.placeholders.conclusion">
+    <title>View Placeholders: Conclusion</title>
+
+    <para>
+        Les objets placeholders de vue sont des manières simples et puissante de créer des layouts
+        de mise en page riches pour votre application. Vous pouvez utiliser des placeholders déja
+        fournis comme ceux abordés précedemment (<methodname>doctype()</methodname>,
+        <methodname>headTitle()</methodname>, <methodname>headLink()</methodname>  et
+        <methodname>headScript()</methodname>), ou utiliser l'aide générique
+        <methodname>placeholder()</methodname> pour agréger du contenu et le rendre de manière
+        personnalisée. Expérimentez les et visitez les sections appropriées du manuel pour découvrir
+        et tester des fonctionnalités supplémentaires qui vous seront sûrement utiles.
+    </para>
+</sect1>

+ 463 - 0
documentation/manual/fr/tutorials/view-placeholders-standard.xml

@@ -0,0 +1,463 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- EN-Revision: 22189 -->
+<!-- Reviewed: no -->
+<sect1 id="learning.view.placeholders.standard">
+    <title>Placeholders standards</title>
+
+    <para>
+        Dans la <link linkend="learning.view.placeholders.basics">section précédente</link>, nous
+        avons vu l'aide de vue <methodname>placeholder()</methodname> et comment l'utiliser pour
+        aggréger du contenu personnalisable. Dans ce chapitre, nous allons passer en revue quelques
+        placeholders concrets fournis avec Zend Framework, ainsi que la manière de les utiliser à
+        votre avantage pour créer des layouts complexes.
+    </para>
+
+    <para>
+        La plupart des placeholders fournis permettent de gérer le contenur de la section
+        <emphasis>&lt;head&gt;</emphasis> de la layout -- une zone qui ne peut typiquement pas être
+        manipulée directement par vos scripts de vue, mais que vous voulez tout de même traiter.
+        Par exemples: vous voudriez que votre titre se compose d'un certain contenu sur toutes les
+        pages mais aussi d'une partie dynamique relative au contrôleur/action en cours; aussi vous
+        voudriez préciser des fichiers <acronym>CSS</acronym> à charger basés sur la section de
+        l'application en cours; enfin vous pourriez avoir recours à des scripts JavaScript spécifiques
+        parfois, ou encore changer la déclaration de <acronym>DocType</acronym>.
+    </para>
+
+    <para>
+        Zend Framework est livré avec des implémentations de placeholder pour chacune de ces situations
+        et encore d'autres.
+    </para>
+
+    <sect2 id="learning.view.placeholders.standard.doctype">
+        <title>Changer le DocType</title>
+
+        <para>
+            Les déclarations de <acronym>DocType</acronym> sont difficiles à mémoriser et souvent
+            essentielles pour s'assurer que le navigateur rende correctement le contenu. L'aide de vue
+            <methodname>doctype()</methodname> permet d'utiliser des mnemonics pour spécifier un
+            <acronym>DocType</acronym>; aussi, d'autres aides de vues interrogeront l'aide
+            <methodname>doctype()</methodname> pour s'assurer que le contenu qu'elles génèrent est
+            conforme au <acronym>DocType</acronym> utilisé.
+        </para>
+
+        <para>
+            Par exemple si vous souhaitez utiliser la <acronym>DTD</acronym>
+            <acronym>XHTML1</acronym> Strict, vous pouvez simplement la préciser
+            comme ceci:
+        </para>
+
+        <programlisting language="php"><![CDATA[
+$this->doctype('XHTML1_STRICT');
+]]></programlisting>
+
+        <para>
+            Voici les autres mnemonics utilisables:
+        </para>
+
+        <variablelist>
+            <varlistentry>
+                <term>XHTML1_STRICT</term>
+
+                <listitem>
+                    <para>
+                        <acronym>XHTML</acronym> 1.0 Strict
+                    </para>
+                </listitem>
+            </varlistentry>
+
+            <varlistentry>
+                <term>XHTML1_TRANSITIONAL</term>
+
+                <listitem>
+                    <para>
+                        <acronym>XHTML</acronym> 1.0 Transitional
+                    </para>
+                </listitem>
+            </varlistentry>
+
+            <varlistentry>
+                <term>HTML4_STRICT</term>
+
+                <listitem>
+                    <para>
+                        <acronym>HTML</acronym> 4.01 Strict
+                    </para>
+                </listitem>
+            </varlistentry>
+
+            <varlistentry>
+                <term>HTML4_Loose</term>
+
+                <listitem>
+                    <para>
+                        <acronym>HTML</acronym> 4.01 Loose
+                    </para>
+                </listitem>
+            </varlistentry>
+
+            <varlistentry>
+                <term>HTML5</term>
+
+                <listitem>
+                    <para>
+                        <acronym>HTML</acronym> 5
+                    </para>
+                </listitem>
+            </varlistentry>
+        </variablelist>
+
+        <para>
+            Vous pouvez changer le type et rendre la déclaration en un seul appel:
+        </para>
+
+        <programlisting language="php"><![CDATA[
+echo $this->doctype('XHTML1_STRICT');
+]]></programlisting>
+
+        <para>
+            Cependant l'approche conseillée est de préciser le type dans le bootstrap et rendre l'aide
+            de vue dans la layout. Essayez d'ajouter ceci à votre classe de bootstrap:
+        </para>
+
+        <programlisting language="php"><![CDATA[
+class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
+{
+    protected function _initDocType()
+    {
+        $this->bootstrap('View');
+        $view = $this->getResource('View');
+        $view->doctype('XHTML1_STRICT');
+    }
+}
+]]></programlisting>
+
+        <para>
+            Puis, dans le script de layout, affichez simplement avec <function>echo</function> l'aide en
+            haut du fichier:
+        </para>
+
+        <programlisting language="php"><![CDATA[
+<?php echo $this->doctype() ?>
+<html>
+    <!-- ... -->
+]]></programlisting>
+
+        <para>
+            Ceci permet d'être sûr que les aides de vue diverses utiliseront cette déclaration,
+            que le docType est précisé avant le rendu du layout et qu'il n'existe qu'un seul endroit
+            logique pour le changer.
+        </para>
+    </sect2>
+
+    <sect2 id="learning.view.placeholders.standard.head-title">
+        <title>Spécifier le titre de la page</title>
+
+        <para>
+            Souvent, le site incluera le nom de la société dans le titre de la page et ajoutera
+            ensuite des informations basées sur la page en cours de lecture. Par exemple, le site
+            zend.com inclut la chaine "Zend.com" sur toutes les pages et y fait précèder des
+            informations relatives à la page en cours: "Zend Server - Zend.com". Dans Zend Framework,
+            l'aide de vue <methodname>headTitle()</methodname> peut vous simplifier cette tâche.
+        </para>
+
+        <para>
+            Au plus simple, l'aide <methodname>headTitle()</methodname> permet d'aggréger du contenu
+            pour la balise <emphasis>&lt;title&gt;</emphasis>; lorsque vous l'affichez, il assemble
+            son contenu dans l'ordre des ajouts. Pour contrôler l'ordre, les méthodes
+            <methodname>prepend()</methodname> et <methodname>append()</methodname> sont là, pour changer
+            le séparateur à utiliser entre les segments, utilisez la méthode
+            <methodname>setSeparator()</methodname>.
+        </para>
+
+        <para>
+            Typiquement vous devriez renseigner tous les segments communs à toutes les pages en bootstrap,
+            de la même manière que nous avions agit avec le doctype. Dans ce cas, nous allons écrire une
+            méthode <methodname>_initPlaceholders()</methodname> pour gérer tous les placeholders et préciser
+            un titre initial ainsi qu'un séparateur.
+        </para>
+
+        <programlisting language="php"><![CDATA[
+class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
+{
+    // ...
+
+    protected function _initPlaceholders()
+    {
+        $this->bootstrap('View');
+        $view = $this->getResource('View');
+        $view->doctype('XHTML1_STRICT');
+
+        // Précise le titre initial et le séparateur:
+        $view->headTitle('My Site')
+             ->setSeparator(' :: ');
+    }
+
+    // ...
+}
+]]></programlisting>
+
+        <para>
+            Dans un script de vue, nous voulons ajouter un nouveau segment:
+        </para>
+
+        <programlisting language="php"><![CDATA[
+<?php $this->headTitle()->append('Some Page'); // placé après les autres segments ?>
+<?php $this->headTitle()->prepend('Some Page'); // placé avant ?>
+]]></programlisting>
+
+        <para>
+            Dans notre layout, nous affichons simplement l'aide <methodname>headTitle()</methodname>:
+        </para>
+
+        <programlisting language="php"><![CDATA[
+<?php echo $this->doctype() ?>
+<html>
+    <?php echo $this->headTitle() ?>
+    <!-- ... -->
+]]></programlisting>
+
+        <para>
+            Le contenu suivant aura été généré:
+        </para>
+
+        <programlisting language="html"><![CDATA[
+<!-- Si append() a été utilisé: -->
+<title>My Site :: Some Page</title>
+
+<!-- Si prepend() a été utilisé: -->
+<title>Some Page :: My Site</title>
+]]></programlisting>
+    </sect2>
+
+    <sect2 id="learning.view.placeholders.standard.head-link">
+        <title>Spécifier des feuilles de style avec HeadLink</title>
+
+        <para>
+            Les bons développeurs <acronym>CSS</acronym> créront souvent une feuille de style
+            globale et des feuilles individuelles pour les sections spécifiques ou certaines pages
+            du site puis chargeront celles-ci plus tard conditionnellement afin de réduire
+            le nombre de données à transférer entre chaque requête. Le placeholder
+            <methodname>headLink()</methodname> permet de réaliser de telles aggrégations
+            conditionnelles de feuilles de style.
+        </para>
+
+        <para>
+            Pour cela, <methodname>headLink()</methodname> definit une certain nombre de méthodes
+            "virtuelles" (via surcharge) pour simplifier le tout. Celles qui vont nous concernet
+            sont <methodname>appendStylesheet()</methodname> et
+            <methodname>prependStylesheet()</methodname>. Chacune peut accepter jusqu'à quatre
+            arguments, <varname>$href</varname> (chemin relatif vers la feuille de style),
+            <varname>$media</varname> (le type <acronym>MIME</acronym>, par défaut "text/css"),
+            <varname>$conditionalStylesheet</varname> (à utiliser pour préciser une "condition"
+            à évaluer pour la feuille de style), et <varname>$extras</varname> (un tableau
+            associatif utiliser générallement pour renseigner une clé pour "media"). Dans la
+            plupart des cas, seul le premier argument suffira, le chemin relatif vers la feuille
+            de style.
+        </para>
+
+        <para>
+            Dans notre exemple, nous supposerons que toutes les pages ont besoin de charger une feuille
+            de style stockée dans "<filename>/styles/site.css</filename>" (relativement au document root);
+            nous allons préciser cela dans notre méthode de bootstrap
+            <methodname>_initPlaceholders()</methodname>.
+        </para>
+
+        <programlisting language="php"><![CDATA[
+class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
+{
+    // ...
+
+    protected function _initPlaceholders()
+    {
+        $this->bootstrap('View');
+        $view = $this->getResource('View');
+        $view->doctype('XHTML1_STRICT');
+
+        // Affecte le titre original et le séparateur:
+        $view->headTitle('My Site')
+             ->setSeparator(' :: ');
+
+        // Affecte la feuille de style originale:
+        $view->headLink()->prependStylesheet('/styles/site.css');
+    }
+
+    // ...
+}
+]]></programlisting>
+
+        <para>
+            Plus tard, dans un contrôleur par exemple, nous pouvons rajouter des feuilles de
+            style:
+        </para>
+
+        <programlisting language="php"><![CDATA[
+<?php $this->headLink()->appendStylesheet('/styles/user-list.css') ?>
+]]></programlisting>
+
+        <para>
+            Dans notre layout, là encore, un simple echo sur le placeholer:
+        </para>
+
+        <programlisting language="php"><![CDATA[
+<?php echo $this->doctype() ?>
+<html>
+    <?php echo $this->headTitle() ?>
+    <?php echo $this->headLink() ?>
+    <!-- ... -->
+]]></programlisting>
+
+        <para>
+            Ceci génèrera quelque chose comme:
+        </para>
+
+        <programlisting language="html"><![CDATA[
+<link rel="stylesheet" type="text/css" href="/styles/site.css" />
+<link rel="stylesheet" type="text/css" href="/styles/user-list.css" />
+]]></programlisting>
+    </sect2>
+
+    <sect2 id="learning.view.placeholders.standard.head-script">
+        <title>Aggréger des scripts avec HeadScript</title>
+
+        <para>
+            Un autre moyen de ne pas surcharger la page est de ne charger le JavaScript que lorsque
+            c'est nécessaire. Vous aurez donc besoin de scripts découpés: peut-être un pour afficher
+            le menu du site progressivement, un autre pour traiter le contenu d'une page spécifique.
+            Dans ces cas, l'aide <methodname>headScript()</methodname> propose une solution.
+        </para>
+
+        <para>
+            Comme l'aide <methodname>headLink()</methodname>, <methodname>headScript()</methodname>
+            permet d'empiler en début ou fin des scripts entiers et de les afficher d'un coup. Cela
+            est très flexible pour spécifier des fichiers de scripts entiers à charger, ou encore
+            du code JavaScript explicite. Vous pouvez aussi capturer le JavaScript via
+            <methodname>captureStart()</methodname>/<methodname>captureEnd()</methodname>, qui
+            permettent d'utiliser du code JavaScript inline plutot que de demander un appel serveur
+            pour charger un fichier.
+        </para>
+
+        <para>
+            Tout comme <methodname>headLink()</methodname>, <methodname>headScript()</methodname>
+            propose des mééthodes "virtuelles" via surcharge pour spécifier rapidement des contenus
+            à aggréger; les méthodes sont <methodname>prependFile()</methodname>,
+            <methodname>appendFile()</methodname>, <methodname>prependScript()</methodname>, et
+            <methodname>appendScript()</methodname>. Les deux premières vous permettent de préciser
+            des fichiers référéncés dans l'attribut <varname>$src</varname> d'une balise
+            <emphasis>&lt;script&gt;</emphasis>; les deux dernières vont prendre le contenu qu'on leur
+            passe et le rendre comme du JavaScript dans les balises <emphasis>&lt;script&gt;</emphasis>.
+        </para>
+
+        <para>
+            Dans cet exemple, nous allons spécifier qu'un script, "<filename>/js/site.js</filename>" a
+            besoin d'être chargé sur chaque page; nous allons donc mettre à jour notre méthode de
+            bootstap <methodname>_initPlaceholders()</methodname> pour effectuer cela.
+        </para>
+
+        <programlisting language="php"><![CDATA[
+class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
+{
+    // ...
+
+    protected function _initPlaceholders()
+    {
+        $this->bootstrap('View');
+        $view = $this->getResource('View');
+        $view->doctype('XHTML1_STRICT');
+
+        // Titre et séparateur d'origine:
+        $view->headTitle('My Site')
+             ->setSeparator(' :: ');
+
+        // Feuille de style originale:
+        $view->headLink()->prependStylesheet('/styles/site.css');
+
+        // Affecte le JS initial à charger:
+        $view->headScript()->prependFile('/js/site.js');
+    }
+
+    // ...
+}
+]]></programlisting>
+
+        <para>
+            Dans un script de vue, nous voulons ajouter un script ou capturer du contenu JavaScript
+            à inclure dans le document.
+        </para>
+
+        <programlisting language="php"><![CDATA[
+<?php $this->headScript()->appendFile('/js/user-list.js') ?>
+<?php $this->headScript()->captureStart() ?>
+site = {
+    baseUrl: "<?php echo $this->baseUrl() ?>"
+};
+<?php $this->headScript()->captureEnd() ?>
+]]></programlisting>
+
+        <para>
+            Dans notre script de layout, nous affichons simplement le placeholder, tout comme nous avions
+            fait pour les autres précédemment:
+        </para>
+
+        <programlisting language="php"><![CDATA[
+<?php echo $this->doctype() ?>
+<html>
+    <?php echo $this->headTitle() ?>
+    <?php echo $this->headLink() ?>
+    <?php echo $this->headScript() ?>
+    <!-- ... -->
+]]></programlisting>
+
+        <para>
+            Le contenu suivant sera généré:
+        </para>
+
+        <programlisting language="html"><![CDATA[
+<script type="text/javascript" src="/js/site.js"></script>
+<script type="text/javascript" src="/js/user-list.js"></script>
+<script type="text/javascript">
+site = {
+    baseUrl: "<?php echo $this->baseUrl() ?>"
+};
+</script>
+]]></programlisting>
+
+        <note>
+            <title>Variante InlineScript</title>
+
+            <para>
+                La plupart des navigateur bloquent l'affichage tant que tous les scritps et les feuilles
+                de style référencés dans la section <emphasis>&lt;head&gt;</emphasis> ne sont pas chargés.
+                Ces règles permettent un meilleur feeling au niveau du rendu de la page et permettent
+                à l'utilisateur de voir le contenu de la page plus tôt.
+            </para>
+
+            <para>
+                Pour cela, vous pouvez par exemple écrire vos tags <emphasis>&lt;script&gt;</emphasis>
+                après avoir fermé <emphasis>&lt;body&gt;</emphasis>. (C'est une pratique recommandée
+                par <ulink url="http://developer.yahoo.com/yslow/">Y! Slow project</ulink>.)
+            </para>
+
+            <para>
+                Zend Framework supporte cela de deux manières différentes:
+            </para>
+
+            <itemizedlist>
+                <listitem>
+                    <para>
+                        Vous pouvez rendre <methodname>headScript()</methodname> où vous voulez dans votre
+                        layout; ce n'est pas parce que la méthode commence par "head" que vous devez
+                        l'appeler pour cette section du HTML.
+                    </para>
+                </listitem>
+
+                <listitem>
+                    <para>
+                        Aussi, vous pourriez utiliser l'aide de vue <methodname>inlineScript()</methodname>,
+                        qui est simplement une variante de <methodname>headScript()</methodname> avec le même
+                        comportement mais un registre séparé.
+                    </para>
+                </listitem>
+            </itemizedlist>
+        </note>
+    </sect2>
+</sect1>