<?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>Thu, 24 Jun 2010 09:40:54 +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>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>10</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>
		<item>
		<title>Rediriger le traffic HTTP d&#8217;un serveur à un autre avec Apache</title>
		<link>http://www.coolcoyote.net/linux-debian/rediriger-le-traffic-http-dun-serveur-a-un-autre-avec-apache</link>
		<comments>http://www.coolcoyote.net/linux-debian/rediriger-le-traffic-http-dun-serveur-a-un-autre-avec-apache#comments</comments>
		<pubDate>Tue, 04 Aug 2009 20:13:07 +0000</pubDate>
		<dc:creator>Denis S.</dc:creator>
				<category><![CDATA[Linux Debian]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[debian]]></category>
		<category><![CDATA[http]]></category>
		<category><![CDATA[proxy]]></category>

		<guid isPermaLink="false">http://www.coolcoyote.net/?p=170</guid>
		<description><![CDATA[Un site  est sur un serveur dédié A. Vous voulez le migrer sur un serveur dédié B. La migration des fichiers et de la base de données éventuelle ne pose pas spécialement de problème. Ce qui est plus délicat, c&#8217;est lorsque vous allez modifier les pointages DNS du nom de domaine : en effet, [...]]]></description>
			<content:encoded><![CDATA[<p>Un site  est sur un serveur dédié A. Vous voulez le migrer sur un serveur dédié B. La migration des fichiers et de la base de données éventuelle ne pose pas spécialement de problème. Ce qui est plus délicat, c&#8217;est lorsque vous allez modifier les pointages DNS du nom de domaine : en effet, le temps de la propagation, certains visiteurs vont rapidement arriver sur le serveur dédié B alors que d&#8217;autres vont rester bloqués sur le serveur A pendant 24 à 48h. Si dans le cadre d&#8217;un site statique cela ne pose aucun souci, c&#8217;est plus problématique dans le cas d&#8217;un site dynamique car cela peut engendrer une désynchronisation de la base de données entre les deux serveurs et conduire à des pertes de données.</p>
<p>L&#8217;idéal serait que le serveur A puisse rediriger les visiteurs sur le serveur B le temps de la propagation des DNS. Apache va nous y aider.</p>
<p><span id="more-170"></span></p>
<p>Pour cela il faut dans un premier temps activer le module proxy dans Apache. Nous allons ici nous contenter de rediriger le traffic HTTP uniquement.</p>
<pre class="code">&gt; cd /etc/apache2/mods-enabled
&gt; ln -s ../mods-available/proxy.conf proxy.conf
&gt; ln -s ../mods-available/proxy.load proxy.load
&gt; ln -s ../mods-available/proxy_http.load proxy_http.load</pre>
<p>Ensuite on va modifier le virtualhost du domaine en question:</p>
<pre class="code">&lt;VirtualHost *&gt;
    ServerName mondomaine.com
    ServerAlias mondomaine.com www.mondomaine.com

    &lt;Proxy *&gt;
        Order deny,allow
        Allow from all
    &lt;/Proxy&gt;

    ProxyRequests Off
    ProxyPass / http://mon_ip_de_domaine/~user/
    ProxyPassReverse / http://mon_ip_de_domaine/~user/
&lt;/VirtualHost&gt;</pre>
<p>Dans ce schéma, nous voyons que sur le serveur de destination nous avons activé le <strong>mod_userdir</strong> afin de pouvoir accéder au site par une adresse temporaire.</p>
<p>Un petit</p>
<pre class="code">&gt; /etc/init.d/apache2 reload</pre>
<p>et votre traffic devrait être redirigé.</p>
<p>Attention cependant pour tous les sites dynamiques utilisant PHP : avec cette méthode,  les variables <strong>$_SERVER['PHP_SELF']</strong> et <strong>$_SERVER['REQUEST_URI']</strong> auront les informations du serveur de destination&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.coolcoyote.net/linux-debian/rediriger-le-traffic-http-dun-serveur-a-un-autre-avec-apache/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Configuration d&#8217;un serveur dédié chez OVH</title>
		<link>http://www.coolcoyote.net/linux-debian/configuration-dun-serveur-dedie-chez-ovh</link>
		<comments>http://www.coolcoyote.net/linux-debian/configuration-dun-serveur-dedie-chez-ovh#comments</comments>
		<pubDate>Wed, 15 Jul 2009 15:57:35 +0000</pubDate>
		<dc:creator>Denis S.</dc:creator>
				<category><![CDATA[Linux Debian]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[configuration]]></category>
		<category><![CDATA[Exim4]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[ovh]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[phpMyAdmin]]></category>
		<category><![CDATA[ProFTPD]]></category>
		<category><![CDATA[serveur dédié]]></category>

		<guid isPermaLink="false">http://www.coolcoyote.net/?p=64</guid>
		<description><![CDATA[Ça faisait un moment que je n&#8217;avais pas eu à configurer un serveur dédié pour de la production. L&#8217;occasion d&#8217;en faire un petit article, le but étant de faire un serveur très basique, sans gestion de boîte mails, sans LDAP, sans chroot, etc. Juste une base LAMP.
Ce serveur dédié a été choisi chez OVH. J&#8217;ai [...]]]></description>
			<content:encoded><![CDATA[<p>Ça faisait un moment que je n&#8217;avais pas eu à configurer un serveur dédié pour de la production. L&#8217;occasion d&#8217;en faire un petit article, le but étant de faire un serveur très basique, sans gestion de boîte mails, sans LDAP, sans chroot, etc. Juste une base LAMP.</p>
<p>Ce serveur dédié a été choisi chez OVH. J&#8217;ai bien sûr demandé une Debian nue mais ça n&#8217;a pas vraiment été le cas. En fait, OVH livre une distribution Debian avec un noyau personnalisé et plusieurs outils installés par défaut. Suite à une mésaventure lors du passage de <strong>Etch</strong> à <strong>Lenny</strong> sur un de mes dédiés, j&#8217;ai décidé de ne plus laisser le noyau d&#8217;OVH mais d&#8217;installer un noyau standard. Si cette manipulation vous intéresse, <a href="http://www.coolcoyote.net/linux-debian/changer-le-noyau-dune-debian-ovh">voyez ce billet</a>. Sinon ce qui suit fonctionne quand même parfaitement.</p>
<p><span id="more-64"></span></p>
<h3>Les outils</h3>
<p>La première chose que je fais en arrivant sur une installation neuve, c&#8217;est de configurer le raccourcit <strong>ll</strong> afin d&#8217;avoir un <strong>ls</strong> détaillé et en couleur. J&#8217;ai déjà fais un billet là-dessus que vous pourrez trouver <a href="http://www.coolcoyote.net/linux-debian/raccourcis-et-couleurs-sous-la-console">à cette adresse</a>.</p>
<p>La deuxième chose est de configurer un accès par clé privée <strong>ssh</strong>. L&#8217;article est <a href="http://www.coolcoyote.net/linux-debian/ssh-cle-publiqueprivee">à cet endroit</a>.</p>
<p>Ceci fait, nous allons faire une première mise à jour du système:</p>
<pre class="code">&gt; apt-get update
&gt; apt-get -u dist-upgrade</pre>
<p>Vient ensuite l&#8217;installation de quelques outils. Chez moi ils étaient déjà pré-installés mais s&#8217;ils ne le sont pas, faites-le:</p>
<ul>
<li><strong>aptitude</strong> (permet de gérer les packages dans un mode semi-graphique)</li>
<li><strong>vim</strong> (qui est une version un peu plus évoluée de vi et qui permet notamment la coloration synthaxique)</li>
<li><strong>screen</strong> (permet de créer des consoles virtuelles supplémentaires, voir <a href="http://www.coolcoyote.net/linux-debian/les-screens-sous-debian">ce billet</a>)</li>
</ul>
<p>Pour activer la coloration syntaxique dans <strong>vim</strong> il faut taper la commande</p>
<pre class="code">:syn on</pre>
<p>Si vous voulez qu&#8217;elle soit permanente, créez le fichier <strong>.vimrc </strong>dans votre répertoire utilisateur et insérez la ligne de commande:</p>
<pre class="code">syn on</pre>
<h3>Déplacer le dossier /var</h3>
<p>Je pense que la première chose à faire, avant de se retrouver avec des daemons qui tournent de tous les côtés, c&#8217;est de déplacer le dossier <strong>/var</strong>. En effet les partitions système ne sont pas très grosses chez OVH et il arrivera un moment où les logs et les bases de données vont saturer cette partition et amener à un plantage du serveur. Etant donné qu&#8217;on a de la place dans <strong>/home</strong>, on va y déplacer le dossier <strong>/var</strong></p>
<pre class="code">&gt; cp -Rp var/ /home/
&gt; mv /var/ /var.old/
&gt; ln -s /home/var/ var</pre>
<h3>Installation de MySQL</h3>
<p>rien de plus simple:</p>
<pre class="code">&gt; apt-get install mysql-server</pre>
<p>Dans la dernière version que j&#8217;ai installé, MySQL me propose désormais de paramétrer le mot de passe <strong>root </strong>du serveur. Je vous encourage fortement à le faire dès maintenant. Si vous ne le faites pas, vous pourrez le faire plus tard mais le plus tôt est le mieux car à ce niveau, ce n&#8217;est plus un trou de sécu, c&#8217;est la porte ouverte à toutes les fenêtres  <img src='http://www.coolcoyote.net/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<h3>Installation d&#8217;Apache 2.2</h3>
<p>Pareil, trop dur Debian:</p>
<pre class="code">&gt; apt-get install apache2-mpm-prefork</pre>
<p>Notez que l&#8217;on installe ce paquet là d&#8217;Apache car le module PHP5 en dépend. Il ne fonctionne pas avec le paquet classique d&#8217;Apache 2.2.</p>
<h3>Installation de PHP 5</h3>
<pre class="code">&gt; apt-get install libapache2-mod-php5</pre>
<p>On va devoir également installer quelques modules supplémentaires pour PHP:</p>
<pre class="code">&gt; apt-get install php5-cli
&gt; apt-get install php5-gd
&gt; apt-get install php5-mcrypt
&gt; apt-get install php5-mysql</pre>
<p>sont un minimum je pense. On peut facilement voir la liste des modules dispos en faisant un petit:</p>
<pre class="code">&gt; dpkg -l *php5*</pre>
<p>A ce niveau on peut déjà faire quelques petits tests. Déjà il faut redémarrer Apache:</p>
<pre class="code">&gt; /etc/init.d/apache2 restart</pre>
<p>Puis les tests : taper l&#8217;adresse du serveur dans votre navigateur web. Vous devriez avoir le fameux &laquo;&nbsp;It Works!&nbsp;&raquo; d&#8217;Apache.</p>
<p>Dans le répertoire <strong>/var/www </strong>créez un fichier <strong>info.php</strong> dans lequel vous allez mettre 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="kw3">phpinfo</span><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>Pareil, dans votre navigateur tapez : <strong>http://monserver/info.php</strong>. Normalement la config de PHP apparaît.</p>
<h3>Configuration</h3>
<p>maintenant que l&#8217;environnement LAMP est installé, on va faire un peu de configuration.</p>
<p>Tout d&#8217;abord pour MySQL, de base il n&#8217;y a rien de spécial à toucher. Cependant si vous désirez personnaliser votre installation, vous pouvez le faire en rajoutant un fichier dans <strong>/etc/mysql/conf.d</strong>. Toutes les options que vous y insèrerez seront prises en compte automatiquement.</p>
<p>Pour PHP, il faut faire la configuration classique de <strong>php.ini</strong> qui se trouve dans <strong>/etc/php5/apache2/php.ini</strong></p>
<p>Ce fichier est configuré de façon très basique. Tel quel il fonctionne, il y a cependant moyen de l&#8217;améliorer un petit peu:</p>
<p>Si vous n&#8217;avez pas de scripts PHP balisés par <strong>&lt;?</strong> et<strong> ?&gt;</strong>, mettez l&#8217;option <strong>short_open_tag</strong> à <strong>Off</strong>. Cela obligera les scripts PHP à être balisés par <strong>&lt;?php</strong> et <strong>?&gt;</strong>. Pourquoi? A partir de PHP6, le balisage court n&#8217;existera plus. Autant se mettre à la norme dès maintenant.</p>
<p>Si vous voulez désactiver certaines fonctions par mesure de sécurité (exec par exemple), vous pouvez les rajouter à l&#8217;option disable_functions en les séparant par des virgules.</p>
<p>En production, on conseille de passer l&#8217;option <strong>display_errors</strong> à <strong>Off</strong> car cela peu donner des indications importantes à une personne mal intentionnée. Par contre on passera le paramètre <strong>log_errors</strong> à <strong>On</strong> pour que les messages d&#8217;erreur soient enregistrés dans un fichier.</p>
<p>Si vous avez de vieux sites codés en PHP, peut-être aurez vous besoin de passer le paramètre <strong>register_globals</strong> à <strong>On</strong>. Si vous pouvez vous en passer ce n&#8217;est que mieux, question de sécurité.</p>
<p>Vous pouvez également décommenter la ligne:</p>
<pre class="code">;include_path = ".:/usr/share/php"</pre>
<p>Cela vous permettra de protéger certains fichiers d&#8217;inclusion en les déportant de l&#8217;espace accessible par le web.</p>
<p>Passons maintenant à la configuration d&#8217;Apache. Tout se passe dans le répertoire <strong>/etc/apache2/</strong></p>
<p>La première chose que nous allons faire c&#8217;est activer les modules dont nous avons besoin. La gestion des modules Apache à la sauce Debian est plutôt bien foutue: Dans le répertoire <strong>mods-available</strong> se trouvent tous les modules disponibles pour Apache. Le répertoire <strong>mods-enabled</strong> contient les modules activés. Si on veut activer un module, on ne va pas copier le module en question du répertoire <strong>mods-available</strong> au répertoire <strong>mods-enabled</strong>, mais plutôt faire un lien symbolique dans le répertoire <strong>mods-enabled</strong> vers les modules que l&#8217;on veut activer. Par exemple, pour activer le <strong>mod_rewrite</strong>, se placer dans le répertoire <strong>mods-enabled</strong> et taper la commande:</p>
<pre class="code">&gt; ln -s ../mods-available/rewrite.load rewrite.load</pre>
<p>Faire cela pour tous les modules que vous voulez activer. Si par exemple vous voulez activer le module <strong>userdir</strong>, n&#8217;oubliez pas qu&#8217;il y a deux liens à faire: un pour le <strong>.load</strong> et un pour le <strong>.conf</strong></p>
<p>Les autres éléments de configuration se trouvent dans le répertoire <strong>/etc/apache2/conf.d</strong>. A l&#8217;image de ce qui se fait pour MySQL, tout fichier créé dans ce répertoire et contenant des directives sera pris en compte et écrasera la configuration d&#8217;origine. De base il y a un fichier charset qui contient une directive</p>
<pre class="code">AddDefaultCharset UTF-8</pre>
<p>Qui active le jeu de caractère UTF-8 par défaut. Si vous préférez activer l&#8217;ISO-8859-1 par défaut, remplacez par:</p>
<pre class="code">AddDefaultCharset on</pre>
<p>On va également créer un fichier <strong>directoryindex</strong> contenant la directive suivante:</p>
<pre class="code">DirectoryIndex index.html index.htm index.cgi index.pl index.php index.xhtml</pre>
<p>Qui permet d&#8217;accepter une page <strong>index.php</strong> ou <strong>index.cgi</strong> comme page d&#8217;accueil pour un site</p>
<p>Si vous voulez accepter les CGI, il faut egalement créer un fichier <strong>cgi.conf</strong> dans lequel on va mettre:</p>
<pre class="code">AddHandler cgi-script .pl
AddHandler cgi-script .cgi</pre>
<p>Ce qui va permettre d&#8217;accepeter les fichier <strong>.pl</strong> et <strong>.cgi</strong> comme CGI</p>
<p>Vous pouvez bien sûr continuer comme ça à paramétrer tout ce que vous voulez.</p>
<h3>Installation de ProFTPD</h3>
<p>On est presque prêt à accueillir nos premiers sites. Mais pour cela il faut les uploader sur le serveur et pour ça il nous faut un serveur FTP. En voici un : <strong>ProFTPD</strong></p>
<pre class="code">&gt; apt-get install proftpd</pre>
<p>On vous demandera si vous voulez le lancer sous <strong>inetd</strong> ou indépendamment, choisissez la deuxième option.</p>
<p>Après installation, le serveur est déjà prêt à l&#8217;utilisation. Si vous voulez changer la configuration, vous pouvez le faire en modifiant le fichier <strong>/etc/proftpd/proftpd.conf</strong>, mais on peut déjà exploiter le serveur tel quel.</p>
<p>Il n&#8217;y a juste qu&#8217;une chose à modifier dans la configuration du serveur. Il faut rajouter les lignes suivantes:</p>
<pre class="code">DefaultRoot ~
IdentLookups off
UseReverseDNS off</pre>
<p>La première instruction permet de bloquer chaque utilisateur dans son répertoire et évite qu&#8217;il se balade sur tout le serveur. Les deuxièmes et troisièmes instructions désactivent des traitements DNS de proftpd et permettent une connexion rapide au serveur (essayez les deux et voyez la différence).</p>
<p>Maintenant, il ne nous reste plus que 2 choses à faire: créer un utilisateur FTP avec son espace, et configurer le domaine associé sous Apache pour qu&#8217;il pointe à cet endroit.</p>
<p>Pour créer un utilisateur FTP, rien de plus simple, on va créer un utilisateur système:</p>
<pre class="code">&gt; addgroup nom_user
&gt; adduser --ingroup nom_user nom_user</pre>
<p>Cela va créer le répertoire personnel de l&#8217;utilisateur dans le répertoire <strong>/home</strong></p>
<p>Lors de la création de cet utilisateur, vous devrez saisir des renseignements. Le plus important est bien sûr le mot de passe, le reste n&#8217;est pas important.</p>
<p>On peut désormais configurer notre client FTP pour se connecter:</p>
<p>host: IP_serveur<br />
login: nom_user<br />
mot de passe : pass_user</p>
<p>Une fois connecté, on crée un répertoire <strong>www</strong> qui contiendra le site et on peu mettre une page d&#8217;accueil quelconque pour faire nos tests.</p>
<p>Tester avec le module <strong>userdir</strong></p>
<p>Le module <strong>userdir </strong>permet de se connecter à l&#8217;espace web d&#8217;un utilisateur du système sans le nom de domaine. L&#8217;url sera de la forme:</p>
<pre>http://ip_serveur/~nom_utilisateur/</pre>
<p>Pour pouvoir faire cela, il faut dans un premier temps activer le module <strong>userdir </strong>dans Apache (voir plus haut). Puis dans le répertoire <strong>/etc/apache2/conf.d</strong> créer un fichier <strong>userdir </strong>contenant les commandes suivantes:</p>
<pre class="code">&lt;IfModule mod_userdir.c&gt;
    UserDir www
    UserDir disabled root

    &lt;Directory /home/*/www&gt;
        AllowOverride FileInfo AuthConfig Limit
        Options Indexes SymLinksIfOwnerMatch IncludesNoExec
    &lt;/Directory&gt;
&lt;/IfModule&gt;</pre>
<p>On relance Apache et normalement si vous faites l&#8217;adresse indiquée plus haut, vous devriez voir votre page uploadée tout à l&#8217;heure.</p>
<p>Note: Si vous utilisez le module <strong>rewrite</strong>, je vous déconseille fortement d&#8217;utiliser l&#8217;option <strong>MultiViews </strong>de la commande <strong>Options </strong>car personnellement j&#8217;ai eu des interférences entre les deux.</p>
<h3>Configuration d&#8217;un domaine:</h3>
<p>Maintenant, on va configurer Apache pour que mondomaine.com pointe sur <strong>/home/nom_user/www</strong>.</p>
<p>Dans le répertoire <strong>/etc/apache2/sites-available</strong> créer le fichier <strong>mondomaine.com</strong>. Y mettre les instructions suivantes:</p>
<pre class="code">&lt;VirtualHost *&gt;
    ServerName www.mondomaine.com
    ServerAlias mondomaine.com www.mondomaine.com
    ServerAdmin webmaster@mondomaine.com

    DocumentRoot /home/nom_utilisateur/www
    ScriptAlias /cgi/ "/home/nom_utilisateur/cgi-bin/"

    &lt;Directory /home/nom_utilisateur/www&gt;
         Options -Indexes
    &lt;/Directory&gt;

    php_admin_value open_basedir "/tmp:/var/lib/php5:/home/nom_utilisateur/www"
&lt;/VirtualHost&gt;</pre>
<p>Vous devez bien sûr encore une fois remplacer les paramètres <strong>mondomaine.com</strong> et <strong>nom_utilisateur</strong> par vos valeurs.</p>
<p>Enregistrez, rechargez Apache et le tour est joué.</p>
<p>Note: il est important de ne pas oublier le paramètre <strong>open_basedir</strong> de PHP, cela empêche les scripts PHP de pouvoir lire n&#8217;importe quel fichier du serveur en le cloisonnant dans le répertoire <strong>www/</strong></p>
<h3>Installation de phpMyAdmin</h3>
<p>Forcément, si vous avez installé <strong>MySQL</strong>, il vous faut <strong>phpMyAdmin</strong>. Il y a deux écoles:</p>
<ul>
<li>Rester à la sauce Debian et installer le package <strong>phpMyAdmin</strong></li>
<li>L&#8217;installer à la main</li>
</ul>
<p>Les deux solutions ont leurs avantages et inconvénients:</p>
<p>Installer le package est simple et la maintenance aussi puisqu&#8217;un simple <strong>apt-get</strong> permet une mise à jour. Par contre les versions ne sont pas à jour. Au moment de la rédaction de ce billet, la version actuelle est en 2.11.9 alors que le package est en 2.9.1. Pour cette raison je préfère une installation manuelle. Par contre cela m&#8217;oblige à me tenir au courant des mises à jour et à les faire manuellement.</p>
<p>Généralement j&#8217;installe phpMyAdmin dans le répertoire <strong>/var/www</strong>. Ainsi on peut accéder à phpMyAdmin par l&#8217;adresse: <strong>http://ip_serveur/phpMyAdmin</strong></p>
<p>L&#8217;avantage de cette méthode est qu&#8217;il est facile de créer des alias ou des redirections de tous les noms de domaine qui seront installés sur le serveur afin qu&#8217;ils aient une url de phpMyAdmin simple. Par exemple une directive:</p>
<pre class="code">Alias /phpMyAdmin /var/www/phpMyAdmin/</pre>
<p>permet une redirection transparente.</p>
<p>une fois phpMyAdmin installé, la première chose à faire est de s&#8217;y logguer afin de paramétrer le mot de passe <strong>root </strong>de MySQL. Si vous ne l&#8217;avez pas fait lors de l&#8217;installation c&#8217;est le moment où jamais !!</p>
<h3>Envoyer des mails avec PHP</h3>
<p>C&#8217;est la dernière chose qui nous manque avant d&#8217;avoir un serveur de production minimal potable. Pour cela on va installer <strong>exim4</strong>:</p>
<pre class="code">&gt; apt-get install exim4</pre>
<p>puis pour la configuration:</p>
<pre class="code">&gt; dpkg-reconfigure exim4-config</pre>
<p>les options:</p>
<ul>
<li>séparer la configuration dans plusieurs fichiers -&gt; Non</li>
<li>Type de configuration -&gt; Distribution directe par SMTP</li>
<li>Nom de courriel du système -&gt; Mettez le nom de domaine principal du serveur ou laissez par défaut</li>
<li>Liste d&#8217;adresses IP -&gt; laissez 127.0.0.1 pour le moment</li>
<li>Autres destinations -&gt; Vide</li>
<li>Domaines à relayer -&gt; Vide</li>
<li>Machines à relayer -&gt; Vide</li>
<li>Faut-il minimiser les requêtes DNS -&gt; Non</li>
<li>Méthode de distribution du courrier local -&gt; laissez &laquo;&nbsp;mbox&nbsp;&raquo;</li>
</ul>
<p>Théoriquement, les emails envoyés de PHP fonctionnent désormais.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.coolcoyote.net/linux-debian/configuration-dun-serveur-dedie-chez-ovh/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Changer le noyau d&#8217;une Debian OVH</title>
		<link>http://www.coolcoyote.net/linux-debian/changer-le-noyau-dune-debian-ovh</link>
		<comments>http://www.coolcoyote.net/linux-debian/changer-le-noyau-dune-debian-ovh#comments</comments>
		<pubDate>Fri, 03 Jul 2009 16:55:46 +0000</pubDate>
		<dc:creator>Denis S.</dc:creator>
				<category><![CDATA[Linux Debian]]></category>
		<category><![CDATA[debian]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[noyau]]></category>
		<category><![CDATA[ovh]]></category>

		<guid isPermaLink="false">http://www.coolcoyote.net/?p=148</guid>
		<description><![CDATA[Malgré le fait de demander une Debian nue à l&#8217;installation de mon serveur dédié, OVH m&#8217;a mis une distrib qui semble un peu modifiée par eux, notamment au niveau du noyau. Le noyau que j&#8217;ai au départ a un nom tout bizarre genre bzImage-2.6.27.10-xxxx-grs-ipv4-64.
En fait c&#8217;est un noyau préparé par OVH qui contient les derniers [...]]]></description>
			<content:encoded><![CDATA[<p>Malgré le fait de demander une Debian nue à l&#8217;installation de mon serveur dédié, OVH m&#8217;a mis une distrib qui semble un peu modifiée par eux, notamment au niveau du noyau. Le noyau que j&#8217;ai au départ a un nom tout bizarre genre bzImage-2.6.27.10-xxxx-grs-ipv4-64.</p>
<p>En fait c&#8217;est un noyau préparé par OVH qui contient les derniers patchs de sécurité et qui permet de se passer de modules externes car ils sont embarqués. Problème: quand j&#8217;ai voulu upgrader ma distrib de Etch à Lenny, j&#8217;ai eu énormément d&#8217;ennuis et j&#8217;ai dû faire appel à un ami spécialiste pour me dépatouiller.</p>
<p>Le premier problème a été Lilo: il a commencé à me mettre des warnings pendant la mise à jour. Comme je n&#8217;étais pas sûr des conséquences que cela aurait au reboot et vu que Lilo commence sérieusement à dater, on a décidé de mettre Grub, et là tout est parti en vrille, ce qui n&#8217;aurait pas été le cas si j&#8217;avais eu un noyau standard&#8230; En effet d&#8217;une part Grub se base sur le nom d&#8217;un noyau standard pour s&#8217;installer, ce qui n&#8217;était pas le cas. La config de grub ne n&#8217;est donc pas faite correctement. On s&#8217;est donc dit que dans ce cas, on allait donner à Grub ce qu&#8217;il voulait, c&#8217;est à dire un noyau standard. Sauf que la il va aussi falloir gérer les modules à la main. En plus de cela le serveur était en raid1 logiciel, ce qui nécessite une maipulation supplémentaire avec Grub.</p>
<p>On va donc essayer à travers cet article de remettre la distribution droite dès le départ étant donné que le serveur dédié sur lequel je refais cette expérience est neuf.</p>
<p><span id="more-148"></span></p>
<p>La première chose à faire est de récupérer toutes les informations nécessaires sur notre hardware, notre architecture, le raid logiciel, etc&#8230;</p>
<p>Déjà, grâce au nom du noyau on sait que l&#8217;on est sur une architecture <strong>64 bits</strong>.</p>
<p>Pour le hardware, on a besoin de savoir quel est le processeur que nous avons, ainsi que la ou les cartes réseaux.  Pour le processeur, on va faire un :</p>
<pre class="code">&gt; vi /var/log/dmesg</pre>
<p>puis on va faire une recherche sur &laquo;&nbsp;Intel&nbsp;&raquo;. Déjà je peux noter les infos suivantes:</p>
<pre class="code">CPU0: Intel(R) Core(TM)2 Duo CPU     E8400  @ 3.00GHz stepping 0a</pre>
<p>Bon, première info&#8230; Le truc à savoir avec l&#8217;architecture 64 bits, c&#8217;est que quel que soit votre processeur (AMD ou Intel), vous devrez installer un noyau AMD64. On peut le voir à cette adresse: <a href="http://www.debian.org/ports/amd64/" target="_blank">http://www.debian.org/ports/amd64/</a></p>
<p><em>Le portage se compose d&#8217;un noyau pour tous les processeurs AMD 64 bits avec l&#8217;extension AMD64 et pour les processeurs Intel avec l&#8217;extension EM64T et d&#8217;un espace utilisateur 64 bits commun.</em></p>
<p>Bref, si je fais un</p>
<pre class="code">&gt; apt-cache seach 'linux-image'</pre>
<p>je tombre sur ce noyau : &nbsp;&raquo; linux-image-2.6.26-2-amd64 &#8211; Linux 2.6.26 image on AMD64&#8243;</p>
<p>C&#8217;est celui-là qu&#8217;il nous faut.</p>
<p>En ce qui concerne la carte réseau, dans un premier temps on a besoin de savoir combien on en a. Pour cela un petit</p>
<pre class="code">&gt; ifconfig</pre>
<p>M&#8217;indique qu&#8217;il n&#8217;y a que <strong>et0</strong> et<strong> lo</strong> (qui est l&#8217;interface locale). Donc je n&#8217;ai qu&#8217;une carte. Pour m&#8217;assurer des modules nécessaires à ma carte réseau, j&#8217;ai trouvé en parcourant les forums un truc plutôt pas mal. Tapez la commande:</p>
<pre class="code">&gt; lspci -n</pre>
<p>Et copiez le contenu du résultat dans le textarea de ce site: <a href="http://kmuto.jp/debian/hcl/" target="_blank">http://kmuto.jp/debian/hcl/</a></p>
<p>Il vous donnera le nom des modules à charger. Dans mon cas c&#8217;est donc le module <strong>r8169</strong> dont j&#8217;ai besoin</p>
<p>Enfin on finit par vérifier si on est en raid ou pas. En tapant :</p>
<pre class="code">&gt; cat /proc/mdstat</pre>
<p>j&#8217;obtiens:</p>
<pre class="code">md1 : active raid1 sdb1[1] sda1[0]
5245120 blocks [2/2] [UU]

md2 : active raid1 sdb2[1] sda2[0]
970992576 blocks [2/2] [UU]</pre>
<p>Donc je sais que je suis en <strong>raid1</strong> sur deux disques serial ATA (sda et sdb).</p>
<p>On a tout ce qu&#8217;il faut pour se lancer. C&#8217;est parti:</p>
<p>On installe grub en premier (en effet notre noyau standard a besoin de grub pour s&#8217;installer sinon on a une erreur).</p>
<pre class="code">&gt; apt-get install grub</pre>
<p>On crée le répertoire de grub dans le répertoire de boot :</p>
<pre class="code">&gt; mkdir /boot/grub</pre>
<p>On fait une première install de grub. Je suis pas sûr que cette étape soit nécessaire, je vérifierai cela lors de ma prochaine installation de dédié <img src='http://www.coolcoyote.net/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<pre class="code">&gt; grub-install /dev/md1</pre>
<p>On installe notre noyau :</p>
<pre class="code">&gt; apt-get install linux-image-2.6.26-2-amd64</pre>
<p>On installe grub :</p>
<pre class="code">&gt; grub-install /dev/md1</pre>
<p>On demande une mise à jour de grub</p>
<pre class="code">&gt; update-grub</pre>
<p>Le problème maintenant c&#8217;est qu&#8217;on est sur du raid logiciel. Notre disque <strong>/dev/md1</strong> n&#8217;est donc pas physique mais virtuel. Et le souci c&#8217;est que notre <em>grub-install</em> ne va pas s&#8217;inscrire sur le secteur de boot de<strong> sda</strong> et <strong>sdb</strong>. Il faut donc faire cette manipulation manuellement :</p>
<pre class="code">&gt; grub
grub&gt; root (hd0,0)
grub&gt; setup (hd0)
grub&gt; setup (hd1)
grub&gt; quit</pre>
<p>Il ne faut pas oublier de le faire sur les deux disques dur, ainsi si un des disques crash, le deuxième sera bootable.</p>
<p>Avant de rebooter, ne pas oublier les modules de la carte réseau ! Dans <strong>/etc/modules</strong> rajouter:</p>
<pre class="code">loop
r8169</pre>
<p>et sauvegardez..</p>
<p>En demandant conseil à mon pote pour réaliser toutes ces manipulations en sécurité, il m&#8217;a dit qu&#8217;on avait eu un problème au niveau du package &laquo;&nbsp;mdadm&nbsp;&raquo; qui est le package gérant le raid. En effet, lors de notre expérience malheureuse, il s&#8217;est rendu compte que ce paquet n&#8217;était pas installé, le noyau d&#8217;OVH embarquant ce dont il a besoin pour le faire fonctionner. En ce qui me concerne sur ce nouveau serveur, le package est bien présent mais n&#8217;hésitez pas à vérifier et à l&#8217;installer le cas échéant sinon vous aurez une surprise au reboot !</p>
<p>Vous pouvez y aller maintenant.</p>
<pre class="code">&gt; reboot</pre>
<p>et croisez les doigts&#8230; <img src='http://www.coolcoyote.net/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>N&#8217;hésitez pas à me faire part de vos expériences sur le sujet, mes connaissances sur le sujet étant modestes, il se peut qu&#8217;il y ait des erreurs ou des choses à améliorer.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.coolcoyote.net/linux-debian/changer-le-noyau-dune-debian-ovh/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
