<?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</title>
	<atom:link href="http://www.coolcoyote.net/feed" rel="self" type="application/rss+xml" />
	<link>http://www.coolcoyote.net</link>
	<description>Coding - Linux</description>
	<lastBuildDate>Mon, 13 Feb 2012 22:05:17 +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>Installation de vlogger sur squeeze</title>
		<link>http://www.coolcoyote.net/linux-debian/installation-de-vlogger-sur-squeeze</link>
		<comments>http://www.coolcoyote.net/linux-debian/installation-de-vlogger-sur-squeeze#comments</comments>
		<pubDate>Mon, 13 Feb 2012 22:04:20 +0000</pubDate>
		<dc:creator>Denis S.</dc:creator>
				<category><![CDATA[Linux Debian]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[logs]]></category>
		<category><![CDATA[vlogger]]></category>

		<guid isPermaLink="false">http://www.coolcoyote.net/?p=400</guid>
		<description><![CDATA[vlogger est un petit script qui va s&#8217;occuper de gérer l&#8217;écriture des logs à la place d&#8217;Apache. Pourquoi ? Car il est bien mieux optimisé qu&#8217;Apache pour faire cette tâche et que du coup nous allons soulager notre serveur et économiser des ressources qui seront plutôt utilisées ailleurs. De plus sa façon de créer les [...]]]></description>
			<content:encoded><![CDATA[<p><strong>vlogger</strong> est un petit script qui va s&#8217;occuper de gérer l&#8217;écriture des logs à la place d&#8217;Apache. Pourquoi ? Car il est bien mieux optimisé qu&#8217;Apache pour faire cette tâche et que du coup nous allons soulager notre serveur et économiser des ressources qui seront plutôt utilisées ailleurs. De plus sa façon de créer les logs est plutôt sympathique: vlogger va créer dans le répertoire de logs d&#8217;Apache un répertoire pour chaque VirtualHost du serveur (ce nom sera basé sur le ServerName). A l&#8217;intérieur, vlogger va créer un fichier de log différent pour chaque jour, et va créer un lien symbolique access.log vers le fichier de log du jour.</p>
<p><span id="more-400"></span></p>
<h3>Installation de vlogger</h3>
<pre class="code">&gt; apt-get install vlogger</pre>
<p>Une fois vlogger installé, nous allons devoir paramétrer Apache pour qu&#8217;il envoie ses logs à vlogger.</p>
<p>tout d&#8217;abord, éditer le fichier <em>/etc/apache2/apache2.conf</em>, et trouver les lignes</p>
<pre class="code">LogFormat "%v:%p %h %l %u %t \"%r\" %&gt;s %O \"%{Referer}i\" \"%{User-Agent}i\"" vhost_combined
LogFormat "%h %l %u %t \"%r\" %&gt;s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined
LogFormat "%h %l %u %t \"%r\" %&gt;s %O" common
LogFormat "%{Referer}i -&gt; %U" referer
LogFormat "%{User-agent}i" agent</pre>
<p>Le but est de rajouter <strong>%v</strong> au début de la ligne de chaque définition de log, ce qui donne :</p>
<pre class="code">LogFormat "%v %v:%p %h %l %u %t \"%r\" %&gt;s %O \"%{Referer}i\" \"%{User-Agent}i\"" vhost_combined
LogFormat "%v %h %l %u %t \"%r\" %&gt;s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined
LogFormat "%v %h %l %u %t \"%r\" %&gt;s %O" common
LogFormat "%v %{Referer}i -&gt; %U" referer
LogFormat "%v %{User-agent}i" agent</pre>
<p>Pourquoi faire cela ? Lorsque nous enverrons nos logs à vlogger, celui-ci va prendre le premier paramètre pour créer le répertoire correspondant et nous voulons que le répertoire corresponde au virtualhost utilisé d&#8217;où l&#8217;ajout de %v. C&#8217;est donc ce nom qui sera utilisé pour désigner le répertoire et il sera ensuite supprimé de la ligne du log. Aller ensuite dans <em>/etc/apache2/conf.d/</em>. Si vous avez un fichier <strong>other-vhosts-access-log</strong> de présent éditez le, sinon créez le. A l&#8217;intérieur on va mettre les lignes suivantes:</p>
<pre class="code">ErrorLog "| /usr/sbin/vlogger -e -s error.log ${APACHE_LOG_DIR}/error/"
CustomLog "| /usr/sbin/vlogger -s access.log ${APACHE_LOG_DIR}" vhost_combined</pre>
<p>Ici donc on fait un <strong>pipe </strong>sur les logs d&#8217;Apache vers vlogger.</p>
<p>Si vous n&#8217;avez pas de <strong>ServerName </strong>par défaut pour votre serveur, je vous conseille d&#8217;en créer un, même bidon. Rappelez vous que vlogger utilise le premier paramètre de la définition du log pour créer son répertoire. Or le VirtualHost par défaut d&#8217;Apache (celui qui est utilisé lorsque l&#8217;on accède directement au serveur par l&#8217;adresse IP par exemple) ne définit pas de ServerName. Du coup le paramètre %v va être vide et vlogger va utiliser les paramètres suivants pour créer son répertoire. On risque donc de se retrouver avec des répertoires exotiques comme le port, l&#8217;adresse IP du client ou autre (selon le format de log utilisé). Pas terrible. Dans <em>conf.d</em> j&#8217;ai donc créé un fichier <strong>servername</strong> dans lequel j&#8217;ai mis:</p>
<pre class="code">ServerName localhost</pre>
<p>vlogger a ceci d&#8217;intéressant qu&#8217;il gère lui-même la création des différents dossiers des virtualhost, du coup on va désactiver les logs du virtualhost par défaut. Dans le fichier <em>/etc/apache2/sites-available/default</em>, commentez les lignes suivantes:</p>
<pre class="code">ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined</pre>
<p>Si vous avez d&#8217;autres VirtualHosts et que vous avez des logs personnalisés, désactivez les également.</p>
<p>On va maintenant allez dans le répertoire de logs d&#8217;Apache (<em>/var/log/apache2/</em>) et créer le répertoire error. En effet, les erreurs elles, seront toutes regroupées dans ce dossier</p>
<p>Sauvegardez et redémarrez Apache, normalement le nouveau système de logs devrait fonctionner.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.coolcoyote.net/linux-debian/installation-de-vlogger-sur-squeeze/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Migration d&#8217;un serveur mysql 5.0 à 5.1 : ERROR 1577 (HY000)</title>
		<link>http://www.coolcoyote.net/linux-debian/migration-dun-serveur-mysql-5-0-a-5-1-error-1577-hy000</link>
		<comments>http://www.coolcoyote.net/linux-debian/migration-dun-serveur-mysql-5-0-a-5-1-error-1577-hy000#comments</comments>
		<pubDate>Mon, 13 Feb 2012 09:49:34 +0000</pubDate>
		<dc:creator>Denis S.</dc:creator>
				<category><![CDATA[Linux Debian]]></category>
		<category><![CDATA[debian]]></category>
		<category><![CDATA[mysql]]></category>

		<guid isPermaLink="false">http://www.coolcoyote.net/?p=425</guid>
		<description><![CDATA[Lors de la migration d&#8217;un serveur mysql de la version 5.0 à la version 5.1 j&#8217;ai eu un message d&#8217;erreur lors du lancement du serveur :
ERROR 1577 (HY000) at line 1: Cannot proceed because system tables used by Event Scheduler were found damaged at server start
J&#8217;ai résolu le problème en lançant cette commande :
&#62; mysql_upgrade [...]]]></description>
			<content:encoded><![CDATA[<p>Lors de la migration d&#8217;un serveur mysql de la version 5.0 à la version 5.1 j&#8217;ai eu un message d&#8217;erreur lors du lancement du serveur :</p>
<pre class="code">ERROR 1577 (HY000) at line 1: Cannot proceed because system tables used by Event Scheduler were found damaged at server start</pre>
<p>J&#8217;ai résolu le problème en lançant cette commande :</p>
<pre class="code">&gt; mysql_upgrade -u root -p --force</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.coolcoyote.net/linux-debian/migration-dun-serveur-mysql-5-0-a-5-1-error-1577-hy000/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Installer Eclipse et PDT séparément sur Windows</title>
		<link>http://www.coolcoyote.net/php-mysql/installer-eclipse-et-pdt-separement-sur-windows</link>
		<comments>http://www.coolcoyote.net/php-mysql/installer-eclipse-et-pdt-separement-sur-windows#comments</comments>
		<pubDate>Sun, 07 Nov 2010 15:27:03 +0000</pubDate>
		<dc:creator>Denis S.</dc:creator>
				<category><![CDATA[Eclipse]]></category>
		<category><![CDATA[PHP - MySQL]]></category>
		<category><![CDATA[pdt]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://www.coolcoyote.net/?p=368</guid>
		<description><![CDATA[Si vous ne voulez pas utiliser Eclipse uniquement pour faire du PHP, mieux vaut installer la version classique d&#8217;Eclipse, puis d&#8217;installer PDT (PHP Development Tool) séparément.
En ce qui me concerne j&#8217;ai commencé par télécharger la version &#171;&#160;Classic&#160;&#187; d&#8217;Eclipse que l&#8217;on peut trouver sur cette page. A l&#8217;heure où j&#8217;écris ces lignes il s&#8217;agit de Eclipse [...]]]></description>
			<content:encoded><![CDATA[<p>Si vous ne voulez pas utiliser Eclipse uniquement pour faire du PHP, mieux vaut installer la version classique d&#8217;Eclipse, puis d&#8217;installer PDT (PHP Development Tool) séparément.</p>
<p>En ce qui me concerne j&#8217;ai commencé par télécharger la version &laquo;&nbsp;Classic&nbsp;&raquo; d&#8217;Eclipse que l&#8217;on peut trouver sur <a href="http://www.eclipse.org/downloads/" target="_blank">cette page</a>. A l&#8217;heure où j&#8217;écris ces lignes il s&#8217;agit de <strong>Eclipse Classic 3.6.1</strong>. Téléchargez le zip en fonction de votre système (32 ou 64 bits). Dézippez ensuite votre fichier dans le répertoire <strong>Program Files</strong>. Vous obtenez un répertoire <strong>eclipse</strong>. Entre-y et faites un raccourcit de <strong>eclipse.exe</strong> vers le bureau par exemple.</p>
<p><span id="more-368"></span></p>
<p>Lancez Eclipse. On vous demande de choisir votre <strong>Workspace</strong>. De ce que j&#8217;ai lu, il est préférable pour des raisons de performances de choisir un espace de travail à la racine de votre <strong>C:</strong>. J&#8217;ai donc choisis <strong>C:\workspace</strong>, et j&#8217;ai coché la case pour l&#8217;utiliser par défaut.</p>
<p>Une fois dans Eclipse, aller dans le menu <strong>Help / Install New Software</strong>. Dans l&#8217;espace <strong>Work with</strong>, cliquer sur <strong>Add&#8230;</strong></p>
<p><a href="http://www.coolcoyote.net/wp-content/uploads/2010/11/Eclipse001.jpg"><img class="aligncenter size-full wp-image-373" title="Eclipse001" src="http://www.coolcoyote.net/wp-content/uploads/2010/11/Eclipse001.jpg" alt="" width="737" height="269" /></a></p>
<p>Dans la nouvelle fenêtre tapez <strong>Eclipse </strong>dans le champ name, et l&#8217;url <strong>http://download.eclipse.org/releases/helios/</strong> dans le champ <strong>Location </strong>et validez.</p>
<p><a href="http://www.coolcoyote.net/wp-content/uploads/2010/11/Eclipse002.jpg"><img class="aligncenter size-full wp-image-374" title="Eclipse002" src="http://www.coolcoyote.net/wp-content/uploads/2010/11/Eclipse002.jpg" alt="" width="489" height="188" /></a></p>
<p>Après quelques instants, la liste des logiciels téléchargeables apparaît. Dans <strong>Programming Languages</strong>, choisir <strong>PDT</strong> et cliquez sur <strong>Next</strong>, puis <strong>Next </strong>à nouveau.</p>
<p><a href="http://www.coolcoyote.net/wp-content/uploads/2010/11/Eclipse003.jpg"><img class="aligncenter size-full wp-image-376" title="Eclipse003" src="http://www.coolcoyote.net/wp-content/uploads/2010/11/Eclipse003.jpg" alt="" width="520" height="239" /></a></p>
<p>Acceptez les conditions et enfin <strong>Finish</strong>. Le chargement de <strong>PDT </strong>commence. Ça peut prendre plusieurs minutes. A la fin de l&#8217;installation, redémarrez Eclipse.</p>
<p>source de l&#8217;article: <a href="http://wiki.eclipse.org/PDT/Installation#Eclipse_3.6_.2F_Helios_.2F_PDT_2.2" target="_blank">http://wiki.eclipse.org/PDT/Installation#Eclipse_3.6_.2F_Helios_.2F_PDT_2.2</a></p>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow: hidden;">
<div class="icon"><img src="http://www.eclipse.org/downloads/images/classic2.jpg" alt="" width="32" /></div>
<p><span class="title"><a href="http://www.eclipse.org/downloads/packages/eclipse-classic-361/heliossr1">Eclipse Classic 3.6.1</a></span></p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.coolcoyote.net/php-mysql/installer-eclipse-et-pdt-separement-sur-windows/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Portée des fonctions</title>
		<link>http://www.coolcoyote.net/php-mysql/portee-des-fonctions</link>
		<comments>http://www.coolcoyote.net/php-mysql/portee-des-fonctions#comments</comments>
		<pubDate>Thu, 17 Jun 2010 15:19:36 +0000</pubDate>
		<dc:creator>Denis S.</dc:creator>
				<category><![CDATA[PHP - MySQL]]></category>
		<category><![CDATA[classes]]></category>
		<category><![CDATA[fonctions]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[portée]]></category>

		<guid isPermaLink="false">http://www.coolcoyote.net/?p=232</guid>
		<description><![CDATA[La dernière fois, je me posais la question de savoir comment Symfony faisait pour proposer dans ses vues des fonctions telles que __() (les helpers) puisque je pensais que la seule solution de rendre une fonction utilisateur locale à une méthode de classe était de la déclarer directement dans la méthode et que je n&#8217;ai [...]]]></description>
			<content:encoded><![CDATA[<p>La dernière fois, je me posais la question de savoir comment <strong>Symfony </strong>faisait pour proposer dans ses vues des fonctions telles que <strong>__()</strong> (les helpers) puisque je pensais que la seule solution de rendre une fonction utilisateur locale à une méthode de classe était de la déclarer directement dans la méthode et que je n&#8217;ai trouvé aucun moyen de transmettre cette fonction à cette méthode (comme cela se passe pour les variables). Et pour cause, on n&#8217;en n&#8217;a pas besoin!</p>
<p><span id="more-232"></span></p>
<p>Un petit retour aux basics de PHP m&#8217;a confirmé que la création d&#8217;une fonction dans une méthode de classe la rendait globale à tout le programme, même dans la méthodes d&#8217;une autre classe. Du coup <strong>Symfony </strong>déclare &laquo;&nbsp;bêtement&nbsp;&raquo; (je met entre guillemets car Symfony oblige, ce n&#8217;est pas si simple <img src='http://www.coolcoyote.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> ) ces fonctions dans la méthode d&#8217;une autre classe.</p>
<p>Exemple:</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
</pre></td><td class="cc_syntax"><pre class="php"><span class="kw2">&lt;?php</span>
<span class="kw2">class</span> MaClasse
<span class="br0">&#123;</span>
    <span class="kw2">public</span> <span class="kw2">function</span> registerFunction<span class="br0">&#40;</span><span class="br0">&#41;</span>
    <span class="br0">&#123;</span>
        <span class="kw2">function</span> ma_fonction<span class="br0">&#40;</span><span class="br0">&#41;</span>
        <span class="br0">&#123;</span>
            <span class="co1">// Traitement</span>
        <span class="br0">&#125;</span>
    <span class="br0">&#125;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="co1">// A ce moment, on ne peut pas appeler ma_fonction() car sa déclaration ne s'est pas faite</span>
&nbsp;
<span class="re0">$instance</span> <span class="sy0">=</span> <span class="kw2">new</span> MaClasse<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="re0">$instance</span><span class="sy0">-&gt;</span><span class="me1">registerFunction</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
<span class="co1">// Maintenant on peut l'appeler</span>
ma_fonction<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="sy1">?&gt;</span></pre></td></tr></table></div>

<p>Comme dit précédemment, on pourra donc également appeler <strong>ma_fonction()</strong> à l&#8217;intérieur d&#8217;une méthode d&#8217;une autre classe ou n&#8217;importe où dans le programme.</p>
<p>Attention cependant : <strong>PHP </strong>n&#8217;accepte pas la redéfinition des fonctions déjà déclarées, ce qui veut dire que si on s&#8217;amuse à appeler une deuxième fois la méthode <strong>registerFunction()</strong>, on aura un beau message d&#8217;erreur.</p>
<p>Comme quoi, relire les bases de temps en temps ça fait pas de mal <img src='http://www.coolcoyote.net/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.coolcoyote.net/php-mysql/portee-des-fonctions/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<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>Installation de APC sous Debian</title>
		<link>http://www.coolcoyote.net/php-mysql/installation-de-apc-sous-debian</link>
		<comments>http://www.coolcoyote.net/php-mysql/installation-de-apc-sous-debian#comments</comments>
		<pubDate>Mon, 07 Jun 2010 13:50:16 +0000</pubDate>
		<dc:creator>Denis S.</dc:creator>
				<category><![CDATA[Linux Debian]]></category>
		<category><![CDATA[PHP - MySQL]]></category>
		<category><![CDATA[apc]]></category>
		<category><![CDATA[debian]]></category>
		<category><![CDATA[opcode]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://www.coolcoyote.net/?p=252</guid>
		<description><![CDATA[APC est un cache d&#8217;OPCodes pour PHP. Il permet de mettre en cache au niveau serveur le code de PHP précompilé afin de ne pas refaire ce traitement.
Vous trouverez plus d&#8217;informations dans l&#8217;article de Julien Pauli sur developpez.com.
Ici il s&#8217;agit de voir comment l&#8217;installer sous Debian. Très facile finalement, il existe un paquet pour ça:
&#62; [...]]]></description>
			<content:encoded><![CDATA[<p>APC est un cache d&#8217;OPCodes pour PHP. Il permet de mettre en cache au niveau serveur le code de PHP précompilé afin de ne pas refaire ce traitement.</p>
<p>Vous trouverez plus d&#8217;informations dans <a href="http://julien-pauli.developpez.com/tutoriels/php/apc/" target="_blank">l&#8217;article</a> de <a href="http://julien-pauli.developpez.com/" target="_blank">Julien Pauli</a> sur developpez.com.</p>
<p>Ici il s&#8217;agit de voir comment l&#8217;installer sous Debian. Très facile finalement, il existe un paquet pour ça:</p>
<pre class="code">&gt; apt-get install php-apc</pre>
<p>Il faudra bien sûr redémarrer Apache.</p>
<p>Le fichier permettant le monitoring du cache est situé dans <strong>/usr/share/doc/php-apc</strong> et s&#8217;appelle <strong>apc.php.gz</strong>. Il faudra donc le décompresser:</p>
<pre class="code">&gt; gzip -d apc-php.gz</pre>
<p>Il vous suffit de déplacer ce fichier où bon vous semble.</p>
<p>A noter que le fichier de config d&#8217;APC se situe dans:</p>
<pre class="code">/etc/php5/conf.d/apc.ini</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.coolcoyote.net/php-mysql/installation-de-apc-sous-debian/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>
		<item>
		<title>Dépendances et exceptions</title>
		<link>http://www.coolcoyote.net/php-mysql/dependances-et-exceptions</link>
		<comments>http://www.coolcoyote.net/php-mysql/dependances-et-exceptions#comments</comments>
		<pubDate>Sat, 09 Jan 2010 11:14:47 +0000</pubDate>
		<dc:creator>Denis S.</dc:creator>
				<category><![CDATA[PHP - MySQL]]></category>
		<category><![CDATA[classes]]></category>
		<category><![CDATA[dépendance]]></category>
		<category><![CDATA[exceptions]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://www.coolcoyote.net/?p=218</guid>
		<description><![CDATA[A l&#8217;heure où j&#8217;entends beaucoup parler d&#8217;objet, de framework, de dépendance faible, d&#8217;injection de dépendance etc. je me suis posé une question. Admettons que dans mon petit framework sans prétention j&#8217;ai envie que mes modules soient complètement indépendants, c&#8217;est-à-dire que je puisse les prendre un à un et les utiliser avec un projet complètement différent, [...]]]></description>
			<content:encoded><![CDATA[<p>A l&#8217;heure où j&#8217;entends beaucoup parler d&#8217;<strong>objet</strong>, de <strong>framework</strong>, de <strong>dépendance faible</strong>, <strong>d&#8217;injection de dépendance</strong> etc. je me suis posé une question. Admettons que dans mon petit framework sans prétention j&#8217;ai envie que mes modules soient complètement indépendants, c&#8217;est-à-dire que je puisse les prendre un à un et les utiliser avec un projet complètement différent, hors framework. <strong>Zend Framework</strong> fait cela. Cependant je me suis demandé comment gérer des exceptions personnalisées dans ce cas ?</p>
<p>En effet, dans mon framework, j&#8217;ai créé une classe d&#8217;exception qui hérite de <em>Exception </em>et qui rajoute des fonctionnalités comme par exemple une méthode permettant d&#8217;afficher le message d&#8217;erreur bien formaté en HTML avec un fond rouge et presque un gyrophare sur le dessus. Oui mais voilà, quand dans un de mes modules j&#8217;ai besoin d&#8217;utiliser une exception et que j&#8217;ai à afficher le message en utilisant une méthode personnalisée de mon exception, cela casse complètement l&#8217;indépendance de mon module. Je ne peux plus le sortir de son contexte car il dépend désormais de la classe d&#8217;exception de mon framework ce qui est contraire à ce que je veux.</p>
<p><span id="more-218"></span></p>
<p>J&#8217;ai vu que Zend Framework crée une classe d&#8217;exception spécifique pour son module héritée de la classe d&#8217;exception du framework, ce qui lui rend à peu près son indépendance puisqu&#8217;en changeant simplement la classe parent, on peut hériter directement de la classe <em>Exception</em>.</p>
<p>Par exemple pour le module de cache, on trouve cette classe d&#8217;exception:<br />
<code lang="php" escaped="true">&lt;?php<br />
class Zend_Cache_Exception extends Zend_Exception {}<br />
?&gt;</code><br />
En changeant la classe parent on rend le module indépendant:<br />
<code lang="php" escaped="true">&lt;?php<br />
class Zend_Cache_Exception extends Exception {}<br />
?&gt;</code><br />
Oui mais voilà, dans ce cas<em> Zend_Exception</em> qui hérite directement de <em>Exception </em>n&#8217;apporte rien de nouveau. Aucune nouvelle méthode, aucune fonctionnalité. Or dans mon cas, si j&#8217;utilise cette façon de procéder les méthodes personnalisées de ma classes d&#8217;exception ne seront plus disponibles lorsque je changerai la classe parent par <em>Exception</em>. Une seule conclusion m&#8217;est venue à l&#8217;esprit: je ne doit pas utiliser les fonctionnalités spéciales de ma classe d&#8217;exception dans mes modules. Dommage, car j&#8217;ai besoin d&#8217;afficher mes messages d&#8217;erreurs comme je le veux&#8230;</p>
<p>Et puis je me suis demandé si c&#8217;était vraiment le rôle de mon module de stopper l&#8217;exécution du programme pour afficher le message d&#8217;erreur. Non finalement. Si je prends pour exemple l&#8217;extension <strong>mysqli </strong>de PHP, elle ne bloque pas l&#8217;exécution du programme si la connexion à la base ne se fait pas. Elle se contente de fournir des méthodes pour récupérer les erreurs. C&#8217;est dans cette direction que je vais aller.</p>
<p>Tout d&#8217;abord, voici une structure de classe pour mon module avec un exemple d&#8217;exception :<br />
<code lang="php" escaped="true">&lt;?php<br />
class MonModule<br />
{<br />
    private $_error = NULL;</p>
<p>    public function __construct()<br />
    {<br />
        try {<br />
            if (!condition) {<br />
                throw new Exception('Message d\'erreur');<br />
            }</p>
<p>            // Suite du code exécuté<br />
        } catch (Exception $e) {<br />
            $this-&gt;_error = $e-&gt;getMessage();<br />
        }<br />
    }</p>
<p>    public function getError()<br />
    {<br />
        return $this-&gt;_error;<br />
    }<br />
}<br />
?&gt;</code><br />
Dans ce code on voir donc que mon module n&#8217;affiche pas le message d&#8217;erreur. Il se contente de le passer à un membre. Dans mon contrôleur, je vais pouvoir faire entrer ma classe d&#8217;exception personnalisée en action:<br />
<code lang="php" escaped="true">&lt;?php<br />
try {<br />
    $instance = new MonModule();</p>
<p>    if ($instance-&gt;getError()) {<br />
        throw new MyException($instance-&gt;getError());<br />
    }<br />
} catch (MyException $e) {<br />
    $e-&gt;methodePerso();<br />
}<br />
?&gt;</code><br />
Ici on travaille directement sur l&#8217;instanciation de la classe <strong>MonModule()</strong>, du coup la valeur retournée par le constructeur est forcément une instance, mais lors de l&#8217;utilisation de cette technique sur les méthodes de la classe, on peut améliorer la chose en retournant <em>false </em>:<br />
<code lang="php" escaped="true">&lt;?php<br />
class MonModule<br />
{<br />
    private $_error = NULL;</p>
<p>    public function maMethode()<br />
    {<br />
        try {<br />
            if (!condition) {<br />
                throw new Exception('Message d\'erreur');<br />
            }</p>
<p>            // Suite du code exécuté<br />
            return $this;<br />
        } catch (Exception $e) {<br />
            $this-&gt;_error = $e-&gt;getMessage();<br />
            return false;<br />
        }<br />
    }</p>
<p>    public function getError()<br />
    {<br />
        return $this-&gt;_error;<br />
    }<br />
}<br />
?&gt;</code><br />
Et dans le contrôleur :<br />
<code lang="php" escaped="true">&lt;?php<br />
try {<br />
    $instance = new MonModule();</p>
<p>    if (!$instance-&gt;maMethode()) {<br />
        throw new MyException($instance-&gt;getError());<br />
    }<br />
} catch (MyException $e) {<br />
    $e-&gt;methodePerso();<br />
}<br />
?&gt;</code><br />
Je ne sais pas si c&#8217;est la méthode idéale, mais au moins je suis sûr de conserver l&#8217;indépendance de mes classes et de mes exceptions.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.coolcoyote.net/php-mysql/dependances-et-exceptions/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Transfert de fichiers via SSH</title>
		<link>http://www.coolcoyote.net/linux-debian/transfert-de-fichiers-via-ssh</link>
		<comments>http://www.coolcoyote.net/linux-debian/transfert-de-fichiers-via-ssh#comments</comments>
		<pubDate>Tue, 18 Aug 2009 20:53:48 +0000</pubDate>
		<dc:creator>Denis S.</dc:creator>
				<category><![CDATA[Linux Debian]]></category>
		<category><![CDATA[debian]]></category>
		<category><![CDATA[fichier]]></category>
		<category><![CDATA[scp]]></category>
		<category><![CDATA[ssh]]></category>
		<category><![CDATA[transfert]]></category>

		<guid isPermaLink="false">http://www.coolcoyote.net/?p=165</guid>
		<description><![CDATA[Dernièrement j&#8217;ai eu à migrer le site d&#8217;un client d&#8217;un serveur dédié à un autre.
Au lieu de faire un backup des données sur ma machine puis les renvoyer sur le nouveau serveur, j&#8217;ai décidé de faire directement un transfert de serveur à serveur via SSH. C&#8217;est nettement plus rapide car on bénéficie de la bande [...]]]></description>
			<content:encoded><![CDATA[<p>Dernièrement j&#8217;ai eu à migrer le site d&#8217;un client d&#8217;un serveur dédié à un autre.</p>
<p>Au lieu de faire un backup des données sur ma machine puis les renvoyer sur le nouveau serveur, j&#8217;ai décidé de faire directement un transfert de serveur à serveur via SSH. C&#8217;est nettement plus rapide car on bénéficie de la bande passante du serveur.</p>
<p><span id="more-165"></span></p>
<p>Pour cela nous allons utiliser la commande <strong>scp</strong>. La procédure est toute simple, on se loggue sur le serveur de destination et on tape la commande suivante:</p>
<pre class="code">&gt; scp -pr user@host:/home/user/www/ /home/user/</pre>
<p>Quelques précisions:</p>
<ul>
<li><strong>-pr</strong> : signifie que l&#8217;on copie tout le contenu récursivement (dossiers, sous-dossiers et leur contenu) et que l&#8217;on veut conserver les options des fichiers</li>
<li><strong>user@host</strong> : le login et l&#8217;adresse du serveur sur lequel on va chercher les fichiers. L&#8217;utilisateur est bien sûr un utilisateur valide sur le serveur sur lequel nous allons récupérer le contenu et qui a les droits de lecture sur les fichiers et dossiers que l&#8217;on veut télécharger.</li>
<li><strong>/home/user/www</strong> : le chemin du répertoire contenant les fichiers à copier. Bien entendu c&#8217;est à personnaliser</li>
<li><strong>/home/user/</strong> : le chemin de destination des fichiers sur notre serveur local. A personnaliser aussi.</li>
</ul>
<p>Notez que l&#8217;on vous demandera bien évidemment le mot de passe de l&#8217;utilisateur afin de pouvoir se connecter au serveur distant.</p>
<p>Les fichiers seront copiés en conservant le chmod de chaque fichier. Par contre leur appartenance sera changée selon l&#8217;utilisateur sous lequel vous allez faire l&#8217;opération. Si vous avez fait l&#8217;opération sous <strong>root</strong>, n&#8217;oubliez pas de faire un petit</p>
<pre class="code">&gt; chown -R user:group /home/user/www</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.coolcoyote.net/linux-debian/transfert-de-fichiers-via-ssh/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>IE7 et z-index</title>
		<link>http://www.coolcoyote.net/integration-css-xhtml/ie7-et-z-index</link>
		<comments>http://www.coolcoyote.net/integration-css-xhtml/ie7-et-z-index#comments</comments>
		<pubDate>Wed, 12 Aug 2009 14:01:06 +0000</pubDate>
		<dc:creator>Denis S.</dc:creator>
				<category><![CDATA[Intégration - CSS / XHTML]]></category>
		<category><![CDATA[absolute]]></category>
		<category><![CDATA[bug]]></category>
		<category><![CDATA[Internet Explorer 7]]></category>
		<category><![CDATA[position]]></category>
		<category><![CDATA[relative]]></category>
		<category><![CDATA[z-index]]></category>

		<guid isPermaLink="false">http://www.coolcoyote.net/?p=206</guid>
		<description><![CDATA[Internet Explorer 7 possède un bug bien particulier qui lui est propre au niveau des z-index. En tous les cas je ne l&#8217;ai pas retrouvé ni sur IE6 (pour une fois) ni sur IE8.
Ce bug m&#8217;est apparu lorsque j&#8217;ai créé un menu déroulant en CSS / jQuery impliquant des listes positionnées en relative et absolute [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Internet Explorer 7</strong> possède un bug bien particulier qui lui est propre au niveau des <strong>z-index</strong>. En tous les cas je ne l&#8217;ai pas retrouvé ni sur IE6 (pour une fois) ni sur IE8.</p>
<p>Ce bug m&#8217;est apparu lorsque j&#8217;ai créé un menu déroulant en CSS / jQuery impliquant des listes positionnées en <strong>relative </strong>et <strong>absolute </strong>et que dans le contenu situé sous le menu j&#8217;ai un ou plusieurs éléments positionnés également en <strong>relative </strong>ou <strong>absolute</strong>. Dans ce cas j&#8217;avais le menu déroulant qui passait sous les éléments du contenu. Problème de <strong>z-index</strong> semble-t-il. Pourtant malgré le fait de bien paramétrer des <strong>z-index</strong> sur les éléments du menu et les éléments du contenu, rien à faire, le menu déroulant reste derrière. Grossièrement, le code a cette structure:</p>
<pre class="code">&lt;div id="header"&gt;
    &lt;div id="div_menu"&gt;
        &lt;ul id="menu"&gt;
            &lt;li&gt;&lt;a href="#"&gt;Lien 1&lt;/a&gt;
                &lt;ul class="sousmenu"&gt;
                    &lt;li&gt;&lt;a href="#"&gt;Sous-menu&lt;/a&gt;&lt;/li&gt;
                    &lt;li&gt;&lt;a href="#"&gt;Sous-menu&lt;/a&gt;&lt;/li&gt;
                    &lt;li&gt;&lt;a href="#"&gt;Sous-menu&lt;/a&gt;&lt;/li&gt;
                &lt;/ul&gt;
            &lt;/li&gt;
        &lt;/ul&gt;
    &lt;/div&gt;
&lt;/div&gt;
&lt;div id="contenu"&gt;
    &lt;div id="element_en_absolu"&gt;Le sous menu passe derrière !&lt;/div&gt;
&lt;/div&gt;</pre>
<p>Tous mes <strong>z-index</strong> avaient été placés sur les éléments <em>#div_menu</em>, <em>#menu</em>, <em>#menu li</em> etc.. ainsi que sur <em>#element_en_absolu</em>.</p>
<p>Finalement j&#8217;ai trouvé la solution <a href="http://www.brenelz.com/blog/2009/02/03/squish-the-internet-explorer-z-index-bug/" target="_blank">sur ce blog</a>. J&#8217;ai résolu le problème en définissant un <strong>z-index</strong> le plus élevé sur <em>#header</em>. Ce qui veut dire qu&#8217;il faut donc définir un<strong> z-index</strong> qui soit le plus élevé que tous les autre sur le ou les parents du menu.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.coolcoyote.net/integration-css-xhtml/ie7-et-z-index/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

