<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>CoolCoyote.net &#187; Doctrine</title>
	<atom:link href="http://www.coolcoyote.net/tag/doctrine/feed" rel="self" type="application/rss+xml" />
	<link>http://www.coolcoyote.net</link>
	<description>Coding - Linux</description>
	<lastBuildDate>Sun, 07 Nov 2010 15:27:34 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>fr</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Les composants de Doctrine &#8211; Le composant Table</title>
		<link>http://www.coolcoyote.net/php-mysql/les-composants-de-doctrine-le-composant-table</link>
		<comments>http://www.coolcoyote.net/php-mysql/les-composants-de-doctrine-le-composant-table#comments</comments>
		<pubDate>Mon, 14 Jun 2010 17:57:33 +0000</pubDate>
		<dc:creator>Denis S.</dc:creator>
				<category><![CDATA[Doctrine]]></category>
		<category><![CDATA[PHP - MySQL]]></category>
		<category><![CDATA[composant]]></category>
		<category><![CDATA[finders]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://www.coolcoyote.net/?p=267</guid>
		<description><![CDATA[Maintenant que nous avons initialisé Doctrine (vois l&#8217;article sur l&#8217;introduction à Doctrine), nous allons pouvoir commencer à l&#8217;utiliser.
Comme nous l&#8217;avons dit, avec Doctrine tout est objet. Nous aurons donc accès à des classes qui vont nous permettre de travailler les données. On appelle ça des composants. Doctrine fournit plusieurs composants. En voici trois essentiels :

Le [...]]]></description>
			<content:encoded><![CDATA[<p>Maintenant que nous avons initialisé Doctrine (vois l&#8217;article sur <a href="http://www.coolcoyote.net/php-mysql/introduction-a-doctrine">l&#8217;introduction à Doctrine</a>), nous allons pouvoir commencer à l&#8217;utiliser.</p>
<p>Comme nous l&#8217;avons dit, avec Doctrine tout est objet. Nous aurons donc accès à des classes qui vont nous permettre de travailler les données. On appelle ça des <strong>composants</strong>. Doctrine fournit plusieurs composants. En voici trois essentiels :</p>
<ul>
<li>Le composant <strong>Record </strong>qui représente un enregistrement d&#8217;une table</li>
<li>Le composant <strong>Collection </strong>qui représente un ensemble de Record</li>
<li>Le composant <strong>Table </strong>qui représente notre table et nous permettra d&#8217;accéder aux composants Collection et Record</li>
</ul>
<p>Dans cet article nous allons étudier le composant Table.  Il permet comme son nom l&#8217;indique d&#8217;accéder à une table de notre base de données et d&#8217;interagir avec elle. Pour cela il nous faut une instance de la classe représentant notre table :</p>

<div class="cc_syntax-container"><table><tr><td class="line-numbers"><pre>1
2
3
</pre></td><td class="cc_syntax"><pre class="php"><span class="kw2">&lt;?php</span>
<span class="kw1">require_once</span><span class="br0">&#40;</span><span class="st_h">'bootstrap.php'</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="re0">$table</span> <span class="sy0">=</span> Doctrine_Core<span class="sy0">::</span><span class="me2">getTable</span><span class="br0">&#40;</span><span class="st_h">'Produits'</span><span class="br0">&#41;</span><span class="sy0">;</span></pre></td></tr></table></div>

<p><span id="more-267"></span></p>
<p>Vous remarquerez le nom particulier de notre table. En effet, dans notre base de données notre table s&#8217;appelle <strong>produits </strong>et dans Doctrine on l&#8217;appellera <strong>Produits</strong>. Chaque classe commence donc par une majuscule. En fait, chaque mot qui compose le nom de la table commence par une majuscule. Ainsi si on a une table <strong>nouveaux_produits</strong> on l&#8217;appellera <strong>NouveauxProduits </strong>dans Doctrine.</p>
<p>Cet objet va nous permettre d&#8217;accéder à une fonctionnalité très intéressante des Table : les <strong>finders</strong>.</p>
<p>Les finders sont des méthodes qui nous permettent de faire des recherches dans notre table et qui retournent soit un <strong>Record</strong>, soit une <strong>Collection</strong>. Voici un exemple :</p>

<div class="cc_syntax-container"><table><tr><td class="line-numbers"><pre>1
</pre></td><td class="cc_syntax"><pre class="php"><span class="re0">$record</span> <span class="sy0">=</span> <span class="re0">$table</span><span class="sy0">-&gt;</span><span class="me1">find</span><span class="br0">&#40;</span><span class="nu0">4</span><span class="br0">&#41;</span><span class="sy0">;</span></pre></td></tr></table></div>

<p>La méthode <strong>find()</strong> permet d&#8217;effectuer une recherche sur la clé primaire de notre table. Dans notre cas la clé primaire de la table <strong>produits </strong>est <strong>produits_id</strong>. L&#8217;équivalent SQL de ce que nous venons de faire est :</p>

<div class="cc_syntax-container"><table><tr><td class="line-numbers"><pre>1
</pre></td><td class="cc_syntax"><pre class="mysql"><span class="kw1">SELECT</span> produits_id<span class="sy2">,</span> produits_name<span class="sy2">,</span> produits_prix <span class="kw1">FROM</span> produits <span class="kw1">WHERE</span> produits_id <span class="sy1">=</span> <span class="nu0">4</span></pre></td></tr></table></div>

<p>En fait <strong>find()</strong> fait plus que cela, il permet de sélectionner non seulement l&#8217;enregistrement mais aussi de rendre accessible les enregistrements des autres tables qui sont en relation avec cet enregistrement. Pour comprendre cela, nous allons étudier en détail le comportement de Doctrine. J&#8217;ai également récupéré les logs MySQL afin de voir comment Doctrine travaillait. Soit la base de données suivante :</p>

<div class="cc_syntax-container"><table><tr><td class="line-numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
</pre></td><td class="cc_syntax"><pre class="mysql"><span class="kw1">SET</span> @OLD_UNIQUE_CHECKS<span class="sy1">=</span>@@UNIQUE_CHECKS<span class="sy2">,</span> UNIQUE_CHECKS<span class="sy1">=</span><span class="nu0">0</span><span class="sy2">;</span>
<span class="kw1">SET</span> @OLD_FOREIGN_KEY_CHECKS<span class="sy1">=</span>@@FOREIGN_KEY_CHECKS<span class="sy2">,</span> FOREIGN_KEY_CHECKS<span class="sy1">=</span><span class="nu0">0</span><span class="sy2">;</span>
<span class="kw1">SET</span> @OLD_SQL_MODE<span class="sy1">=</span>@@SQL_MODE<span class="sy2">,</span> SQL_MODE<span class="sy1">=</span><span class="st0">'TRADITIONAL'</span><span class="sy2">;</span>
&nbsp;
<span class="co1">-- -----------------------------------------------------</span>
<span class="co1">-- Table `groupes`</span>
<span class="co1">-- -----------------------------------------------------</span>
<span class="kw1">CREATE</span>  <span class="kw1">TABLE</span> <span class="kw1">IF <span class="kw10">NOT</span> EXISTS</span> <span class="st0">`groupes`</span> <span class="br0">&#40;</span>
  <span class="st0">`groupes<span class="es1">_</span>id`</span> <span class="kw4">INT</span> <span class="kw10">NOT</span> <span class="kw3">NULL</span> <span class="kw6">AUTO_INCREMENT</span> <span class="sy2">,</span>
  <span class="st0">`groupes<span class="es1">_</span>name`</span> <span class="kw4">VARCHAR</span><span class="br0">&#40;</span><span class="nu0">45</span><span class="br0">&#41;</span> <span class="kw10">NOT</span> <span class="kw3">NULL</span> <span class="sy2">,</span>
  <span class="kw1">PRIMARY KEY</span> <span class="br0">&#40;</span><span class="st0">`groupes<span class="es1">_</span>id`</span><span class="br0">&#41;</span> <span class="br0">&#41;</span>
<span class="kw1">ENGINE</span> <span class="sy1">=</span> <span class="kw1">InnoDB</span>
<span class="kw2">DEFAULT</span> CHARACTER <span class="kw1">SET</span> <span class="sy1">=</span> utf8
<span class="kw10">COLLATE</span> <span class="sy1">=</span> utf8_general_ci<span class="sy2">;</span>
&nbsp;
<span class="co1">-- -----------------------------------------------------</span>
<span class="co1">-- Table `user`</span>
<span class="co1">-- -----------------------------------------------------</span>
<span class="kw1">CREATE</span>  <span class="kw1">TABLE</span> <span class="kw1">IF <span class="kw10">NOT</span> EXISTS</span> <span class="st0">`user`</span> <span class="br0">&#40;</span>
  <span class="st0">`user<span class="es1">_</span>id`</span> <span class="kw4">INT</span> <span class="kw10">NOT</span> <span class="kw3">NULL</span> <span class="kw6">AUTO_INCREMENT</span> <span class="sy2">,</span>
  <span class="st0">`groupes<span class="es1">_</span>id`</span> <span class="kw4">INT</span> <span class="kw10">NOT</span> <span class="kw3">NULL</span> <span class="sy2">,</span>
  <span class="st0">`user<span class="es1">_</span>pseudo`</span> <span class="kw4">VARCHAR</span><span class="br0">&#40;</span><span class="nu0">100</span><span class="br0">&#41;</span> <span class="kw3">NULL</span> <span class="sy2">,</span>
  <span class="kw1">PRIMARY KEY</span> <span class="br0">&#40;</span><span class="st0">`user<span class="es1">_</span>id`</span><span class="br0">&#41;</span> <span class="sy2">,</span>
  <span class="kw1">CONSTRAINT</span> <span class="st0">`user<span class="es1">_</span>groupes<span class="es1">_</span>id`</span>
    <span class="kw1">FOREIGN KEY</span> <span class="br0">&#40;</span><span class="st0">`groupes<span class="es1">_</span>id`</span> <span class="br0">&#41;</span>
    <span class="kw1">REFERENCES</span> <span class="st0">`groupes`</span> <span class="br0">&#40;</span><span class="st0">`groupes<span class="es1">_</span>id`</span> <span class="br0">&#41;</span>
    <span class="kw1">ON</span> <span class="kw1">DELETE</span> <span class="kw1">CASCADE</span>
    <span class="kw1">ON</span> <span class="kw1">UPDATE</span> <span class="kw1">NO</span> <span class="kw1">ACTION</span><span class="br0">&#41;</span>
<span class="kw1">ENGINE</span> <span class="sy1">=</span> <span class="kw1">InnoDB</span>
<span class="kw2">DEFAULT</span> CHARACTER <span class="kw1">SET</span> <span class="sy1">=</span> utf8
<span class="kw10">COLLATE</span> <span class="sy1">=</span> utf8_general_ci<span class="sy2">;</span>
&nbsp;
<span class="kw1">CREATE</span> <span class="kw1">INDEX</span> <span class="st0">`user<span class="es1">_</span>groupes<span class="es1">_</span>id`</span> <span class="kw1">ON</span> <span class="st0">`user`</span> <span class="br0">&#40;</span><span class="st0">`groupes<span class="es1">_</span>id`</span> <span class="kw1">ASC</span><span class="br0">&#41;</span> <span class="sy2">;</span>
&nbsp;
<span class="co1">-- -----------------------------------------------------</span>
<span class="co1">-- Table `phone`</span>
<span class="co1">-- -----------------------------------------------------</span>
<span class="kw1">CREATE</span>  <span class="kw1">TABLE</span> <span class="kw1">IF <span class="kw10">NOT</span> EXISTS</span> <span class="st0">`phone`</span> <span class="br0">&#40;</span>
  <span class="st0">`phone<span class="es1">_</span>id`</span> <span class="kw4">INT</span> <span class="kw10">NOT</span> <span class="kw3">NULL</span> <span class="kw6">AUTO_INCREMENT</span> <span class="sy2">,</span>
  <span class="st0">`user<span class="es1">_</span>id`</span> <span class="kw4">INT</span> <span class="kw10">NOT</span> <span class="kw3">NULL</span> <span class="sy2">,</span>
  <span class="st0">`phone<span class="es1">_</span>number`</span> <span class="kw4">VARCHAR</span><span class="br0">&#40;</span><span class="nu0">20</span><span class="br0">&#41;</span> <span class="kw10">NOT</span> <span class="kw3">NULL</span> <span class="sy2">,</span>
  <span class="kw1">PRIMARY KEY</span> <span class="br0">&#40;</span><span class="st0">`phone<span class="es1">_</span>id`</span><span class="br0">&#41;</span> <span class="sy2">,</span>
  <span class="kw1">CONSTRAINT</span> <span class="st0">`phone<span class="es1">_</span>user<span class="es1">_</span>id`</span>
    <span class="kw1">FOREIGN KEY</span> <span class="br0">&#40;</span><span class="st0">`user<span class="es1">_</span>id`</span> <span class="br0">&#41;</span>
    <span class="kw1">REFERENCES</span> <span class="st0">`user`</span> <span class="br0">&#40;</span><span class="st0">`user<span class="es1">_</span>id`</span> <span class="br0">&#41;</span>
    <span class="kw1">ON</span> <span class="kw1">DELETE</span> <span class="kw1">CASCADE</span>
    <span class="kw1">ON</span> <span class="kw1">UPDATE</span> <span class="kw1">NO</span> <span class="kw1">ACTION</span><span class="br0">&#41;</span>
<span class="kw1">ENGINE</span> <span class="sy1">=</span> <span class="kw1">InnoDB</span>
<span class="kw2">DEFAULT</span> CHARACTER <span class="kw1">SET</span> <span class="sy1">=</span> utf8
<span class="kw10">COLLATE</span> <span class="sy1">=</span> utf8_general_ci<span class="sy2">;</span>
&nbsp;
<span class="kw1">CREATE</span> <span class="kw1">INDEX</span> <span class="st0">`phone<span class="es1">_</span>user<span class="es1">_</span>id`</span> <span class="kw1">ON</span> <span class="st0">`phone`</span> <span class="br0">&#40;</span><span class="st0">`user<span class="es1">_</span>id`</span> <span class="kw1">ASC</span><span class="br0">&#41;</span> <span class="sy2">;</span>
&nbsp;
<span class="kw1">SET</span> SQL_MODE<span class="sy1">=</span>@OLD_SQL_MODE<span class="sy2">;</span>
<span class="kw1">SET</span> FOREIGN_KEY_CHECKS<span class="sy1">=</span>@OLD_FOREIGN_KEY_CHECKS<span class="sy2">;</span>
<span class="kw1">SET</span> UNIQUE_CHECKS<span class="sy1">=</span>@OLD_UNIQUE_CHECKS<span class="sy2">;</span></pre></td></tr></table></div>

<p>Voici une représentation schématique de cette base :</p>
<div id="attachment_268" class="wp-caption alignnone" style="width: 417px"><img class="size-full wp-image-268" title="exemple_user" src="http://www.coolcoyote.net/wp-content/uploads/2010/01/exemple_user.png" alt="Schéma base de données" width="407" height="231" /><p class="wp-caption-text">Schéma base de données</p></div>
<p>Comme on peut le voir, on a une table d&#8217;utilisateur. Chaque utilisateur ne peut appartenir qu&#8217;à un seul groupe (many-to-one), mais peut posséder plusieurs numéros de téléphone (one-to-many). Si je fais :</p>

<div class="cc_syntax-container"><table><tr><td class="line-numbers"><pre>1
</pre></td><td class="cc_syntax"><pre class="php"><span class="re0">$user</span> <span class="sy0">=</span> Doctrine_Core<span class="sy0">::</span><span class="me2">getTable</span><span class="br0">&#40;</span><span class="st_h">'User'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">find</span><span class="br0">&#40;</span><span class="nu0">1</span><span class="br0">&#41;</span><span class="sy0">;</span></pre></td></tr></table></div>

<p>MySQL va faire la requête suivante :</p>

<div class="cc_syntax-container"><table><tr><td class="line-numbers"><pre>1
</pre></td><td class="cc_syntax"><pre class="mysql"><span class="kw1">SELECT</span> u.user_id <span class="kw1">AS</span> u__user_id<span class="sy2">,</span> u.groupes_id <span class="kw1">AS</span> u__groupes_id<span class="sy2">,</span> u.user_pseudo <span class="kw1">AS</span> u__user_pseudo <span class="kw1">FROM</span> <span class="kw23">user</span> u <span class="kw1">WHERE</span> <span class="br0">&#40;</span>u.user_id <span class="sy1">=</span> <span class="st0">'1'</span><span class="br0">&#41;</span> <span class="kw1">LIMIT</span> <span class="nu0">1</span></pre></td></tr></table></div>

<p>Je vais ainsi avoir accès aux champs de l&#8217;enregistrement récupéré grâce aux propriétés suivantes:</p>

<div class="cc_syntax-container"><table><tr><td class="line-numbers"><pre>1
2
3
</pre></td><td class="cc_syntax"><pre class="php"><span class="kw1">echo</span> <span class="re0">$user</span><span class="sy0">-&gt;</span><span class="me1">user_id</span>  <span class="sy0">.</span>  <span class="st_h">'&lt;br /&gt;'</span><span class="sy0">;</span>
<span class="kw1">echo</span> <span class="re0">$user</span><span class="sy0">-&gt;</span><span class="me1">groupes_id</span>  <span class="sy0">.</span>  <span class="st_h">'&lt;br /&gt;'</span><span class="sy0">;</span>
<span class="kw1">echo</span> <span class="re0">$user</span><span class="sy0">-&gt;</span><span class="me1">user_pseudo</span>  <span class="sy0">.</span>  <span class="st_h">'&lt;br /&gt;'</span><span class="sy0">;</span></pre></td></tr></table></div>

<p>On va également avoir la possibilité d&#8217;accéder aux champs de la table <strong>groupes </strong>dont dépend notre enregistrement :</p>

<div class="cc_syntax-container"><table><tr><td class="line-numbers"><pre>1
</pre></td><td class="cc_syntax"><pre class="php"><span class="kw1">echo</span> <span class="re0">$user</span><span class="sy0">-&gt;</span><span class="me1">Groupes</span><span class="sy0">-&gt;</span><span class="me1">groupes_name</span> <span class="sy0">.</span> <span class="st_h">'&lt;br /&gt;'</span><span class="sy0">;</span></pre></td></tr></table></div>

<p><strong>$user-&gt;Groupes</strong> représente un objet <strong>Record </strong>de la table <strong>Groupes</strong>. C&#8217;est un Record car selon le type de relation définit , un utilisateur ne peut appartenir qu&#8217;à un seul et unique groupe.</p>
<p>Sauf que dans la requête effectuée par Doctrine, on ne va pas chercher les informations de la table <strong>groupes</strong>. En fait la requête sera effectuée uniquement au moment où je demande d&#8217;accéder à la propriété <strong>$user-&gt;Groupes-&gt;groupes_name</strong>. Ainsi, à ce moment et uniquement lors du premier appel, Doctrine va effectuer la requête suivante :</p>

<div class="cc_syntax-container"><table><tr><td class="line-numbers"><pre>1
</pre></td><td class="cc_syntax"><pre class="mysql"><span class="kw1">SELECT</span> g.groupes_id <span class="kw1">AS</span> g__groupes_id<span class="sy2">,</span> g.groupes_name <span class="kw1">AS</span> g__groupes_name <span class="kw1">FROM</span> groupes g <span class="kw1">WHERE</span> <span class="br0">&#40;</span>g.groupes_id <span class="sy1">=</span> <span class="st0">'1'</span><span class="br0">&#41;</span></pre></td></tr></table></div>

<p>Doctrine va ensuite mettre ce résultat en cache. C&#8217;est à dire que si on demande à nouveau à accéder à une propriété de l&#8217;objet <strong>$user-&gt;Groupes</strong>, Doctrine ne va pas refaire la requête.</p>
<p>Tout comme nous avons un objet <strong>$user-&gt;Groupes</strong>, nous avons un objet <strong>$user-&gt;Phone</strong>. Sauf qu&#8217;il y a une différence : ici un utilisateur peut posséder plusieurs numéros de téléphone. Ainsi l&#8217;objet <strong>$user-&gt;Phone</strong> ne sera pas une instance de <strong>Record</strong>, mais une instance de <strong>Collection</strong>. Nous verrons plus loin les collections en détail, mais rapidement voici comment nous accèderons aux éléments de notre collection:</p>

<div class="cc_syntax-container"><table><tr><td class="line-numbers"><pre>1
2
</pre></td><td class="cc_syntax"><pre class="php"><span class="kw1">echo</span> <span class="re0">$user</span><span class="sy0">-&gt;</span><span class="me1">Phone</span><span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="sy0">-&gt;</span><span class="me1">phone_number</span><span class="sy0">;</span>
<span class="kw1">echo</span> <span class="re0">$user</span><span class="sy0">-&gt;</span><span class="me1">Phone</span><span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="sy0">-&gt;</span><span class="me1">phone_number</span><span class="sy0">;</span></pre></td></tr></table></div>

<p>Au moment de l&#8217;appel à l&#8217;objet <strong>$user-&gt;Phone</strong>, Doctrine va effectuer la requête suivante :</p>

<div class="cc_syntax-container"><table><tr><td class="line-numbers"><pre>1
</pre></td><td class="cc_syntax"><pre class="mysql"><span class="kw1">SELECT</span> p.phone_id <span class="kw1">AS</span> p__phone_id<span class="sy2">,</span> p.user_id <span class="kw1">AS</span> p__user_id<span class="sy2">,</span> p.phone_number <span class="kw1">AS</span> p__phone_number <span class="kw1">FROM</span> phone p <span class="kw1">WHERE</span> <span class="br0">&#40;</span>p.user_id <span class="kw2">IN</span> <span class="br0">&#40;</span><span class="st0">'1'</span><span class="br0">&#41;</span><span class="br0">&#41;</span></pre></td></tr></table></div>

<p>et récupérer l&#8217;ensemble des résultats.</p>
<p><strong>find()</strong> est donc bien pratique pour récupérer l&#8217;enregistrement d&#8217;une table, mais c&#8217;est moins glorieux lorsque l&#8217;on doit accéder aux relations de cet enregistrement. Même si Doctrine fait attention de ne pas effectuer de requêtes superflues, il fait en deux requêtes ce que l&#8217;on aurait pu faire en une seule avec une jointure.</p>
<p>Dans les finders, nous avons vu comment récupérer un enregistrement. Il est également possible de récupérer tous les enregistrements :</p>

<div class="cc_syntax-container"><table><tr><td class="line-numbers"><pre>1
</pre></td><td class="cc_syntax"><pre class="php"><span class="re0">$users</span> <span class="sy0">=</span> Doctrine_Record<span class="sy0">::</span><span class="me2">getTable</span><span class="br0">&#40;</span><span class="st_h">'User'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">findAll</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></pre></td></tr></table></div>

<p><strong>findAll()</strong> retourne donc une Collection qui contient tous les enregistrements de la table <strong>user</strong>. On peut itérer dans cette collection afin d&#8217;extraire les informations :</p>

<div class="cc_syntax-container"><table><tr><td class="line-numbers"><pre>1
2
3
</pre></td><td class="cc_syntax"><pre class="php"><span class="kw1">foreach</span> <span class="br0">&#40;</span><span class="re0">$users</span> <span class="kw1">as</span> <span class="re0">$user</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
    <span class="kw1">echo</span> <span class="re0">$user</span><span class="sy0">-&gt;</span><span class="me1">user_pseudo</span> <span class="sy0">.</span> <span class="st_h">'&lt;br /&gt;'</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div>

<p>La requête SQL de Doctrine qui va aller chercher les résultats est la suivante :</p>

<div class="cc_syntax-container"><table><tr><td class="line-numbers"><pre>1
</pre></td><td class="cc_syntax"><pre class="mysql"><span class="kw1">SELECT</span> u.user_id <span class="kw1">AS</span> u__user_id<span class="sy2">,</span> u.groupes_id <span class="kw1">AS</span> u__groupes_id<span class="sy2">,</span> u.user_pseudo <span class="kw1">AS</span> u__user_pseudo <span class="kw1">FROM</span> <span class="kw23">user</span> u</pre></td></tr></table></div>

<p>On peut également afficher le nom du groupe de chaque utilisateur :</p>

<div class="cc_syntax-container"><table><tr><td class="line-numbers"><pre>1
2
3
</pre></td><td class="cc_syntax"><pre class="php"><span class="kw1">foreach</span> <span class="br0">&#40;</span><span class="re0">$users</span> <span class="kw1">as</span> <span class="re0">$user</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
    <span class="kw1">echo</span> <span class="re0">$user</span><span class="sy0">-&gt;</span><span class="me1">Groupes</span><span class="sy0">-&gt;</span><span class="me1">groupes_name</span> <span class="sy0">.</span> <span class="st_h">'&lt;br /&gt;'</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></td></tr></table></div>

<p>Là c&#8217;est encore pire au niveau de l&#8217;optimisation. En effet, nous avons vu plus haut que Doctrine n&#8217;effectuait les requêtes des tables en relation que lorsque l&#8217;on y accède. Insérons les données suivantes dans nos tables :</p>

<div class="cc_syntax-container"><table><tr><td class="line-numbers"><pre>1
2
3
4
5
6
7
8
</pre></td><td class="cc_syntax"><pre class="mysql"><span class="kw2">INSERT</span> <span class="kw1">INTO</span> <span class="st0">`groupes`</span> <span class="br0">&#40;</span><span class="st0">`groupes<span class="es1">_</span>id`</span><span class="sy2">,</span> <span class="st0">`groupes<span class="es1">_</span>name`</span><span class="br0">&#41;</span> <span class="kw1">VALUES</span>
<span class="br0">&#40;</span><span class="nu0">1</span><span class="sy2">,</span> <span class="st0">'groupe 1'</span><span class="br0">&#41;</span><span class="sy2">,</span>
<span class="br0">&#40;</span><span class="nu0">2</span><span class="sy2">,</span> <span class="st0">'groupe 2'</span><span class="br0">&#41;</span><span class="sy2">;</span>
&nbsp;
<span class="kw2">INSERT</span> <span class="kw1">INTO</span> <span class="st0">`user`</span> <span class="br0">&#40;</span><span class="st0">`user<span class="es1">_</span>id`</span><span class="sy2">,</span> <span class="st0">`groupes<span class="es1">_</span>id`</span><span class="sy2">,</span> <span class="st0">`user<span class="es1">_</span>pseudo`</span><span class="br0">&#41;</span> <span class="kw1">VALUES</span>
<span class="br0">&#40;</span><span class="nu0">1</span><span class="sy2">,</span> <span class="nu0">1</span><span class="sy2">,</span> <span class="st0">'User 1'</span><span class="br0">&#41;</span><span class="sy2">,</span>
<span class="br0">&#40;</span><span class="nu0">2</span><span class="sy2">,</span> <span class="nu0">2</span><span class="sy2">,</span> <span class="st0">'User 2'</span><span class="br0">&#41;</span><span class="sy2">,</span>
<span class="br0">&#40;</span><span class="nu0">3</span><span class="sy2">,</span> <span class="nu0">1</span><span class="sy2">,</span> <span class="st0">'User 3'</span><span class="br0">&#41;</span><span class="sy2">;</span></pre></td></tr></table></div>

<p>Si nous analysons les requêtes effectuées par Doctrine lors de la boucle qui accède à la table groupe voici ce que l&#8217;on voit :</p>

<div class="cc_syntax-container"><table><tr><td class="line-numbers"><pre>1
2
3
</pre></td><td class="cc_syntax"><pre class="mysql"><span class="kw1">SELECT</span> g.groupes_id <span class="kw1">AS</span> g__groupes_id<span class="sy2">,</span> g.groupes_name <span class="kw1">AS</span> g__groupes_name <span class="kw1">FROM</span> groupes g <span class="kw1">WHERE</span> <span class="br0">&#40;</span>g.groupes_id <span class="sy1">=</span> <span class="st0">'1'</span><span class="br0">&#41;</span>
<span class="kw1">SELECT</span> g.groupes_id <span class="kw1">AS</span> g__groupes_id<span class="sy2">,</span> g.groupes_name <span class="kw1">AS</span> g__groupes_name <span class="kw1">FROM</span> groupes g <span class="kw1">WHERE</span> <span class="br0">&#40;</span>g.groupes_id <span class="sy1">=</span> <span class="st0">'2'</span><span class="br0">&#41;</span>
<span class="kw1">SELECT</span> g.groupes_id <span class="kw1">AS</span> g__groupes_id<span class="sy2">,</span> g.groupes_name <span class="kw1">AS</span> g__groupes_name <span class="kw1">FROM</span> groupes g <span class="kw1">WHERE</span> <span class="br0">&#40;</span>g.groupes_id <span class="sy1">=</span> <span class="st0">'1'</span><span class="br0">&#41;</span></pre></td></tr></table></div>

<p>Là ce n&#8217;est plus du tout optimisé puisque l&#8217;on constate que Doctrine va effectuer une requête pour chacun des enregistrements de la Collection <strong>$users</strong>, même si certaines sont communes. Si ce n&#8217;est pas grave dans notre cas, imaginez sur une table de 10 000 entrées&#8230; N&#8217;importe qui vous dirait que dans ce cas il faut effectuer une requête sur la table <strong>user </strong>avec une jointure sur la table <strong>groupes </strong>pour récupérer les champs du groupe. Cela nous pourrons le faire en DQL. En attendant sachez donc que si <strong>findAll()</strong> est parfaitement adapté pour récupérer les enregistrements d&#8217;une table, il ne l&#8217;est plus du tout lorsqu&#8217;il s&#8217;agit d&#8217;accéder aux relations de cette table.</p>
<p>Les finders ont d&#8217;autre possibilités assez intéressantes. Par exemple, il est possible d&#8217;avoir des finders personnalisés selon notre table. On les appelle les <strong>Magic Finders</strong>. Imaginons que nous voulions récupérer toutes les entrées de <strong>user </strong>dont le <strong>groupes_id</strong> est 1 :</p>

<div class="cc_syntax-container"><table><tr><td class="line-numbers"><pre>1
</pre></td><td class="cc_syntax"><pre class="php"><span class="re0">$users</span> <span class="sy0">=</span> Doctrine_Core<span class="sy0">::</span><span class="me2">getTable</span><span class="br0">&#40;</span><span class="st_h">'User'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">findByGroupes_id</span><span class="br0">&#40;</span><span class="nu0">1</span><span class="br0">&#41;</span><span class="sy0">;</span></pre></td></tr></table></div>

<p>Cette ligne exécute la requête suivante :</p>

<div class="cc_syntax-container"><table><tr><td class="line-numbers"><pre>1
</pre></td><td class="cc_syntax"><pre class="mysql"><span class="kw1">SELECT</span> u.user_id <span class="kw1">AS</span> u__user_id<span class="sy2">,</span> u.groupes_id <span class="kw1">AS</span> u__groupes_id<span class="sy2">,</span> u.user_pseudo <span class="kw1">AS</span> u__user_pseudo <span class="kw1">FROM</span> <span class="kw23">user</span> u <span class="kw1">WHERE</span> <span class="br0">&#40;</span>u.groupes_id <span class="sy1">=</span> <span class="st0">'1'</span><span class="br0">&#41;</span></pre></td></tr></table></div>

<p>Et renverra une instance de <strong>Doctrine_Collection</strong>. Ce qui est vraiment top, c&#8217;est que ce finder, qui dépend complètement des champs présents dans la table n&#8217;a pas besoin d&#8217;être codé par le développeur, Doctrine le propose automatiquement, voilà pourquoi on les appelle les <strong>Magic Finders</strong>.</p>
<p>Il est également possible de ne retourner qu&#8217;un seul enregistrement au lieu d&#8217;une Collection :</p>

<div class="cc_syntax-container"><table><tr><td class="line-numbers"><pre>1
</pre></td><td class="cc_syntax"><pre class="php"><span class="re0">$users</span> <span class="sy0">=</span> Doctrine_Core<span class="sy0">::</span><span class="me2">getTable</span><span class="br0">&#40;</span><span class="st_h">'User'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">findOneByGroupes_id</span><span class="br0">&#40;</span><span class="nu0">1</span><span class="br0">&#41;</span><span class="sy0">;</span></pre></td></tr></table></div>

<p>Encore une fois il s&#8217;agit d&#8217;un finder personnalisé qui va effectuer la requête suivante :</p>

<div class="cc_syntax-container"><table><tr><td class="line-numbers"><pre>1
</pre></td><td class="cc_syntax"><pre class="mysql"><span class="kw1">SELECT</span> u.user_id <span class="kw1">AS</span> u__user_id<span class="sy2">,</span> u.groupes_id <span class="kw1">AS</span> u__groupes_id<span class="sy2">,</span> u.user_pseudo <span class="kw1">AS</span> u__user_pseudo <span class="kw1">FROM</span> <span class="kw23">user</span> u <span class="kw1">WHERE</span> <span class="br0">&#40;</span>u.groupes_id <span class="sy1">=</span> <span class="st0">'1'</span><span class="br0">&#41;</span> <span class="kw1">LIMIT</span> <span class="nu0">1</span></pre></td></tr></table></div>

<p>Les finders personnalisés peuvent aller encore plus loin. Regardez le finder suivant :</p>

<div class="cc_syntax-container"><table><tr><td class="line-numbers"><pre>1
</pre></td><td class="cc_syntax"><pre class="php"><span class="re0">$users</span> <span class="sy0">=</span> Doctrine_Core<span class="sy0">::</span><span class="me2">getTable</span><span class="br0">&#40;</span><span class="st_h">'User'</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">findOneByGroupes_idAndUser_pseudo</span><span class="br0">&#40;</span><span class="nu0">1</span><span class="sy0">,</span> <span class="st_h">'User 1'</span><span class="br0">&#41;</span><span class="sy0">;</span></pre></td></tr></table></div>

<p>La requête SQL produite est la suivante :</p>

<div class="cc_syntax-container"><table><tr><td class="line-numbers"><pre>1
</pre></td><td class="cc_syntax"><pre class="mysql"><span class="kw1">SELECT</span> u.user_id <span class="kw1">AS</span> u__user_id<span class="sy2">,</span> u.groupes_id <span class="kw1">AS</span> u__groupes_id<span class="sy2">,</span> u.user_pseudo <span class="kw1">AS</span> u__user_pseudo <span class="kw1">FROM</span> <span class="kw23">user</span> u <span class="kw1">WHERE</span> <span class="br0">&#40;</span>u.groupes_id <span class="sy1">=</span> <span class="st0">'1'</span> <span class="kw10">AND</span> u.user_pseudo <span class="sy1">=</span> <span class="st0">'User 1'</span><span class="br0">&#41;</span> <span class="kw1">LIMIT</span> <span class="nu0">1</span></pre></td></tr></table></div>

<p>On peut donc utiliser les mots-clés <strong>And </strong>et <strong>Or </strong>dans les Magic Finders afin de composer notre recherche</p>
<p>Voici donc un petit récap sur les finders :</p>
<ul>
<li><strong>findAll()</strong> renvoie une Collection qui contient tous les enregistrements de la table</li>
<li><strong>find()</strong> renvoi un Record. La recherche se fera sur la clé primaire de la table</li>
<li><strong>findBy</strong> + le nom du champ commençant par une majuscule : Renvoie une Collection. La recherche se fait sur le champ indiqué après <strong>By</strong></li>
<li><strong>findOneBy </strong>+  le nom du champ commençant par une majuscule : Renvoie un Record. La recherche se fait sur le champ indiqué après <strong>By</strong></li>
<li>On peut utiliser les mots-clés <strong>And </strong>et <strong>Or </strong>dans les Magic Finders afin de composer une recherche sur plusieurs champs</li>
</ul>
<p>Ces finders sont très pratiques mais retenez qu&#8217;<span style="color: #ff0000;"><strong>il ne faut jamais les utiliser si vous avez besoin d&#8217;accéder aux relations des enregistrements à cause de leur manque d&#8217;optimisation</strong></span>. Pour cela nous nous tournerons vers le DQL.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.coolcoyote.net/php-mysql/les-composants-de-doctrine-le-composant-table/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Introduction à Doctrine</title>
		<link>http://www.coolcoyote.net/php-mysql/introduction-a-doctrine</link>
		<comments>http://www.coolcoyote.net/php-mysql/introduction-a-doctrine#comments</comments>
		<pubDate>Tue, 12 Jan 2010 13:09:05 +0000</pubDate>
		<dc:creator>Denis S.</dc:creator>
				<category><![CDATA[Doctrine]]></category>
		<category><![CDATA[PHP - MySQL]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://www.coolcoyote.net/?p=254</guid>
		<description><![CDATA[Cette année je suis passé à Doctrine. Les raisons étaient diverses:

Il était temps pour moi de laisser tomber la vieille extension mysql de PHP et de passer à de l&#8217;objet.
Trouver un système qui s&#8217;intègre facilement dans un modèle MVC
Pouvoir faire de l&#8217;abstraction de base de données
Idéalement un système qui va me faire gagner du temps [...]]]></description>
			<content:encoded><![CDATA[<p>Cette année je suis passé à Doctrine. Les raisons étaient diverses:</p>
<ul>
<li>Il était temps pour moi de laisser tomber la vieille extension <strong>mysql</strong> de <strong>PHP</strong> et de passer à de l&#8217;objet.</li>
<li>Trouver un système qui s&#8217;intègre facilement dans un modèle <strong>MVC</strong></li>
<li>Pouvoir faire de l&#8217;abstraction de base de données</li>
<li>Idéalement un système qui va me faire gagner du temps dans mes développements.</li>
</ul>
<p>Après avoir regardé plusieurs solutions, je me suis donc tourné vers <a href="http://doctrine-project.org" target="_blank">Doctrine</a>:</p>
<ul>
<li>Il s&#8217;interface avec <strong>PDO</strong>, donc abstraction de base de données</li>
<li>Les performances semblent au rendez-vous</li>
<li>Il génère automatiquement le modèle du <strong>MVC</strong></li>
<li>Support des fonctionnalités récentes de MySQL</li>
<li>Utilisé par défaut dans<strong> Symfony</strong></li>
<li>Tout est objet</li>
</ul>
<p>Bref je me suis dis que c&#8217;était le top. Et c&#8217;est vrai que quand on le maîtrise c&#8217;est vraiment sympa. Sauf que la transition s&#8217;est quand même un peu faite dans la douleur. La doc est présente mais dans certains cas j&#8217;ai quand même perdu pas mal de temps à chercher des solutions à mes problèmes. Je me suis donc dit qu&#8217;il était peut-être possible d&#8217;apporter quelques compléments d&#8217;information.</p>
<p><span id="more-254"></span></p>
<h3>Comprendre la philosophie Doctrine</h3>
<p>Doctrine est un <a href="http://fr.wikipedia.org/wiki/Mapping_objet-relationnel" target="_blank">ORM</a> (Object Relational Mapper), c&#8217;est à dire qu&#8217;il va s&#8217;interfacer avec notre base de données afin de nous permettre d&#8217;y accéder comme s&#8217;il s&#8217;agissait d&#8217;un objet.  Ainsi il sera possible d&#8217;accéder aux données d&#8217;une table comme s&#8217;il s&#8217;agissait de propriétés d&#8217;une classe, mais en plus cette classe va nous proposer des méthodes permettant de mettre en œuvre des fonctionnalité comme l&#8217;enregistrement, la suppression, la mise à jour etc.</p>
<p>Prenons un exemple simple :  soit la table mysql suivante:</p>

<div class="cc_syntax-container"><table><tr><td class="line-numbers"><pre>1
2
3
4
5
</pre></td><td class="cc_syntax"><pre class="mysql"><span class="kw1">CREATE</span> <span class="kw1">TABLE</span> produits <span class="br0">&#40;</span>
  produits_id <span class="kw4">int</span><span class="br0">&#40;</span><span class="nu0">11</span><span class="br0">&#41;</span> <span class="kw10">NOT</span> <span class="kw3">NULL</span> <span class="kw6">auto_increment</span><span class="sy2">,</span>
  produits_name <span class="kw4">varchar</span><span class="br0">&#40;</span><span class="nu0">255</span><span class="br0">&#41;</span> <span class="kw10">NOT</span> <span class="kw3">NULL</span>
  <span class="kw1">PRIMARY KEY</span>  <span class="br0">&#40;</span>produits_id<span class="br0">&#41;</span>
<span class="br0">&#41;</span> <span class="kw1">ENGINE</span><span class="sy1">=</span><span class="kw1">InnoDB</span>  <span class="kw2">DEFAULT</span> <span class="kw7">CHARSET</span><span class="sy1">=</span>utf8<span class="sy2">;</span></pre></td></tr></table></div>

<p>Imaginons que nous voulions insérer un nouvel enregistrement, nous pourrons le réaliser comme ceci :</p>

<div class="cc_syntax-container"><table><tr><td class="line-numbers"><pre>1
2
3
</pre></td><td class="cc_syntax"><pre class="php"><span class="re0">$produit</span> <span class="sy0">=</span> <span class="kw2">new</span> Produits<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="re0">$produit</span><span class="sy0">-&gt;</span><span class="me1">produits_name</span> <span class="sy0">=</span> <span class="st_h">'Casserole'</span><span class="sy0">;</span>
<span class="re0">$produit</span><span class="sy0">-&gt;</span><span class="me1">save</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></pre></td></tr></table></div>

<p>C&#8217;est tout ! Et en bon ORM qu&#8217;il est, Doctrine propose une interface objet pour de nombreux éléments comme la connexion à la base, les tables, les enregistrements des tables, etc. ce que nous verrons plus tard.</p>
<p>Doctrine peut également réaliser des requêtes similaires à ce que l&#8217;on connaît sous MySQL mais avec son propre langage: le <a href="http://www.doctrine-project.org/documentation/manual/1_2/en/dql-doctrine-query-language" target="_blank">DQL</a> (Doctrine Query Langage). Sincèrement, on s&#8217;y fait très vite, voici un exemple de sélection du produit ayant l&#8217;ID 4 :</p>

<div class="cc_syntax-container"><table><tr><td class="line-numbers"><pre>1
2
3
4
</pre></td><td class="cc_syntax"><pre class="php"><span class="re0">$produit</span> <span class="sy0">=</span> Doctrine_Query<span class="sy0">::</span><span class="me2">create</span><span class="br0">&#40;</span><span class="br0">&#41;</span>
    <span class="sy0">-&gt;</span><span class="me1">from</span><span class="br0">&#40;</span><span class="st_h">'Produits a'</span><span class="br0">&#41;</span>
    <span class="sy0">-&gt;</span><span class="me1">where</span><span class="br0">&#40;</span><span class="st_h">'a.produits_id = ?'</span><span class="sy0">,</span> <span class="nu0">4</span><span class="br0">&#41;</span>
    <span class="sy0">-&gt;</span><span class="me1">fetchOne</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></pre></td></tr></table></div>

<p>La documentation officielle sur le <a href="http://www.doctrine-project.org/documentation/manual/1_2/en/dql-doctrine-query-language" target="_blank">DQL</a> est plutôt bien faite et le &laquo;&nbsp;langage&nbsp;&raquo; est très explicite. Il n&#8217;y aura donc aucune difficulté particulière. Cependant nous en parlerons quand même dans un prochain article.</p>
<h3>La génération du modèle et le fichier YAML</h3>
<p>Pour arriver à tout cela, Doctrine va devoir utiliser des classes qui représenteront nos tables. Ces classes, on ne va pas les créer car Doctrine s&#8217;en charge pour nous. Il va donc se charger de générer des fichiers PHP qui seront notre modèle de données. Il y a plusieurs façons de réaliser cela :</p>
<ul>
<li>On peut créer notre modèle sur Doctrine qui va ensuite se charger de créer les tables sur MySQL</li>
<li>On peut créer nos tables MySQL et Doctrine en déduira son modèle.</li>
</ul>
<p>En ce qui me concerne, je modélise ma base de données avec <strong>MySQL Workbench</strong>, donc je pars toujours d&#8217;une base de données existante pour générer mon modèle Doctrine (je vais considérer que vous ferez pareil). Quelle que soit la solution choisie, il y a un passage qui semble indispensable : le fichier <strong>YAML</strong>. Il s&#8217;agit d&#8217;un fichier  de configuration qui va contenir le schéma de notre base de données et sur lequel Doctrine va se baser.</p>
<p>La génération du modèle va donc se dérouler ainsi:</p>
<p>Base de données MySQL existante -&gt; Génération du fichier YAML -&gt; Génération du modèle</p>
<p>Il existe une solution qui permet de générer le modèle directement à partir de la base de données, mais je ne l&#8217;ai pas trouvée intéressante car elle manque de fonctionnalités. En effet, nous verrons plus tard que Doctrine propose des fonctionnalités très intéressantes mais qui nécessitent d&#8217;être paramétrées dans le fichier YAML et que la conversion directe MySQL -&gt; Modèle va ignorer.</p>
<p>Si vous ne connaissez pas <strong>YAML</strong>, il s&#8217;agit d&#8217;un langage de sérialisation de données comparable à <a href="http://fr.wikipedia.org/wiki/Json" target="_blank">JSON</a>. Vous pourrez trouver plus de renseignements sur <a href="http://fr.wikipedia.org/wiki/YAML" target="_blank">Wikipédia</a> et sur <a href="http://www.yaml.org/" target="_blank">le site officiel</a>. Bien que je le trouve un peu plus complexe que JSON, YAML reste facilement compréhensible. Il ne sera donc pas compliqué de retravailler le modèle pour Doctrine.</p>
<h3>Téléchargement et installation de Doctrine</h3>
<p>Les informations qui suivent sont valables pour Doctrine 1.2.1. Il est possible de télécharger le sandbox à cette adresse: <a href="http://www.doctrine-project.org/download" target="_blank">http://www.doctrine-project.org/download</a></p>
<p>On va créer un répertoire <strong>doctrine_test</strong>. Dans ce répertoire, nous allons créer le répertoire <strong>lib/vendor/doctrine</strong> dans lequel nous allons copier la librairie.</p>
<p>Nous devrions donc avoir dans le répertoire <strong>doctrine_test/lib/vendor/dotrine</strong> les éléments suivants:</p>
<ul>
<li>Un répertoire <strong>Doctrine</strong></li>
<li>Un répertoire <strong>vendor</strong></li>
<li>Un fichier <strong>Doctrine.php</strong></li>
</ul>
<h3>Le bootstrap</h3>
<p>Ce que l&#8217;on va appeler bootstrap, c&#8217;est un fichier PHP qui va contenir le code de connexion à la base de données et que l&#8217;on va inclure dans chacun de nos fichiers afin d&#8217;activer l&#8217;autoload, d&#8217;établir la connexion à la base et de définir plusieurs paramètres. Dans le répertoire doctrine_test, nous allons créer un fichier bootstrap.php dont voici le contenu :</p>

<div class="cc_syntax-container"><table><tr><td class="line-numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
</pre></td><td class="cc_syntax"><pre class="php"><span class="kw2">&lt;?php</span>
&nbsp;
<span class="co1">// bootstrap.php</span>
&nbsp;
<span class="co4">/**
 * Bootstrap Doctrine.php, register autoloader specify
 * configuration attributes and load models.
 */</span>
&nbsp;
<span class="kw1">require_once</span><span class="br0">&#40;</span><span class="st_h">'lib/vendor/doctrine/Doctrine.php'</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
<span class="kw3">spl_autoload_register</span><span class="br0">&#40;</span><span class="kw3">array</span><span class="br0">&#40;</span><span class="st_h">'Doctrine'</span><span class="sy0">,</span> <span class="st_h">'autoload'</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="kw3">spl_autoload_register</span><span class="br0">&#40;</span><span class="kw3">array</span><span class="br0">&#40;</span><span class="st_h">'Doctrine'</span><span class="sy0">,</span> <span class="st_h">'modelsAutoload'</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span> 
&nbsp;
<span class="re0">$manager</span> <span class="sy0">=</span> Doctrine_Manager<span class="sy0">::</span><span class="me2">getInstance</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
<span class="re0">$conn</span> <span class="sy0">=</span> Doctrine_Manager<span class="sy0">::</span><span class="me2">connection</span><span class="br0">&#40;</span><span class="st_h">'mysql://user:password@host/dbname'</span><span class="sy0">,</span><span class="st_h">'doctrine'</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
<span class="re0">$manager</span><span class="sy0">-&gt;</span><span class="me1">setAttribute</span><span class="br0">&#40;</span>Doctrine_Core<span class="sy0">::</span><span class="me2">ATTR_VALIDATE</span><span class="sy0">,</span> Doctrine_Core<span class="sy0">::</span><span class="me2">VALIDATE_ALL</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="re0">$manager</span><span class="sy0">-&gt;</span><span class="me1">setAttribute</span><span class="br0">&#40;</span>Doctrine_Core<span class="sy0">::</span><span class="me2">ATTR_AUTO_ACCESSOR_OVERRIDE</span><span class="sy0">,</span> <span class="kw4">true</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="re0">$manager</span><span class="sy0">-&gt;</span><span class="me1">setAttribute</span><span class="br0">&#40;</span>Doctrine_Core<span class="sy0">::</span><span class="me2">ATTR_AUTOLOAD_TABLE_CLASSES</span><span class="sy0">,</span> <span class="kw4">true</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="re0">$manager</span><span class="sy0">-&gt;</span><span class="me1">setAttribute</span><span class="br0">&#40;</span>Doctrine_Core<span class="sy0">::</span><span class="me2">ATTR_MODEL_LOADING</span><span class="sy0">,</span> Doctrine_Core<span class="sy0">::</span><span class="me2">MODEL_LOADING_CONSERVATIVE</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
Doctrine_Core<span class="sy0">::</span><span class="me2">loadModels</span><span class="br0">&#40;</span><span class="st_h">'models'</span><span class="br0">&#41;</span><span class="sy0">;</span></pre></td></tr></table></div>

<p>Une note très importante si vous avez déjà utilisé Doctrine : vous remarquerez un deuxième autoload qui n&#8217;est pas indiqué dans la documentation. En effet cet autoload est nécessaire et n&#8217;est pas documenté et j&#8217;ai galéré un bon moment avant de trouver la solution sur leur forum.</p>
<p>L&#8217;explication de ce fichier est relativement simple :</p>

<div class="cc_syntax-container"><table><tr><td class="line-numbers"><pre>1
</pre></td><td class="cc_syntax"><pre class="php"><span class="kw1">require_once</span><span class="br0">&#40;</span><span class="st_h">'lib/vendor/doctrine/Doctrine.php'</span><span class="br0">&#41;</span><span class="sy0">;</span></pre></td></tr></table></div>

<p>On inclue la librairie Doctrine</p>

<div class="cc_syntax-container"><table><tr><td class="line-numbers"><pre>1
2
</pre></td><td class="cc_syntax"><pre class="php"><span class="kw3">spl_autoload_register</span><span class="br0">&#40;</span><span class="kw3">array</span><span class="br0">&#40;</span><span class="st_h">'Doctrine'</span><span class="sy0">,</span> <span class="st_h">'autoload'</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="kw3">spl_autoload_register</span><span class="br0">&#40;</span><span class="kw3">array</span><span class="br0">&#40;</span><span class="st_h">'Doctrine'</span><span class="sy0">,</span> <span class="st_h">'modelsAutoload'</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></pre></td></tr></table></div>

<p>On déclare les autoloads</p>

<div class="cc_syntax-container"><table><tr><td class="line-numbers"><pre>1
</pre></td><td class="cc_syntax"><pre class="php"><span class="re0">$manager</span> <span class="sy0">=</span> Doctrine_Manager<span class="sy0">::</span><span class="me2">getInstance</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span></pre></td></tr></table></div>

<p>On récupère une instance <strong>Doctrine_Manager</strong> (singleton) qui va nous permettre de définir certaines options</p>

<div class="cc_syntax-container"><table><tr><td class="line-numbers"><pre>1
</pre></td><td class="cc_syntax"><pre class="php"><span class="re0">$conn</span> <span class="sy0">=</span> Doctrine_Manager<span class="sy0">::</span><span class="me2">connection</span><span class="br0">&#40;</span><span class="st_h">'mysql://user:password@host/dbname'</span><span class="sy0">,</span><span class="st_h">'doctrine'</span><span class="br0">&#41;</span><span class="sy0">;</span></pre></td></tr></table></div>

<p>On se connecte à la base de données avec une syntaxe de type <strong>DSN</strong> compatible avec <strong>PDO</strong></p>

<div class="cc_syntax-container"><table><tr><td class="line-numbers"><pre>1
2
3
4
</pre></td><td class="cc_syntax"><pre class="php"><span class="re0">$manager</span><span class="sy0">-&gt;</span><span class="me1">setAttribute</span><span class="br0">&#40;</span>Doctrine_Core<span class="sy0">::</span><span class="me2">ATTR_VALIDATE</span><span class="sy0">,</span> Doctrine_Core<span class="sy0">::</span><span class="me2">VALIDATE_ALL</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="re0">$manager</span><span class="sy0">-&gt;</span><span class="me1">setAttribute</span><span class="br0">&#40;</span>Doctrine_Core<span class="sy0">::</span><span class="me2">ATTR_AUTO_ACCESSOR_OVERRIDE</span><span class="sy0">,</span> <span class="kw4">true</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="re0">$manager</span><span class="sy0">-&gt;</span><span class="me1">setAttribute</span><span class="br0">&#40;</span>Doctrine_Core<span class="sy0">::</span><span class="me2">ATTR_AUTOLOAD_TABLE_CLASSES</span><span class="sy0">,</span> <span class="kw4">true</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="re0">$manager</span><span class="sy0">-&gt;</span><span class="me1">setAttribute</span><span class="br0">&#40;</span>Doctrine_Core<span class="sy0">::</span><span class="me2">ATTR_MODEL_LOADING</span><span class="sy0">,</span> Doctrine_Core<span class="sy0">::</span><span class="me2">MODEL_LOADING_CONSERVATIVE</span><span class="br0">&#41;</span><span class="sy0">;</span></pre></td></tr></table></div>

<p>Ici on définit les options de Doctrine au niveau global (on peut définir des options sur 3 niveaux: au niveau global, au niveau d&#8217;une connexion en particulier, au niveau d&#8217;une table en particulier). Voici la signification de ces options:</p>

<div class="cc_syntax-container"><table><tr><td class="line-numbers"><pre>1
</pre></td><td class="cc_syntax"><pre class="php"><span class="re0">$manager</span><span class="sy0">-&gt;</span><span class="me1">setAttribute</span><span class="br0">&#40;</span>Doctrine_Core<span class="sy0">::</span><span class="me2">ATTR_VALIDATE</span><span class="sy0">,</span> Doctrine_Core<span class="sy0">::</span><span class="me2">VALIDATE_ALL</span><span class="br0">&#41;</span><span class="sy0">;</span></pre></td></tr></table></div>

<p>Doctrine possède un validateur de données intégré. Si jamais vous essayez par exemple d&#8217;insérer une chaîne de caractère dans une champ de type entier, Doctrine va générer une erreur avant même de tenter de l&#8217;insérer en base. C&#8217;est assez utile et ici on déclare vouloir l&#8217;utiliser.</p>

<div class="cc_syntax-container"><table><tr><td class="line-numbers"><pre>1
</pre></td><td class="cc_syntax"><pre class="php"><span class="re0">$manager</span><span class="sy0">-&gt;</span><span class="me1">setAttribute</span><span class="br0">&#40;</span>Doctrine_Core<span class="sy0">::</span><span class="me2">ATTR_AUTO_ACCESSOR_OVERRIDE</span><span class="sy0">,</span> <span class="kw4">true</span><span class="br0">&#41;</span></pre></td></tr></table></div>

<p>l&#8217;<strong>AUTO_ACCESSOR_OVERRIDE</strong> va nous permettre de personnaliser l&#8217;assignation de données. J&#8217;essaierai de faire un article complet sur la personnalisation des classes car j&#8217;ai trouvé la documentation assez légère sur les possibilités offertes du coup je pense moi-même ne pas exploiter cette fonctionnalité à fond.</p>

<div class="cc_syntax-container"><table><tr><td class="line-numbers"><pre>1
</pre></td><td class="cc_syntax"><pre class="php"><span class="re0">$manager</span><span class="sy0">-&gt;</span><span class="me1">setAttribute</span><span class="br0">&#40;</span>Doctrine_Core<span class="sy0">::</span><span class="me2">ATTR_AUTOLOAD_TABLE_CLASSES</span><span class="sy0">,</span> <span class="kw4">true</span><span class="br0">&#41;</span><span class="sy0">;</span></pre></td></tr></table></div>

<p>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.</p>

<div class="cc_syntax-container"><table><tr><td class="line-numbers"><pre>1
</pre></td><td class="cc_syntax"><pre class="php"><span class="re0">$manager</span><span class="sy0">-&gt;</span><span class="me1">setAttribute</span><span class="br0">&#40;</span>Doctrine_Core<span class="sy0">::</span><span class="me2">ATTR_MODEL_LOADING</span><span class="sy0">,</span> Doctrine_Core<span class="sy0">::</span><span class="me2">MODEL_LOADING_CONSERVATIVE</span><span class="br0">&#41;</span><span class="sy0">;</span></pre></td></tr></table></div>

<p>Ce paramètre permet d&#8217;utiliser l&#8217;autoload pour le chargement des classes du modèle.</p>

<div class="cc_syntax-container"><table><tr><td class="line-numbers"><pre>1
</pre></td><td class="cc_syntax"><pre class="php">Doctrine_Core<span class="sy0">::</span><span class="me2">loadModels</span><span class="br0">&#40;</span><span class="st_h">'models'</span><span class="br0">&#41;</span><span class="sy0">;</span></pre></td></tr></table></div>

<p>Enfin on déclare quel répertoire contient nos fichiers de modèle. Vous en déduirez donc qu&#8217;il va falloir créer un dossier <strong>models</strong> <img src='http://www.coolcoyote.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<h3>Base de données de test et génération du modèle</h3>
<p>Nous allons commencer avec une base de données simple dont voici le schema :</p>
<p>Voici le code SQL de création des tables (à copier / coller dans phpMyAdmin) :</p>

<div class="cc_syntax-container"><table><tr><td class="line-numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
</pre></td><td class="cc_syntax"><pre class="mysql"><span class="kw1">SET</span> @OLD_UNIQUE_CHECKS<span class="sy1">=</span>@@UNIQUE_CHECKS<span class="sy2">,</span> UNIQUE_CHECKS<span class="sy1">=</span><span class="nu0">0</span><span class="sy2">;</span>
<span class="kw1">SET</span> @OLD_FOREIGN_KEY_CHECKS<span class="sy1">=</span>@@FOREIGN_KEY_CHECKS<span class="sy2">,</span> FOREIGN_KEY_CHECKS<span class="sy1">=</span><span class="nu0">0</span><span class="sy2">;</span>
<span class="kw1">SET</span> @OLD_SQL_MODE<span class="sy1">=</span>@@SQL_MODE<span class="sy2">,</span> SQL_MODE<span class="sy1">=</span><span class="st0">'TRADITIONAL'</span><span class="sy2">;</span>
&nbsp;
<span class="co1">-- -----------------------------------------------------</span>
<span class="co1">-- Table `produits`</span>
<span class="co1">-- -----------------------------------------------------</span>
<span class="kw1">CREATE</span>  <span class="kw1">TABLE</span> <span class="kw1">IF <span class="kw10">NOT</span> EXISTS</span> <span class="st0">`produits`</span> <span class="br0">&#40;</span>
  <span class="st0">`produits<span class="es1">_</span>id`</span> <span class="kw4">INT</span> <span class="kw10">NOT</span> <span class="kw3">NULL</span> <span class="kw6">AUTO_INCREMENT</span> <span class="sy2">,</span>
  <span class="st0">`produits<span class="es1">_</span>name`</span> <span class="kw4">VARCHAR</span><span class="br0">&#40;</span><span class="nu0">100</span><span class="br0">&#41;</span> <span class="kw10">NOT</span> <span class="kw3">NULL</span> <span class="sy2">,</span>
  <span class="st0">`produits<span class="es1">_</span>prix`</span> <span class="kw4">FLOAT</span> <span class="kw10">NOT</span> <span class="kw3">NULL</span> <span class="kw2">DEFAULT</span> <span class="nu0">0</span> <span class="sy2">,</span>
  <span class="kw1">PRIMARY KEY</span> <span class="br0">&#40;</span><span class="st0">`produits<span class="es1">_</span>id`</span><span class="br0">&#41;</span> <span class="br0">&#41;</span>
<span class="kw1">ENGINE</span> <span class="sy1">=</span> <span class="kw1">InnoDB</span>
<span class="kw2">DEFAULT</span> CHARACTER <span class="kw1">SET</span> <span class="sy1">=</span> utf8<span class="sy2">;</span>
&nbsp;
<span class="co1">-- -----------------------------------------------------</span>
<span class="co1">-- Table `tailles`</span>
<span class="co1">-- -----------------------------------------------------</span>
<span class="kw1">CREATE</span>  <span class="kw1">TABLE</span> <span class="kw1">IF <span class="kw10">NOT</span> EXISTS</span> <span class="st0">`tailles`</span> <span class="br0">&#40;</span>
  <span class="st0">`tailles<span class="es1">_</span>id`</span> <span class="kw4">INT</span> <span class="kw10">NOT</span> <span class="kw3">NULL</span> <span class="kw6">AUTO_INCREMENT</span> <span class="sy2">,</span>
  <span class="st0">`tailles<span class="es1">_</span>name`</span> <span class="kw4">VARCHAR</span><span class="br0">&#40;</span><span class="nu0">45</span><span class="br0">&#41;</span> <span class="kw3">NULL</span> <span class="sy2">,</span>
  <span class="kw1">PRIMARY KEY</span> <span class="br0">&#40;</span><span class="st0">`tailles<span class="es1">_</span>id`</span><span class="br0">&#41;</span> <span class="br0">&#41;</span>
<span class="kw1">ENGINE</span> <span class="sy1">=</span> <span class="kw1">InnoDB</span>
<span class="kw2">DEFAULT</span> CHARACTER <span class="kw1">SET</span> <span class="sy1">=</span> utf8<span class="sy2">;</span>
&nbsp;
<span class="co1">-- -----------------------------------------------------</span>
<span class="co1">-- Table `couleurs`</span>
<span class="co1">-- -----------------------------------------------------</span>
<span class="kw1">CREATE</span>  <span class="kw1">TABLE</span> <span class="kw1">IF <span class="kw10">NOT</span> EXISTS</span> <span class="st0">`couleurs`</span> <span class="br0">&#40;</span>
  <span class="st0">`couleurs<span class="es1">_</span>id`</span> <span class="kw4">INT</span> <span class="kw10">NOT</span> <span class="kw3">NULL</span> <span class="kw6">AUTO_INCREMENT</span> <span class="sy2">,</span>
  <span class="st0">`couleurs<span class="es1">_</span>name`</span> <span class="kw4">VARCHAR</span><span class="br0">&#40;</span><span class="nu0">45</span><span class="br0">&#41;</span> <span class="kw10">NOT</span> <span class="kw3">NULL</span> <span class="sy2">,</span>
  <span class="kw1">PRIMARY KEY</span> <span class="br0">&#40;</span><span class="st0">`couleurs<span class="es1">_</span>id`</span><span class="br0">&#41;</span> <span class="br0">&#41;</span>
<span class="kw1">ENGINE</span> <span class="sy1">=</span> <span class="kw1">InnoDB</span>
<span class="kw2">DEFAULT</span> CHARACTER <span class="kw1">SET</span> <span class="sy1">=</span> utf8<span class="sy2">;</span>
&nbsp;
<span class="co1">-- -----------------------------------------------------</span>
<span class="co1">-- Table `produits_having_tailles`</span>
<span class="co1">-- -----------------------------------------------------</span>
<span class="kw1">CREATE</span>  <span class="kw1">TABLE</span> <span class="kw1">IF <span class="kw10">NOT</span> EXISTS</span> <span class="st0">`produits<span class="es1">_</span>having<span class="es1">_</span>tailles`</span> <span class="br0">&#40;</span>
  <span class="st0">`produits<span class="es1">_</span>id`</span> <span class="kw4">INT</span> <span class="kw10">NOT</span> <span class="kw3">NULL</span> <span class="sy2">,</span>
  <span class="st0">`tailles<span class="es1">_</span>id`</span> <span class="kw4">INT</span> <span class="kw10">NOT</span> <span class="kw3">NULL</span> <span class="sy2">,</span>
  <span class="kw1">PRIMARY KEY</span> <span class="br0">&#40;</span><span class="st0">`produits<span class="es1">_</span>id`</span><span class="sy2">,</span> <span class="st0">`tailles<span class="es1">_</span>id`</span><span class="br0">&#41;</span> <span class="sy2">,</span>
  <span class="kw1">INDEX</span> <span class="st0">`pht<span class="es1">_</span>produits<span class="es1">_</span>id`</span> <span class="br0">&#40;</span><span class="st0">`produits<span class="es1">_</span>id`</span> <span class="kw1">ASC</span><span class="br0">&#41;</span> <span class="sy2">,</span>
  <span class="kw1">INDEX</span> <span class="st0">`pht<span class="es1">_</span>tailles<span class="es1">_</span>id`</span> <span class="br0">&#40;</span><span class="st0">`tailles<span class="es1">_</span>id`</span> <span class="kw1">ASC</span><span class="br0">&#41;</span> <span class="sy2">,</span>
  <span class="kw1">CONSTRAINT</span> <span class="st0">`pht<span class="es1">_</span>produits<span class="es1">_</span>id`</span>
    <span class="kw1">FOREIGN KEY</span> <span class="br0">&#40;</span><span class="st0">`produits<span class="es1">_</span>id`</span> <span class="br0">&#41;</span>
    <span class="kw1">REFERENCES</span> <span class="st0">`produits`</span> <span class="br0">&#40;</span><span class="st0">`produits<span class="es1">_</span>id`</span> <span class="br0">&#41;</span>
    <span class="kw1">ON</span> <span class="kw1">DELETE</span> <span class="kw1">CASCADE</span>
    <span class="kw1">ON</span> <span class="kw1">UPDATE</span> <span class="kw1">NO</span> <span class="kw1">ACTION</span><span class="sy2">,</span>
  <span class="kw1">CONSTRAINT</span> <span class="st0">`pht<span class="es1">_</span>tailles<span class="es1">_</span>id`</span>
    <span class="kw1">FOREIGN KEY</span> <span class="br0">&#40;</span><span class="st0">`tailles<span class="es1">_</span>id`</span> <span class="br0">&#41;</span>
    <span class="kw1">REFERENCES</span> <span class="st0">`tailles`</span> <span class="br0">&#40;</span><span class="st0">`tailles<span class="es1">_</span>id`</span> <span class="br0">&#41;</span>
    <span class="kw1">ON</span> <span class="kw1">DELETE</span> <span class="kw1">CASCADE</span>
    <span class="kw1">ON</span> <span class="kw1">UPDATE</span> <span class="kw1">NO</span> <span class="kw1">ACTION</span><span class="br0">&#41;</span>
<span class="kw1">ENGINE</span> <span class="sy1">=</span> <span class="kw1">InnoDB</span>
<span class="kw2">DEFAULT</span> CHARACTER <span class="kw1">SET</span> <span class="sy1">=</span> utf8<span class="sy2">;</span>
&nbsp;
<span class="co1">-- -----------------------------------------------------</span>
<span class="co1">-- Table `produits_having_couleurs`</span>
<span class="co1">-- -----------------------------------------------------</span>
<span class="kw1">CREATE</span>  <span class="kw1">TABLE</span> <span class="kw1">IF <span class="kw10">NOT</span> EXISTS</span> <span class="st0">`produits<span class="es1">_</span>having<span class="es1">_</span>couleurs`</span> <span class="br0">&#40;</span>
  <span class="st0">`produits<span class="es1">_</span>id`</span> <span class="kw4">INT</span> <span class="kw10">NOT</span> <span class="kw3">NULL</span> <span class="sy2">,</span>
  <span class="st0">`couleurs<span class="es1">_</span>id`</span> <span class="kw4">INT</span> <span class="kw10">NOT</span> <span class="kw3">NULL</span> <span class="sy2">,</span>
  <span class="kw1">PRIMARY KEY</span> <span class="br0">&#40;</span><span class="st0">`produits<span class="es1">_</span>id`</span><span class="sy2">,</span> <span class="st0">`couleurs<span class="es1">_</span>id`</span><span class="br0">&#41;</span> <span class="sy2">,</span>
  <span class="kw1">INDEX</span> <span class="st0">`phc<span class="es1">_</span>produits<span class="es1">_</span>id`</span> <span class="br0">&#40;</span><span class="st0">`produits<span class="es1">_</span>id`</span> <span class="kw1">ASC</span><span class="br0">&#41;</span> <span class="sy2">,</span>
  <span class="kw1">INDEX</span> <span class="st0">`phc<span class="es1">_</span>couleurs<span class="es1">_</span>id`</span> <span class="br0">&#40;</span><span class="st0">`couleurs<span class="es1">_</span>id`</span> <span class="kw1">ASC</span><span class="br0">&#41;</span> <span class="sy2">,</span>
  <span class="kw1">CONSTRAINT</span> <span class="st0">`phc<span class="es1">_</span>produits<span class="es1">_</span>id`</span>
    <span class="kw1">FOREIGN KEY</span> <span class="br0">&#40;</span><span class="st0">`produits<span class="es1">_</span>id`</span> <span class="br0">&#41;</span>
    <span class="kw1">REFERENCES</span> <span class="st0">`produits`</span> <span class="br0">&#40;</span><span class="st0">`produits<span class="es1">_</span>id`</span> <span class="br0">&#41;</span>
    <span class="kw1">ON</span> <span class="kw1">DELETE</span> <span class="kw1">CASCADE</span>
    <span class="kw1">ON</span> <span class="kw1">UPDATE</span> <span class="kw1">NO</span> <span class="kw1">ACTION</span><span class="sy2">,</span>
  <span class="kw1">CONSTRAINT</span> <span class="st0">`phc<span class="es1">_</span>couleurs<span class="es1">_</span>id`</span>
    <span class="kw1">FOREIGN KEY</span> <span class="br0">&#40;</span><span class="st0">`couleurs<span class="es1">_</span>id`</span> <span class="br0">&#41;</span>
    <span class="kw1">REFERENCES</span> <span class="st0">`couleurs`</span> <span class="br0">&#40;</span><span class="st0">`couleurs<span class="es1">_</span>id`</span> <span class="br0">&#41;</span>
    <span class="kw1">ON</span> <span class="kw1">DELETE</span> <span class="kw1">CASCADE</span>
    <span class="kw1">ON</span> <span class="kw1">UPDATE</span> <span class="kw1">NO</span> <span class="kw1">ACTION</span><span class="br0">&#41;</span>
<span class="kw1">ENGINE</span> <span class="sy1">=</span> <span class="kw1">InnoDB</span>
<span class="kw2">DEFAULT</span> CHARACTER <span class="kw1">SET</span> <span class="sy1">=</span> utf8<span class="sy2">;</span>
&nbsp;
<span class="kw1">SET</span> SQL_MODE<span class="sy1">=</span>@OLD_SQL_MODE<span class="sy2">;</span>
<span class="kw1">SET</span> FOREIGN_KEY_CHECKS<span class="sy1">=</span>@OLD_FOREIGN_KEY_CHECKS<span class="sy2">;</span>
<span class="kw1">SET</span> UNIQUE_CHECKS<span class="sy1">=</span>@OLD_UNIQUE_CHECKS<span class="sy2">;</span></pre></td></tr></table></div>

<p>Votre base de données étant créée, on va commencer par générer notre fichier YAML. Pensez à bien paramétrer le DSN dans le fichier bootstrap.php pour vous connecter à la base. Dans le répertoire <strong>doctrine_test</strong>, créez un répertoire <strong>yaml</strong> et un répertoire <strong>models</strong> accessibles en écriture pour Apache. On va ensuite créer un fichier <strong>generate_yaml.php</strong> contenant le code suivant :</p>

<div class="cc_syntax-container"><table><tr><td class="line-numbers"><pre>1
2
3
</pre></td><td class="cc_syntax"><pre class="php"><span class="kw2">&lt;?php</span>
<span class="kw1">require_once</span><span class="br0">&#40;</span><span class="st_h">'bootstrap.php'</span><span class="br0">&#41;</span><span class="sy0">;</span>
Doctrine<span class="sy0">::</span><span class="me2">generateYamlFromDb</span><span class="br0">&#40;</span><span class="st_h">'yaml'</span><span class="sy0">,</span> <span class="kw3">array</span><span class="br0">&#40;</span><span class="st_h">'doctrine'</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></pre></td></tr></table></div>

<p>Si vous exécutez ce fichier, vous trouverez dans le répertoire <strong>yaml</strong> un fichier <strong>schema.yml</strong>. Vous pouvez éditer ce fichier pour voir à quoi ressemble notre modèle. Nous allons ensuite générer les fichiers de classe à proprement parler. Créez le fichier <strong>generate_model.php</strong> et insérez le code :</p>

<div class="cc_syntax-container"><table><tr><td class="line-numbers"><pre>1
2
3
</pre></td><td class="cc_syntax"><pre class="php"><span class="kw2">&lt;?php</span>
<span class="kw1">require_once</span><span class="br0">&#40;</span><span class="st_h">'bootstrap.php'</span><span class="br0">&#41;</span><span class="sy0">;</span>
Doctrine<span class="sy0">::</span><span class="me2">generateModelsFromYaml</span><span class="br0">&#40;</span><span class="st_h">'yaml'</span><span class="sy0">,</span> <span class="st_h">'models'</span><span class="sy0">,</span> <span class="kw3">array</span><span class="br0">&#40;</span><span class="st_h">'generateTableClasses'</span> <span class="sy0">=&gt;</span> <span class="kw4">true</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span></pre></td></tr></table></div>

<p>Si vous l&#8217;exécutez , c&#8217;est maintenant dans le répertoire models que seront générés les fichiers. On y trouvera un répertoire <strong>generated </strong>dans lequel on trouvera les classes définissant nos tables, ainsi qu&#8217;une série de fichiers qui nous permettra par la suite de personnaliser nos classes.</p>
<p>Nous sommes maintenant fin prêts à utiliser Doctrine. Dans un prochain article nous verrons comment commencer à exploiter notre base de données.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.coolcoyote.net/php-mysql/introduction-a-doctrine/feed</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
	</channel>
</rss>

