<?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"
	>

<channel>
	<title>Olivier El Mekki</title>
	<atom:link href="http://blog.olivier-elmekki.com/2009/01/wp-rss2.php" rel="self" type="application/rss+xml" />
	<link>http://blog.olivier-elmekki.com</link>
	<description></description>
	<pubDate>Thu, 21 Jan 2010 21:39:54 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.6.5</generator>
	<language>en</language>
			<item>
		<title>Le développement top-down en uad</title>
		<link>http://blog.olivier-elmekki.com/2010/01/21/le-developpement-top-down-en-uad/</link>
		<comments>http://blog.olivier-elmekki.com/2010/01/21/le-developpement-top-down-en-uad/#comments</comments>
		<pubDate>Thu, 21 Jan 2010 21:39:04 +0000</pubDate>
		<dc:creator>kik</dc:creator>
		
		<category><![CDATA[Ruby on Rails]]></category>

		<guid isPermaLink="false">http://blog.olivier-elmekki.com/?p=424</guid>
		<description><![CDATA[Cet article fait suite à la conversation que j&#8217;ai eue avec Patrick Fratczak sur la manière de faire du TDD.
Voici donc la méthode que j&#8217;emploi pour faire du user acceptance testing. L&#8217;exemple décrit ici utilise rails, cucumber et rspec, mais cela fonctionne également bien avant Typolight, cucumber et phpspec.
Soit, je développe un site pour un [...]]]></description>
			<content:encoded><![CDATA[<p>Cet article fait suite à <a href="http://blog.olivier-elmekki.com/2008/10/17/maitriser-les-tests-unitaires-dans-ruby-on-rails/#comments">la conversation que j&#8217;ai eue avec Patrick Fratczak sur la manière de faire du TDD</a>.</p>
<p>Voici donc la méthode que j&#8217;emploi pour faire du user acceptance testing. L&#8217;exemple décrit ici utilise rails, cucumber et rspec, mais cela fonctionne également bien avant Typolight, cucumber et phpspec.</p>
<p>Soit, je développe un site pour un client qui vend des peintures. Une des fonctionnalité est le catalogue de peinture. Pour compliquer un peu cet exemple (et le rendre donc plus proche de la réalité), disons que ce client veut que lorsqu&#8217;on visionne la page d&#8217;une peinture, on voit le nombre d&#8217;autres visiteurs qui la visionne en même temps. Je lui dis d&#8217;abord que cette fonctionnalité n&#8217;est pas rentable, si on prend en compte son temps/coût de développement et son retour sur investissement. Mon client m&#8217;assure que c&#8217;est rentable, grâce au principe « le monde attire le monde » : si un visiteur remarque que d&#8217;autres personnes regarde la peinture en même temps que lui, il aura plus envie de l&#8217;acheter.</p>
<p>Dans la user story du catalogue, on donc trouve le scénario suivant :</p>
<pre>
Scénario: Voir le détail d'une peinture
  Lorsque je vais sur la page de la liste des peinture
  Et que je suis le lien de la première peinture
  Alors je dois voir sa photo
  Et je dois voir son titre
  Et je dois voir son auteur
  Et je dois voir son prix
  Et je dois voir le nombre de personnes qui visualisent ce produit actuellement
</pre>
<p>Une fois que le client a validé ce scénario, j&#8217;écris les steps cucumber suivantes :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">Then</span> <span style="color:#006600; font-weight:bold;">/</span>je dois voir sa photo<span style="color:#006600; font-weight:bold;">/</span> <span style="color:#9966CC; font-weight:bold;">do</span>
  response.<span style="color:#9900CC;">should</span> have_selector<span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#996600;">'#paint .picture img[src*=&quot;paint-1-full.jpg&quot;]'</span> <span style="color:#006600; font-weight:bold;">&#41;</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">Then</span> <span style="color:#006600; font-weight:bold;">/</span>je dois voir son titre<span style="color:#006600; font-weight:bold;">/</span> <span style="color:#9966CC; font-weight:bold;">do</span>
  response.<span style="color:#9900CC;">should</span> have_selector<span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#996600;">'#paint h1.title:contains(&quot;Paint 1 test&quot;)'</span> <span style="color:#006600; font-weight:bold;">&#41;</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">Then</span> <span style="color:#006600; font-weight:bold;">/</span>je dois voir son auteur<span style="color:#006600; font-weight:bold;">/</span> <span style="color:#9966CC; font-weight:bold;">do</span>
  response.<span style="color:#9900CC;">should</span> have_selector<span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#996600;">'#paint .author:contains(&quot;Paint 1 author&quot;)'</span> <span style="color:#006600; font-weight:bold;">&#41;</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">Then</span> <span style="color:#006600; font-weight:bold;">/</span>je dois voir son prix<span style="color:#006600; font-weight:bold;">/</span> <span style="color:#9966CC; font-weight:bold;">do</span>
  response.<span style="color:#9900CC;">should</span> have_selector<span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#996600;">'#paint .price:contains(&quot;10€&quot;)'</span> <span style="color:#006600; font-weight:bold;">&#41;</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">Then</span> <span style="color:#006600; font-weight:bold;">/</span>je dois voir le nombre de personnes qui visualisent ce produit actuellement<span style="color:#006600; font-weight:bold;">/</span> <span style="color:#9966CC; font-weight:bold;">do</span>
  response.<span style="color:#9900CC;">should</span> have_selector<span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#996600;">'#paint .viewer-count:contains(&quot;5&quot;)'</span> <span style="color:#006600; font-weight:bold;">&#41;</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Cucumber, couplé à webrat, a cet avantage de permettre de faire des tests précis des vues à base de sélecteur CSS3. De nombreuses autres méthodes sont permises, et notament toute une gamme de méthodes qui executent une action tout en la testant, par exemple .click_link( link ) fait une assertion sur l&#8217;existence de ce lien, puis le suit effectivement. Pour ma part, j&#8217;aime bien être le plus précis possible dans les sélecteurs dans mes steps afin de me permettre de composer d&#8217;un trait mes vues ensuite.</p>
<p>Ayant ces steps, je peux maintenant écrire ma vue :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby ruby" style="font-family:monospace;">&lt;div id=&quot;paint&quot;&gt;
  &lt;h1 class=&quot;title&quot;&gt;&lt; %= @paint.title -%&gt;&lt;/h1&gt;
&nbsp;
  &lt;div class=&quot;picture&quot;&gt;
    &lt;img src=&quot;<span style="color:#006600; font-weight:bold;">&lt;%</span>= <span style="color:#0066ff; font-weight:bold;">@paint</span>.<span style="color:#9900CC;">imageSRC</span> <span style="color:#006600; font-weight:bold;">-%/&gt;</span><span style="color:#996600;">&quot; alt=&quot;</span>Photo de <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#006600; font-weight:bold;">%</span>= <span style="color:#0066ff; font-weight:bold;">@paint</span>.<span style="color:#9900CC;">title</span> <span style="color:#006600; font-weight:bold;">-%&gt;</span>&quot; /&gt;
  &lt;/div&gt;&lt;!-- .picture --&gt;
&nbsp;
  &lt;div class=&quot;author&quot;&gt;
    &lt; %= @paint.author -%&gt;
  &lt;/div&gt;&lt;!-- .author --&gt;
&nbsp;
  &lt;div class=&quot;price&quot;&gt;
    &lt; %= &quot;%.2f&quot; % @paint.price -%&gt;€
  &lt;/div&gt;&lt;!-- .price --&gt;
&nbsp;
  &lt;div class=&quot;viewer-count&quot;&gt;
    &lt; %= @viewer_count -%&gt;
  &lt;/div&gt;&lt;!-- .viewer-count --&gt;
&lt;/div&gt;&lt;!-- #paint --&gt;</pre></div></div>

<p>Je sais maintenant que mon controller doit assigner @paint et @viewer_count. J&#8217;ai également déjà de bon indices sur ce dont je vais avoir besoin dans mes modèles et ma base de donnée. Je peux maintenant écrire les test de mon controller. Qu&#8217;est-ce que ce controller doit faire? Il doit assigner un modèle Paint et calculer le nombre de personnes qui voient actuellement cet article. Réflichissant à cette deuxième fonctionnalité, je me dis que cela doit être une méthode de classe de Visitor, qui vérifiera les journaux de visite pour une page donnée. Je n&#8217;ai pas besoin d&#8217;en savoir plus pour l&#8217;instant.</p>

<div class="wp_syntax"><div class="code"><pre class="ruby ruby" style="font-family:monospace;"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'spec_helper'</span>
&nbsp;
describe PaintsController <span style="color:#9966CC; font-weight:bold;">do</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> mock_paint<span style="color:#006600; font-weight:bold;">&#40;</span>stubs=<span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#006600; font-weight:bold;">&#125;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#0066ff; font-weight:bold;">@mock_paint</span> ||= mock_model<span style="color:#006600; font-weight:bold;">&#40;</span>Paint, stubs<span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  describe <span style="color:#996600;">&quot;GET show&quot;</span> <span style="color:#9966CC; font-weight:bold;">do</span>
    it <span style="color:#996600;">&quot;assigns the requested paint as @paint and the current viewers count as @viewer_count&quot;</span> <span style="color:#9966CC; font-weight:bold;">do</span>
      Paint.<span style="color:#9900CC;">stub</span>!<span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#ff3333; font-weight:bold;">:find</span> <span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">with</span><span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#996600;">&quot;1&quot;</span> <span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">and_return</span><span style="color:#006600; font-weight:bold;">&#40;</span> mock_paint<span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#ff3333; font-weight:bold;">:title</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'Paint 1 test'</span>, <span style="color:#ff3333; font-weight:bold;">:imageSRC</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'paint-1-full.jpg'</span>, <span style="color:#ff3333; font-weight:bold;">:author</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'Paint 1 author'</span>, <span style="color:#ff3333; font-weight:bold;">:price</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'10.0'</span> <span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#41;</span>
      Visitor.<span style="color:#9900CC;">stub</span>!<span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#ff3333; font-weight:bold;">:viewer_count</span> <span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">with</span><span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#996600;">'/paints/show/1'</span> <span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">and_return</span><span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#006666;">5</span> <span style="color:#006600; font-weight:bold;">&#41;</span>
      get <span style="color:#ff3333; font-weight:bold;">:show</span>, <span style="color:#ff3333; font-weight:bold;">:id</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;1&quot;</span>
      assigns<span style="color:#006600; font-weight:bold;">&#91;</span> <span style="color:#ff3333; font-weight:bold;">:paint</span> <span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">should</span> equal<span style="color:#006600; font-weight:bold;">&#40;</span> mock_paint <span style="color:#006600; font-weight:bold;">&#41;</span>
      assigns<span style="color:#006600; font-weight:bold;">&#91;</span> <span style="color:#ff3333; font-weight:bold;">:viewer_count</span> <span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">should</span> equal<span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#006666;">5</span> <span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Je peux maintenant écrire mon controller.</p>

<div class="wp_syntax"><div class="code"><pre class="ruby ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> PaintsController <span style="color:#006600; font-weight:bold;">&lt;</span> ApplicationController
  <span style="color:#9966CC; font-weight:bold;">def</span> show
    <span style="color:#0066ff; font-weight:bold;">@paint</span>        = Paint.<span style="color:#9900CC;">find</span><span style="color:#006600; font-weight:bold;">&#40;</span> params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:id</span><span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#0066ff; font-weight:bold;">@viewer_count</span> = Visitor.<span style="color:#9900CC;">viewer_count</span><span style="color:#006600; font-weight:bold;">&#40;</span> request.<span style="color:#9900CC;">request_uri</span> <span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
    respond_to <span style="color:#9966CC; font-weight:bold;">do</span> |format|
      <span style="color:#CC0066; font-weight:bold;">format</span>.<span style="color:#9900CC;">html</span> <span style="color:#008000; font-style:italic;"># show.html.erb</span>
      <span style="color:#CC0066; font-weight:bold;">format</span>.<span style="color:#9900CC;">xml</span>  <span style="color:#006600; font-weight:bold;">&#123;</span> render <span style="color:#ff3333; font-weight:bold;">:xml</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0066ff; font-weight:bold;">@paint</span> <span style="color:#006600; font-weight:bold;">&#125;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Désormais, je sais que j&#8217;ai besoin de deux modèles : Paint et Visitor. Je sais également à quoi ils doivent répondre : :title, :imageSRC, :author et :price pour les instances de Paint, :viewer_count pour la classe Visitor. Qu&#8217;est-ce qui sera attribut et qu&#8217;est-ce qui sera méthode dans tout cela? Je réalise maintenant que tous ce à quoi doit répondre une instance de paint est un attribut simple. Il s&#8217;agira donc d&#8217;un modèle simple avec title, imageSRC, author et price en tant que champs de la table `paints`.</p>
<p>À ce stade, je peux utiliser le generateur rspec_model pour créer ce modèle simple et ses tests :<br />
./script/generate rspec_model Paint title:string imageSRC:string author:string price:float</p>
<p>Visitor est un modèle moins simple. Que sais-je sur lui? D&#8217;abord, il doit répondre à la méthode :viewer_count. J&#8217;écris donc tout de suite ce test.</p>

<div class="wp_syntax"><div class="code"><pre class="ruby ruby" style="font-family:monospace;"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'spec_helper'</span>
&nbsp;
describe Visitor <span style="color:#9966CC; font-weight:bold;">do</span>
  it <span style="color:#996600;">&quot;should give the viewer count&quot;</span> <span style="color:#9966CC; font-weight:bold;">do</span>
    Visitor.<span style="color:#9900CC;">viewer_count</span><span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#996600;">'/paints/show/1'</span> <span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">should</span> equal<span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#006666;">5</span> <span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Je m&#8217;interroge maintenant sur comment retrouver ce nombre. Les visites doivent être loggée dans une table. Un visiteur est considéré comment visitant une page s&#8217;il l&#8217;a visité dans les 5 précédentes minutes. J&#8217;identifie un visiteur par son IP. Je dois effacer les anciennes visites pour ne pas surcharger ma db. Ok, j&#8217;ai ce qu&#8217;il faut pour écrire mes specs.</p>
<p>D&#8217;abord, je sais que chaque visite doit être loggé. Cela passera donc par un before_filter dans application_controller.rb . Je modifie donc mon fichier de test de mon controller ainsi :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby ruby" style="font-family:monospace;"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'spec_helper'</span>
&nbsp;
describe PaintsController <span style="color:#9966CC; font-weight:bold;">do</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> mock_paint<span style="color:#006600; font-weight:bold;">&#40;</span>stubs=<span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#006600; font-weight:bold;">&#125;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#0066ff; font-weight:bold;">@mock_paint</span> ||= mock_model<span style="color:#006600; font-weight:bold;">&#40;</span>Paint, stubs<span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  before<span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#ff3333; font-weight:bold;">:each</span> <span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">do</span>
    Visitor.<span style="color:#9900CC;">stub</span>!<span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#ff3333; font-weight:bold;">:log</span> <span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  describe <span style="color:#996600;">&quot;GET show&quot;</span> <span style="color:#9966CC; font-weight:bold;">do</span>
    it <span style="color:#996600;">&quot;assigns the requested paint as @paint and the current viewers count as @viewer_count&quot;</span> <span style="color:#9966CC; font-weight:bold;">do</span>
      Paint.<span style="color:#9900CC;">stub</span>!<span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#ff3333; font-weight:bold;">:find</span> <span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">with</span><span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#996600;">&quot;1&quot;</span> <span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">and_return</span><span style="color:#006600; font-weight:bold;">&#40;</span> mock_paint<span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#ff3333; font-weight:bold;">:title</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'Paint 1 test'</span>, <span style="color:#ff3333; font-weight:bold;">:imageSRC</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'paint-1-full.jpg'</span>, <span style="color:#ff3333; font-weight:bold;">:author</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'Paint 1 author'</span>, <span style="color:#ff3333; font-weight:bold;">:price</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'10.0'</span> <span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#41;</span>
      Visitor.<span style="color:#9900CC;">stub</span>!<span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#ff3333; font-weight:bold;">:viewer_count</span> <span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">with</span><span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#996600;">'paints/show/1'</span> <span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">and_return</span><span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#006666;">5</span> <span style="color:#006600; font-weight:bold;">&#41;</span>
      get <span style="color:#ff3333; font-weight:bold;">:show</span>, <span style="color:#ff3333; font-weight:bold;">:id</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;1&quot;</span>
      assigns<span style="color:#006600; font-weight:bold;">&#91;</span> <span style="color:#ff3333; font-weight:bold;">:paint</span> <span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">should</span> equal<span style="color:#006600; font-weight:bold;">&#40;</span> mock_paint <span style="color:#006600; font-weight:bold;">&#41;</span>
      assigns<span style="color:#006600; font-weight:bold;">&#91;</span> <span style="color:#ff3333; font-weight:bold;">:viewer_count</span> <span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">should</span> equal<span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#006666;">5</span> <span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Je peux maintenant écrire le before_filter :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> ApplicationController <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">ActionController::Base</span>
  before_filter <span style="color:#ff3333; font-weight:bold;">:log_visit</span>
  helper <span style="color:#ff3333; font-weight:bold;">:all</span> <span style="color:#008000; font-style:italic;"># include all helpers, all the time</span>
  protect_from_forgery <span style="color:#008000; font-style:italic;"># See ActionController::RequestForgeryProtection for details</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> log_visit
    Visitor.<span style="color:#9900CC;">log</span><span style="color:#006600; font-weight:bold;">&#40;</span> request.<span style="color:#9900CC;">request_uri</span>, request.<span style="color:#9900CC;">ip</span>, <span style="color:#CC00FF; font-weight:bold;">Time</span>.<span style="color:#9900CC;">now</span> <span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Cela m&#8217;en dit plus sur mon modèle Visitor. Il possède une méthode de classe :log. Celle ci enregistrera l&#8217;ip, la page et la date. Cette méthode devra également être responsable du vidage de la table. Cela fait une requête de plus à chaque visite, mais ça maintiendra la table presque vide.  Je peux donc écrire son test :</p>
</pre>

<div class="wp_syntax"><div class="code"><pre class="ruby ruby" style="font-family:monospace;"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'spec_helper'</span>
&nbsp;
describe Visitor <span style="color:#9966CC; font-weight:bold;">do</span>
  it <span style="color:#996600;">&quot;should give the viewer count&quot;</span> <span style="color:#9966CC; font-weight:bold;">do</span>
    Visitor.<span style="color:#9900CC;">viewer_count</span>.<span style="color:#9900CC;">should</span> equal<span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#006666;">5</span> <span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  it <span style="color:#996600;">&quot;should log visits&quot;</span> <span style="color:#9966CC; font-weight:bold;">do</span>
    Visitor.<span style="color:#9900CC;">should_receive</span><span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#ff3333; font-weight:bold;">:delete_all</span> <span style="color:#006600; font-weight:bold;">&#41;</span>
    ip, page, date = <span style="color:#996600;">'127.0.0.1'</span>, <span style="color:#996600;">'/show/paint/1'</span>, <span style="color:#CC00FF; font-weight:bold;">Time</span>.<span style="color:#9900CC;">now</span>
    Visitor.<span style="color:#9900CC;">should_receive</span><span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#ff3333; font-weight:bold;">:create</span> <span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">with</span><span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#ff3333; font-weight:bold;">:page</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> page, <span style="color:#ff3333; font-weight:bold;">:ip</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> ip, <span style="color:#ff3333; font-weight:bold;">:date</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> time <span style="color:#006600; font-weight:bold;">&#41;</span>
    Visitor.<span style="color:#9900CC;">log</span><span style="color:#006600; font-weight:bold;">&#40;</span> page, id, date <span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Je sais maintenant que mon modèle ma table visitors possède les champs :page, :ip et :date. Je peux générer le modèle.<br />
./script/generate model Visitor page:string ip:string date:datetime</p>
<p>Et je peux implémenter ma méthode :log</p>

<div class="wp_syntax"><div class="code"><pre class="ruby ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> Visitor <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>
  attr_accessible         <span style="color:#ff3333; font-weight:bold;">:page</span>, <span style="color:#ff3333; font-weight:bold;">:ip</span>, <span style="color:#ff3333; font-weight:bold;">:date</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">log</span><span style="color:#006600; font-weight:bold;">&#40;</span> page, ip, date <span style="color:#006600; font-weight:bold;">&#41;</span>
    Visitor.<span style="color:#9900CC;">delete_all</span><span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#006600; font-weight:bold;">&#91;</span> <span style="color:#996600;">&quot;date &lt; ?&quot;</span>, 5.<span style="color:#9900CC;">minutes</span>.<span style="color:#9900CC;">ago</span>.<span style="color:#9900CC;">to_s</span><span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#ff3333; font-weight:bold;">:db</span> <span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#006600; font-weight:bold;">&#41;</span>
    Visitor.<span style="color:#9900CC;">create</span><span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#ff3333; font-weight:bold;">:page</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> page, <span style="color:#ff3333; font-weight:bold;">:ip</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> ip, <span style="color:#ff3333; font-weight:bold;">:date</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> date <span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Je sais également comment retrouver le nombre de visiteurs d&#8217;une page. Je complète donc son test :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby ruby" style="font-family:monospace;"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'spec_helper'</span>
&nbsp;
describe Visitor <span style="color:#9966CC; font-weight:bold;">do</span>
  it <span style="color:#996600;">&quot;should give the viewer count&quot;</span> <span style="color:#9966CC; font-weight:bold;">do</span>
    page = <span style="color:#996600;">'/paints/show/1'</span>
    Visitor.<span style="color:#9900CC;">should_receive</span><span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#ff3333; font-weight:bold;">:all</span> <span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">with</span><span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#ff3333; font-weight:bold;">:conditions</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span> <span style="color:#996600;">&quot;page = ?&quot;</span>, page <span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">and_return</span><span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#006600; font-weight:bold;">&#91;</span> <span style="color:#006666;">1</span>, <span style="color:#006666;">2</span>, <span style="color:#006666;">3</span>, <span style="color:#006666;">4</span>, <span style="color:#006666;">5</span> <span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#006600; font-weight:bold;">&#41;</span>
    Visitor.<span style="color:#9900CC;">viewer_count</span><span style="color:#006600; font-weight:bold;">&#40;</span> page <span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">should</span> equal<span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#006666;">5</span> <span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  it <span style="color:#996600;">&quot;should log visits&quot;</span> <span style="color:#9966CC; font-weight:bold;">do</span>
    Visitor.<span style="color:#9900CC;">should_receive</span><span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#ff3333; font-weight:bold;">:delete_all</span> <span style="color:#006600; font-weight:bold;">&#41;</span>
    ip, page, date = <span style="color:#996600;">'127.0.0.1'</span>, <span style="color:#996600;">'/show/paint/1'</span>, <span style="color:#CC00FF; font-weight:bold;">Time</span>.<span style="color:#9900CC;">now</span>
    Visitor.<span style="color:#9900CC;">should_receive</span><span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#ff3333; font-weight:bold;">:create</span> <span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">with</span><span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#ff3333; font-weight:bold;">:page</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> page, <span style="color:#ff3333; font-weight:bold;">:ip</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> ip, <span style="color:#ff3333; font-weight:bold;">:date</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> time <span style="color:#006600; font-weight:bold;">&#41;</span>
    Visitor.<span style="color:#9900CC;">log</span><span style="color:#006600; font-weight:bold;">&#40;</span> page, id, date <span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Et j&#8217;écris la méthode :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> Visitor <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>
  attr_accessible         <span style="color:#ff3333; font-weight:bold;">:page</span>, <span style="color:#ff3333; font-weight:bold;">:ip</span>, <span style="color:#ff3333; font-weight:bold;">:date</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">log</span><span style="color:#006600; font-weight:bold;">&#40;</span> page, ip, date <span style="color:#006600; font-weight:bold;">&#41;</span>
    Visitor.<span style="color:#9900CC;">delete_all</span><span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#006600; font-weight:bold;">&#91;</span> <span style="color:#996600;">&quot;date &lt; ?&quot;</span>, 5.<span style="color:#9900CC;">minutes</span>.<span style="color:#9900CC;">ago</span>.<span style="color:#9900CC;">to_s</span><span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#ff3333; font-weight:bold;">:db</span> <span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#006600; font-weight:bold;">&#41;</span>
    Visitor.<span style="color:#9900CC;">create</span><span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#ff3333; font-weight:bold;">:page</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> page, <span style="color:#ff3333; font-weight:bold;">:ip</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> ip, <span style="color:#ff3333; font-weight:bold;">:date</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> date <span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">viewer_count</span><span style="color:#006600; font-weight:bold;">&#40;</span> page <span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#0000FF; font-weight:bold;">return</span> Visitor.<span style="color:#9900CC;">all</span><span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#ff3333; font-weight:bold;">:conditions</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span> <span style="color:#996600;">&quot;page = ?&quot;</span>, page <span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">length</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>À ce point, j&#8217;ai terminé l&#8217;implémentation de mon scénario. Il ne me reste plus qu&#8217;à le tester. Les specs doivent déjà passer, Pour faire passer les tests de cucumber, je dois d&#8217;abord écrire ma route et inclure mes fixtures (nombreux sont ceux qui détestent les fixtures, aujourd&#8217;hui, je les trouve personnellement plus simple d&#8217;utilisation dans le cadre de cucumber).</p>
<p>L&#8217;immense avantage de cette méthode est de rendre tout évident. C&#8217;est un no-brainer total et il n&#8217;y a qu&#8217;à développer, au sens strict. Plutôt que de construire un outil en tentant d&#8217;imaginer ses usages, puis d&#8217;adapter les usages en fonction de l&#8217;outil créé ( schéma du type : on va des modèles aux vues ), je défini d&#8217;abord l&#8217;usage en disant ce que mes outils doivent faire, et je les construis en conséquence ( schéma du type : vues vers modèles ).</p>
<p>L&#8217;immense inconvénient est que les tests ne sont pas exécutables avant l&#8217;arrivée aux modèles. Il est donc important de procéder à très petite itérations. Celle que je viens de prendre pour exemple est déjà presque trop longue (en fait, il est assez probable qu&#8217;en situation réelle, j&#8217;aurai d&#8217;abord fait le :show classique, puis j&#8217;aurais rajouté le :view_count).</p>
 <img src="http://blog.olivier-elmekki.com/wp-content/plugins/feed-statistics.php?view=1&post_id=424" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://blog.olivier-elmekki.com/2010/01/21/le-developpement-top-down-en-uad/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Getters et setters en PHP</title>
		<link>http://blog.olivier-elmekki.com/2009/11/13/getters-et-setters-en-php/</link>
		<comments>http://blog.olivier-elmekki.com/2009/11/13/getters-et-setters-en-php/#comments</comments>
		<pubDate>Fri, 13 Nov 2009 16:16:50 +0000</pubDate>
		<dc:creator>kik</dc:creator>
		
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://blog.olivier-elmekki.com/?p=417</guid>
		<description><![CDATA[Venant du monde de ruby, j&#8217;ai pris l&#8217;habitude de ne pas faire de distinction dans l&#8217;utilisation d&#8217;un objet entre une méthode et un attribut. En ruby, un attribut se récupère exactement de la même manière qu&#8217;une méthode s&#8217;appelle.

Prenons le script suivant :

class Person
  attr_accessor :food
&#160;
  def initialize
    @food = 10
 [...]]]></description>
			<content:encoded><![CDATA[<p>Venant du monde de ruby, j&#8217;ai pris l&#8217;habitude de ne pas faire de distinction dans l&#8217;utilisation d&#8217;un objet entre une méthode et un attribut. En ruby, un attribut se récupère exactement de la même manière qu&#8217;une méthode s&#8217;appelle.<br />
<span id="more-417"></span></p>
<p>Prenons le script suivant :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> Person
  attr_accessor <span style="color:#ff3333; font-weight:bold;">:food</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> initialize
    <span style="color:#0066ff; font-weight:bold;">@food</span> = <span style="color:#006666;">10</span>
    <span style="color:#0066ff; font-weight:bold;">@firstname</span> = <span style="color:#996600;">'John'</span>
    <span style="color:#0066ff; font-weight:bold;">@lastname</span>  = <span style="color:#996600;">'Doe'</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> eat
    <span style="color:#0066ff; font-weight:bold;">@food</span> <span style="color:#006600; font-weight:bold;">-</span>= <span style="color:#006666;">1</span>
    <span style="color:#0000FF; font-weight:bold;">true</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> name
    <span style="color:#0066ff; font-weight:bold;">@firstname</span> <span style="color:#006600; font-weight:bold;">+</span> <span style="color:#996600;">' '</span> <span style="color:#006600; font-weight:bold;">+</span> <span style="color:#0066ff; font-weight:bold;">@lastname</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> name=<span style="color:#006600; font-weight:bold;">&#40;</span> fullname <span style="color:#006600; font-weight:bold;">&#41;</span>
    parts      = fullname.<span style="color:#CC0066; font-weight:bold;">split</span><span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#996600;">' '</span>, <span style="color:#006666;">2</span> <span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#0066ff; font-weight:bold;">@firstname</span> = parts<span style="color:#006600; font-weight:bold;">&#91;</span>0<span style="color:#006600; font-weight:bold;">&#93;</span>
    <span style="color:#0066ff; font-weight:bold;">@lastname</span>  = parts<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">1</span><span style="color:#006600; font-weight:bold;">&#93;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
michel = Person.<span style="color:#9900CC;">new</span>
michel.<span style="color:#9900CC;">name</span> = <span style="color:#996600;">'Michel Dupont'</span>
michel.<span style="color:#9900CC;">food</span>                     <span style="color:#008000; font-style:italic;"># =&gt; 10</span>
michel.<span style="color:#9900CC;">eat</span>                      <span style="color:#008000; font-style:italic;"># =&gt; true</span>
michel.<span style="color:#9900CC;">name</span>                     <span style="color:#008000; font-style:italic;"># =&gt; 'Michel Dupont'</span></pre></div></div>

<p>Nous voyons ici qu&#8217;il n&#8217;est pas possible de distinguer, formellement, la méthode &#8220;eat&#8221; et la méthode &#8220;name&#8221; de l&#8217;attribut &#8220;food&#8221;.  Que nous importe, finalement, leur implémentation? Lorsque j&#8217;utilise l&#8217;interface d&#8217;un objet, je veux soit exécuter une action, soit manipuler une valeur. Dans le cas où je souhaite retrouver une valeur, peu m&#8217;importe de savoir si cette valeur se trouve directement dans un attribut ou si une méthode est appelée pour me le retourner : cela relève de l&#8217;implémentation et non de l&#8217;usage. Au niveau de l&#8217;usage, ici, je sais que &#8220;food&#8221; et &#8220;name&#8221; me retourneront des valeurs, parce que ce sont des noms, et je sais que &#8220;eat&#8221; exécutera une action, parce que c&#8217;est un verbe.</p>
<p>Qu&#8217;en est-il en PHP? Le même script s&#8217;écrirait :</p>

<div class="wp_syntax"><div class="code"><pre class="php php" style="font-family:monospace;"><span style="color: #339933;">&lt;</span> ?php
<span style="color: #000000; font-weight: bold;">class</span> Person 
<span style="color: #009900;">&#123;</span>
  <span style="color: #000000; font-weight: bold;">public</span>    <span style="color: #000088;">$food</span>;
  protected <span style="color: #000088;">$firstname</span>;
  protected <span style="color: #000088;">$lastname</span>;
&nbsp;
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> __construct<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">food</span>       <span style="color: #339933;">=</span> <span style="color: #cc66cc;">10</span>;
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">firstname</span>  <span style="color: #339933;">=</span> <span style="">'John'</span>;
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">lastname</span>   <span style="color: #339933;">=</span> <span style="">'Doe'</span>;
  <span style="color: #009900;">&#125;</span>
&nbsp;
&nbsp;
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> eat<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">food</span> <span style="color: #339933;">-=</span> <span style="color: #cc66cc;">1</span>;
    <span style="color: #b1b100;">return</span> <span style="color: #000000; font-weight: bold;">true</span>;
  <span style="color: #009900;">&#125;</span>
&nbsp;
&nbsp;
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getName<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">firstname</span> <span style="color: #339933;">.</span> <span style="">' '</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">lastname</span>;
  <span style="color: #009900;">&#125;</span>
&nbsp;
&nbsp;
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> setName<span style="color: #009900;">&#40;</span> <span style="color: #000088;">$fullname</span> <span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$parts</span> <span style="color: #339933;">=</span> <span style="color: #990000;">preg_split</span><span style="color: #009900;">&#40;</span> <span style="">'/ /'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$fullname</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">2</span> <span style="color: #009900;">&#41;</span>;
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">firstname</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$parts</span><span style="color: #009900;">&#91;</span><span style="color:#800080;">0</span><span style="color: #009900;">&#93;</span>;
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">lastname</span>  <span style="color: #339933;">=</span> <span style="color: #000088;">$parts</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span>;
    <span style="color: #b1b100;">return</span> <span style="color: #000088;">$fullname</span>;
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #000088;">$michel</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Person<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;
<span style="color: #000088;">$michel</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setName</span><span style="color: #009900;">&#40;</span> <span style="">'Michel Dupont'</span> <span style="color: #009900;">&#41;</span>;   
<span style="color: #000088;">$michel</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">food</span>;                         <span style="color: #666666; font-style: italic;">// =&gt; 10</span>
<span style="color: #000088;">$michel</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">eat</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;                        <span style="color: #666666; font-style: italic;">// =&gt; true</span>
<span style="color: #000088;">$michel</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getName</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;                    <span style="color: #666666; font-style: italic;">// =&gt; 'Michel Dupont'</span></pre></div></div>

<p>Nous voyons ici que l&#8217;implémentation est clairement visible. &#8220;food&#8221; est un attribut, &#8220;eat&#8221;, &#8220;setName&#8221; et &#8220;getName&#8221; sont des méthodes. L&#8217;astuce, chez PHP, est de transformer un nom en verbe par l&#8217;emploi des setters et des getters ( setName() et getName() ) pour justifier l&#8217;appel d&#8217;une méthode. Néanmoins, rien ne justifie le fait que je doive exécuter une action sur une Person pour avoir son nom. Il s&#8217;agit d&#8217;une valeur et cela ne me regarde pas, à l&#8217;usage, de savoir comment ce nom a été retrouvé.</p>
<h3>Suggestion d&#8217;une implémentation</h3>
<p>Dans l&#8217;extension framework que j&#8217;ai faite pour Typolight, j&#8217;ai généralisé l&#8217;emploi d&#8217;un design différent pour répondre à ce problème. En voici un exemple :</p>

<div class="wp_syntax"><div class="code"><pre class="php php" style="font-family:monospace;"><span style="color: #339933;">&lt;</span> ?php
<span style="color: #000000; font-weight: bold;">class</span> Person 
<span style="color: #009900;">&#123;</span>
  <span style="color: #000000; font-weight: bold;">public</span>    <span style="color: #000088;">$food</span>;
  protected <span style="color: #000088;">$firstname</span>;
  protected <span style="color: #000088;">$lastname</span>;
  protected <span style="color: #000088;">$_cache</span>      <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;
  protected <span style="color: #000088;">$_uncachable</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;
&nbsp;
&nbsp;
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> __construct<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">food</span>       <span style="color: #339933;">=</span> <span style="color: #cc66cc;">10</span>;
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">firstname</span>  <span style="color: #339933;">=</span> <span style="">'John'</span>;
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">lastname</span>   <span style="color: #339933;">=</span> <span style="">'Doe'</span>;
  <span style="color: #009900;">&#125;</span>
&nbsp;
&nbsp;
&nbsp;
  <span style="color: #0000ff; font-style: italic;">/**
   * Check if a getter method exists
   *
   * @param string  the attribute name
   * @return mixed
   */</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> __get<span style="color: #009900;">&#40;</span> <span style="color: #000088;">$key</span> <span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$firstLetter</span> <span style="color: #339933;">=</span> <span style="color: #990000;">substr</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$key</span><span style="color: #339933;">,</span> <span style="color:#800080;">0</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">1</span> <span style="color: #009900;">&#41;</span>;
    <span style="color: #000088;">$rest</span>        <span style="color: #339933;">=</span> <span style="color: #990000;">substr</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$key</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">1</span> <span style="color: #009900;">&#41;</span>;
    <span style="color: #000088;">$getter</span>      <span style="color: #339933;">=</span> <span style="">'get'</span> <span style="color: #339933;">.</span> <span style="color: #990000;">strtoupper</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$firstLetter</span> <span style="color: #009900;">&#41;</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$rest</span>;
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> <span style="color: #990000;">method_exists</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$this</span><span style="color: #339933;">,</span> <span style="color: #000088;">$getter</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
      <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> <span style="color: #990000;">array_key_exists</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$key</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_cache <span style="color: #009900;">&#41;</span> and <span style="color: #339933;">!</span> <span style="color: #990000;">in_array</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$key</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_uncachable <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span>
      <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_cache<span style="color: #009900;">&#91;</span> <span style="color: #000088;">$key</span> <span style="color: #009900;">&#93;</span>;
      <span style="color: #009900;">&#125;</span>
&nbsp;
      <span style="color: #000088;">$result</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #000088;">$getter</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;
      <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> <span style="color: #339933;">!</span> <span style="color: #990000;">in_array</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$key</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_uncachable <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span>
      <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_cache<span style="color: #009900;">&#91;</span> <span style="color: #000088;">$key</span> <span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$result</span>;
      <span style="color: #009900;">&#125;</span>
&nbsp;
      <span style="color: #b1b100;">return</span> <span style="color: #000088;">$result</span>;
    <span style="color: #009900;">&#125;</span>
&nbsp;
    throw <span style="color: #000000; font-weight: bold;">new</span> Exception<span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">&quot;Unknown attribute&quot;</span> <span style="color: #009900;">&#41;</span>;
  <span style="color: #009900;">&#125;</span>
&nbsp;
&nbsp;
&nbsp;
  <span style="color: #0000ff; font-style: italic;">/**
   * Check if a setter method exists
   *
   * @param string  the attribute name
   * @param string  the attribute value
   * @return mixed
   */</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> __set<span style="color: #009900;">&#40;</span> <span style="color: #000088;">$key</span><span style="color: #339933;">,</span> <span style="color: #000088;">$value</span> <span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$firstLetter</span>  <span style="color: #339933;">=</span> <span style="color: #990000;">substr</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$key</span><span style="color: #339933;">,</span> <span style="color:#800080;">0</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">1</span> <span style="color: #009900;">&#41;</span>;
    <span style="color: #000088;">$rest</span>         <span style="color: #339933;">=</span> <span style="color: #990000;">substr</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$key</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">1</span> <span style="color: #009900;">&#41;</span>;
    <span style="color: #000088;">$setter</span>       <span style="color: #339933;">=</span> <span style="">'set'</span> <span style="color: #339933;">.</span> <span style="color: #990000;">strtoupper</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$firstLetter</span> <span style="color: #009900;">&#41;</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$rest</span>;
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> <span style="color: #990000;">method_exists</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$this</span><span style="color: #339933;">,</span> <span style="color: #000088;">$setter</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
      <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_cache<span style="color: #009900;">&#91;</span> <span style="color: #000088;">$key</span> <span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #000088;">$setter</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$value</span> <span style="color: #009900;">&#41;</span>;
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #b1b100;">else</span>
    <span style="color: #009900;">&#123;</span>
      <span style="color: #000088;">$getter</span> <span style="color: #339933;">=</span> <span style="">'get'</span> <span style="color: #339933;">.</span> <span style="color: #990000;">strtoupper</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$firstLetter</span> <span style="color: #009900;">&#41;</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$rest</span>;
      <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> <span style="color: #990000;">method_exists</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$this</span><span style="color: #339933;">,</span> <span style="color: #000088;">$getter</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span>
      <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_cache<span style="color: #009900;">&#91;</span> <span style="color: #000088;">$key</span> <span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$value</span>;
        <span style="color: #b1b100;">return</span> <span style="color: #000000; font-weight: bold;">true</span>;
      <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    throw <span style="color: #000000; font-weight: bold;">new</span> Exception<span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">&quot;Unknown attribute&quot;</span> <span style="color: #009900;">&#41;</span>;
  <span style="color: #009900;">&#125;</span>
&nbsp;
&nbsp;
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> eat<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">food</span> <span style="color: #339933;">-=</span> <span style="color: #cc66cc;">1</span>;
    <span style="color: #b1b100;">return</span> <span style="color: #000000; font-weight: bold;">true</span>;
  <span style="color: #009900;">&#125;</span>
&nbsp;
&nbsp;
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getName<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">firstname</span> <span style="color: #339933;">.</span> <span style="">' '</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">lastname</span>;
  <span style="color: #009900;">&#125;</span>
&nbsp;
&nbsp;
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> setName<span style="color: #009900;">&#40;</span> <span style="color: #000088;">$fullname</span> <span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$parts</span> <span style="color: #339933;">=</span> <span style="color: #990000;">preg_split</span><span style="color: #009900;">&#40;</span> <span style="">'/ /'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$fullname</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">2</span> <span style="color: #009900;">&#41;</span>;
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">firstname</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$parts</span><span style="color: #009900;">&#91;</span><span style="color:#800080;">0</span><span style="color: #009900;">&#93;</span>;
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">lastname</span>  <span style="color: #339933;">=</span> <span style="color: #000088;">$parts</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span>;
    <span style="color: #b1b100;">return</span> <span style="color: #000000; font-weight: bold;">true</span>;
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
&nbsp;
<span style="color: #666666; font-style: italic;">// Nous pouvons maintenant faire ceci :</span>
<span style="color: #000088;">$michel</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Person<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;
<span style="color: #000088;">$michel</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">name</span> <span style="color: #339933;">=</span> <span style="">'Michel Dupont'</span>;  
<span style="color: #000088;">$michel</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">food</span>;                    <span style="color: #666666; font-style: italic;">// =&gt; 10</span>
<span style="color: #000088;">$michel</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">eat</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;                   <span style="color: #666666; font-style: italic;">// =&gt; true</span>
<span style="color: #000088;">$michel</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">name</span>;                    <span style="color: #666666; font-style: italic;">// =&gt; 'Michel Dupont'</span></pre></div></div>

<p>Ainsi, en utilisant les méthodes magiques __set() et __get(), nous pouvons rétablir le respect de la blackbox. Lorsque $michel->name est exécuté, __get() est appelé ( puisqu&#8217;il n&#8217;existe pas d&#8217;attribut $name ) et vérifie s&#8217;il existe une méthode getName().</p>
<p>En outre, cela permet d&#8217;ajouter un système de cache. La prochaine fois que j&#8217;appellerai $michel->name, la valeur précédente sera directement retournée plutôt que de devoir executer la méthode à nouveau. Si je veux éviter ce comportement, il me suffit d&#8217;appeler directement la méthode en faisant $michel->getName(), et le nom sera recalculé.</p>
<p>Bien entendu, mettre en place un tel mécanisme n&#8217;a pas de sens pour une petite classe isolée. J&#8217;ai employé personnellement ce mécanisme pour la couche modèle et la couche controller de mon extension. Cela est particulièrement intéressant pour les modèles, qui doivent se comporter de la manière la plus naturelle possible et qui font régulièrement des requêtes sur la base de donnée. Avec un tel mécanisme vous pouvez, dans le cadre d&#8217;un framework MVC, utiliser autant de fois que vous le voulez vos modèles dans vos vues de manière intuitive et sans vous soucier de savoir si cela va exécuter une requête sql ou non.</p>
 <img src="http://blog.olivier-elmekki.com/wp-content/plugins/feed-statistics.php?view=1&post_id=417" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://blog.olivier-elmekki.com/2009/11/13/getters-et-setters-en-php/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Typolight et les modèles : M comme dans VC</title>
		<link>http://blog.olivier-elmekki.com/2009/11/08/typolight-et-les-modeles-m-comme-dans-vc/</link>
		<comments>http://blog.olivier-elmekki.com/2009/11/08/typolight-et-les-modeles-m-comme-dans-vc/#comments</comments>
		<pubDate>Sun, 08 Nov 2009 00:41:32 +0000</pubDate>
		<dc:creator>kik</dc:creator>
		
		<category><![CDATA[Non classé]]></category>

		<category><![CDATA[typolight]]></category>

		<guid isPermaLink="false">http://blog.olivier-elmekki.com/?p=407</guid>
		<description><![CDATA[Si on me posait la question du problème majeur dans le core de Typolight, je répondrais : l&#8217;implémentation incomplète du pattern MVC. La couche modèle est difficilement utilisable telle-quelle et provoque l&#8217;abondance de requêtes SQL dans les contrôleurs. Il y a aussi le problème de la présence de HTML dans les contrôleurs, mais cela ne [...]]]></description>
			<content:encoded><![CDATA[<p>Si on me posait la question du problème majeur dans le core de Typolight, je répondrais : l&#8217;implémentation incomplète du pattern MVC. La couche modèle est difficilement utilisable telle-quelle et provoque l&#8217;abondance de requêtes SQL dans les contrôleurs. Il y a aussi le problème de la présence de HTML dans les contrôleurs, mais cela ne concernera pas ce tutoriel. Nous verrons cette fois comment rendre aux modèles ce qui appartient aux modèles.</p>
<p><span id="more-407"></span></p>
<h3>Le MVC, c&#8217;est quoi?</h3>
<p>Pour ceux qui ne sont pas familiers à la notion de <a href="http://fr.wikipedia.org/wiki/Modèle-Vue-Contrôleur">MVC</a>, récapitulons brièvement. MVC est un acronyme pour : Model, View, Controller ( en français, ça marche bien aussi ). Il s&#8217;agit d&#8217;un <a href="http://fr.wikipedia.org/wiki/Patron_de_conception">design pattern</a> qui structure une application selon trois tâches :</p>
<ul>
<li>Le traitement des données ( Modèles )</li>
<li>La présentation des données ( Vues )</li>
<li>La logique qui détermine quelles données associer à quelle présentation ( Contrôleurs )</li>
</ul>
<p>Typiquement, dans une application web, les modèles sont tous les calculs faits sur la base de donnée ; les vues sont les fichiers contenant le html ( ou autre, par exemple la structure d&#8217;un email ) ; les contrôleurs sont ce qui gèrent les requêtes ( POST, GET, etc ), leurs paramètres, et décident quels modèles utiliser et quelles variables fournir aux vues.</p>
<p>La couche modèle est en général gérée par un ORM ( <a href="http://fr.wikipedia.org/wiki/Mapping_objet-relationnel">Object Relational Mapping</a> ). Celui-ci permet de manipuler la base de donnée sans faire soi-même de pénibles requêtes SQL. Si par exemple j&#8217;ai dans ma base de donnée une table posts avec des champs id, name, content et author, j&#8217;aurai une classe Post, héritant de Model, qui me permettra de manipuler les entrées de la base de donnée comme des objets. Voici un exemple de PHP fictif qui illustre la manipulation d&#8217;un modèle :</p>

<div class="wp_syntax"><div class="code"><pre class="php php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">// récupérer l'entrée de la tables posts qui à l'id 10</span>
<span style="color: #000088;">$post</span> <span style="color: #339933;">=</span> Post<span style="color: #339933;">::</span><span style="color: #004000;">find</span><span style="color: #009900;">&#40;</span> <span style="color: #cc66cc;">10</span> <span style="color: #009900;">&#41;</span>;
&nbsp;
<span style="color: #666666; font-style: italic;">// retrouver son attribut &quot;name&quot;</span>
<span style="color: #990000;">echo</span> <span style="color: #000088;">$post</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">name</span>;
&nbsp;
<span style="color: #666666; font-style: italic;">// le modifier</span>
<span style="color: #000088;">$post</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">name</span> <span style="color: #339933;">=</span> <span style="">'an other name'</span>;
&nbsp;
<span style="color: #666666; font-style: italic;">// sauvegarder le changement dans la base de donnée</span>
<span style="color: #000088;">$post</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">save</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;
&nbsp;
<span style="color: #666666; font-style: italic;">// récupérer tous les posts dans un array</span>
<span style="color: #000088;">$posts</span> <span style="color: #339933;">=</span> Post<span style="color: #339933;">::</span><span style="color: #004000;">findAll</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;</pre></div></div>

<p>On peut ensuite utiliser ce array dans une vue, avec par exemple :</p>

<div class="wp_syntax"><div class="code"><pre class="php php" style="font-family:monospace;">&lt;ul id=&quot;posts&quot;&gt;
  &lt; ?php foreach ( $posts as $post ) : ?&gt;
  &lt;li&gt;&lt;a href=&quot;post-<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #990000;">echo</span> <span style="color: #000088;">$post</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">id</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&quot;&gt;&lt; ?php echo $post-&gt;name ?&gt;&lt;/a&gt;, by &lt; ?php echo $post-&gt;author ?&gt;&lt;/li&gt;
  &lt; ?php endforeach ?&gt;
&lt;/ul&gt;</pre></div></div>

<p>Dans Typolight, les vues sont les templates et les contrôleurs sont les FrontendModule et BackendModule. Il n&#8217;y a malheureusement pas d&#8217;équivalence pour la couche modèle, et les données sont généralement retrouvées en remplissant les contrôleurs de requêtes SQL, ce qui rend la base de donnée pénible à utiliser et encombre les contrôleurs.</p>
<h3>Comment utiliser une couche modèle dans Typolight?</h3>
<p>Heureusement, une couche modèle existe belle et bien. Le fichier est TL_ROOT/system/libraries/Model.php . Ce fichier dispose des méthodes de base d&#8217;une couche modèle, mais il semble avoir été sabordé en route. En effet, c&#8217;est un <a href="ihttp://fr.wikipedia.org/wiki/Singleton_%28patron_de_conception%29">singleton</a> ( ce qui signifie qu&#8217;un seul objet de cette classe peut exister en même temps ). Il a en fait été pensé pour ne servir qu&#8217;aux classes User, BackendUser et FrontendUser, permettant de gérer l&#8217;utilisateur actuellement loggé.</p>
<p>Il n&#8217;y a en fait qu&#8217;une simple chose à faire pour rendre une couche modèle utilisable dans Typolight : créer une classe qui descend de Model et rendre publique sa méthode __construct(). C&#8217;est par exemple la méthode choisie par les développeurs de Isotope, ou par ma propre extension framework.</p>
<p>Nous allons reprendre la base du <a href="http://www.typolight.fr/forums/viewtopic.php?id=422">précédent tutoriel</a>. Nous avions deux tables SQL : tl_filiere_services et tl_filiere_filiales. Nous allons donc faire deux classes de modèles : Service et Filiale.</p>

<div class="wp_syntax"><div class="code"><pre class="php php" style="font-family:monospace;"><span style="color: #339933;">&lt;</span> ?php <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #990000;">defined</span><span style="color: #009900;">&#40;</span><span style="">'TL_ROOT'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #990000;">die</span><span style="color: #009900;">&#40;</span><span style="">'You can not access this file directly!'</span><span style="color: #009900;">&#41;</span>;
&nbsp;
<span style="color: #0000ff; font-style: italic;">/**
 * TYPOlight webCMS
 * Copyright (C) 2005 Leo Feyer
 *
 * This program is free software: you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation, either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this program. If not, please visit the Free
 * Software Foundation website at http://www.gnu.org/licenses/.
 *
 * PHP version 5
 * @copyright  
 * @author    
 * @package    
 * @license    
 * @filesource
 */</span>
&nbsp;
&nbsp;
<span style="color: #0000ff; font-style: italic;">/**
 * Class Service
 *
 * @copyright  
 * @author     
 * @package    Model
 */</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">class</span> Service <span style="color: #000000; font-weight: bold;">extends</span> Model
<span style="color: #009900;">&#123;</span>
  protected <span style="color: #000088;">$strTable</span> <span style="color: #339933;">=</span> <span style="">'tl_filiere_services'</span>;
&nbsp;
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> __construct<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    parent<span style="color: #339933;">::</span>__construct<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

</pre>

<div class="wp_syntax"><div class="code"><pre class="php php" style="font-family:monospace;"><span style="color: #339933;">&lt;</span> ?php <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #990000;">defined</span><span style="color: #009900;">&#40;</span><span style="">'TL_ROOT'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #990000;">die</span><span style="color: #009900;">&#40;</span><span style="">'You can not access this file directly!'</span><span style="color: #009900;">&#41;</span>;
&nbsp;
<span style="color: #0000ff; font-style: italic;">/**
 * TYPOlight webCMS
 * Copyright (C) 2005 Leo Feyer
 *
 * This program is free software: you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation, either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this program. If not, please visit the Free
 * Software Foundation website at http://www.gnu.org/licenses/.
 *
 * PHP version 5
 * @copyright  
 * @author    
 * @package    
 * @license    
 * @filesource
 */</span>
&nbsp;
&nbsp;
<span style="color: #0000ff; font-style: italic;">/**
 * Class Filiale
 *
 * @copyright  
 * @author     
 * @package    Model
 */</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">class</span> Filiale <span style="color: #000000; font-weight: bold;">extends</span> Model
<span style="color: #009900;">&#123;</span>
  protected <span style="color: #000088;">$strTable</span> <span style="color: #339933;">=</span> <span style="">'tl_filiere_services'</span>;
&nbsp;
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> __construct<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    parent<span style="color: #339933;">::</span>__construct<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Et c&#8217;est tout. Nous disposons maintenant de tout ce qu&#8217;il faut pour trouver une entrée, récupérer la valeur de ses champs, enregistrer ses changements ou l&#8217;effacer. Par exemple :</p>
</pre>

<div class="wp_syntax"><div class="code"><pre class="php php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">// crée un objet service</span>
<span style="color: #000088;">$service</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Service<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;
&nbsp;
<span style="color: #666666; font-style: italic;">// retrouver l'entrée qui a l'id 10</span>
<span style="color: #000088;">$service</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">findBy</span><span style="color: #009900;">&#40;</span> <span style="">'id, 10 );
&nbsp;
// retrouve l'</span>attribut <span style="">'name'</span>
<span style="color: #990000;">echo</span> <span style="color: #000088;">$service</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">name</span>;
&nbsp;
<span style="color: #666666; font-style: italic;">// modifie l'attribut 'name'</span>
<span style="color: #000088;">$service</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">name</span> <span style="color: #339933;">=</span> <span style="">'new service'</span>;
&nbsp;
<span style="color: #666666; font-style: italic;">// enregistre les modifications dans la base de donnée</span>
<span style="color: #000088;">$service</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">save</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;
&nbsp;
<span style="color: #666666; font-style: italic;">// efface l'entrée</span>
<span style="color: #000088;">$service</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">delete</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;</pre></div></div>

<p>Nous pouvons maintenant manipuler simplement nos services et nos filiales sans avoir à écrire de fastidieuses requêtes SQL.</p>
<p>Mais ce n&#8217;est pas tout ce à quoi sert un modèle. Pour respecter le design pattern, il faut que toute manipulation de donnée soit faite dans le modèle. C&#8217;est son rôle, après tout. Dans le monde de Ruby on Rails, il y a même une devise : &#8220;thick models, thin controllers&#8221; ( modèles gros et contrôleurs minces ). L&#8217;idée est que puisque les modèles gèrent les données et que, précisément, un site est d&#8217;abord une question de données, c&#8217;est aux modèles de faire la majeure partie du travail. Il y a là un partie pris ( comme toujours avec rails ), vous en penserez ce que vous voudrez. Néanmoins, il reste exact que les manipulations des données doivent être opérées par les modèles. Reste a définir la limite entre &#8220;traitement des données&#8221; et &#8220;contrôle d&#8217;une requête&#8221; :)</p>
<p>Prenons un exemple concret. Les services de nos filiales ont un prix. Disons que ce prix est hors taxe. Il va me falloir, à un moment ou un autre, calculer le prix TTC pour un service. C&#8217;est ici typiquement une méthode qui doit résider dans le modèle Service. Comme nous sommes insouciants, nous allons considérer que les taxes sont fixes et que nous pouvons considérer qu&#8217;elles sont de 20% ( dans un cas réel, il faudrait rendre cette valeur configurable en backend ). Voici la méthode que nous allons rajouter dans la classe Service :</p>

<div class="wp_syntax"><div class="code"><pre class="php php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> ttc<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
  <span style="color: #000088;">$ttc</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">price</span> <span style="color: #339933;">+</span> <span style="color: #009900;">&#40;</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">price</span> <span style="color: #339933;">*</span> <span style="color:#800080;">0.2</span> <span style="color: #009900;">&#41;</span>;
  <span style="color: #b1b100;">return</span> <span style="color: #000088;">$ttc</span>;
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Désormais, dans le template qui affiche un service, nous n&#8217;aurons plus qu&#8217;à faire :</p>

<div class="wp_syntax"><div class="code"><pre class="php php" style="font-family:monospace;"><span style="color: #339933;">&lt;</span>p<span style="color: #339933;">&gt;</span>Prix TTC <span style="color: #339933;">:</span> <span style="color: #339933;">&lt;</span> ?php <span style="color: #990000;">echo</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">service</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">ttc</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> ?<span style="color: #339933;">&gt;&lt;/</span>p<span style="color: #339933;">&gt;</span></pre></div></div>

<p>( nous verrons dans un prochain tutoriel comment passer des variables à un template ).</p>
<h3>Ce que la classe Model de Typolight ne permet pas</h3>
<p>Aujourd&#8217;hui, les ORM des frameworks permettent toutes sortes de raffinements, telle que les associations, les validations, finders et autres.</p>
<p>Nos filiales ont des services. Nous voudrions, avec un objet $filiale, pouvoir faire $filiale->services() pour avoir la liste des services de cette filiale. C&#8217;est ce que permettent de faire les associations, par le biais de relations ( has many, has one, belongs to, many to many&#8230; ).</p>
<p>Nous voudrions aussi empêcher d&#8217;enregistrer les modifications sur une filiale si l&#8217;adresse mail fournie n&#8217;est pas dans un format valide ( par exemple &#8220;1HD23s&#8221; ). C&#8217;est le rôle des validations ( elle sont présentes dans les widgets backend, dans Typolight, mais pas dans la couche modèle ). </p>
<p>Enfin, nous voudrions pouvoir, par exemple, trouver toutes les filiales enregistrées depuis moins d&#8217;un mois. Ou simplement trouver toutes les filiales. Ou trouver la première filiale qui se trouve à Lyon. C&#8217;est le rôle des finders.</p>
<p>Avec la couche modèle de Typolight, vous devrez écrire ces méthodes vous-même. Si vous désirez avoir une solution générique pour ces problèmes relativement courant, je vous invite à utiliser ma classe EModel : <a href="http://github.com/oelmekki/typolight_framework/blob/master/system/modules/framework/EModel.php">http://github.com/oelmekki/typolight_framework/blob/master/system/modules/framework/EModel.php</a> ( promis, la documentation arrive. Vous devrez pour l&#8217;instant lire le code ou me poser des questions pour comprendre comment s&#8217;en servir ).</p>
<p>Cela conclut mon article sur les modèles dans Typolight. Nous verrons ensuite les modules frontend.</p>
 <img src="http://blog.olivier-elmekki.com/wp-content/plugins/feed-statistics.php?view=1&post_id=407" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://blog.olivier-elmekki.com/2009/11/08/typolight-et-les-modeles-m-comme-dans-vc/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Hadopi 2 : la loi, c&#8217;est moi.</title>
		<link>http://blog.olivier-elmekki.com/2009/10/23/hadopi-2-la-loi-cest-moi/</link>
		<comments>http://blog.olivier-elmekki.com/2009/10/23/hadopi-2-la-loi-cest-moi/#comments</comments>
		<pubDate>Fri, 23 Oct 2009 00:17:25 +0000</pubDate>
		<dc:creator>kik</dc:creator>
		
		<category><![CDATA[éditoral]]></category>

		<guid isPermaLink="false">http://blog.olivier-elmekki.com/?p=385</guid>
		<description><![CDATA[Hadopi version 2 a donc été approuvée par le conseil constitutionnel.
Pour rappel, ce même conseil avait rejeté une version précédente en faisant appel à l&#8217;article 11 de la déclaration des droits de l&#8217;homme de 1789, estimant qu&#8217;un filtrage du réseau nuisait à la liberté d&#8217;expression. En effet, Internet permet de communiquer et empêcher l&#8217;accès à [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.olivier-elmekki.com/wp-content/uploads/2009/10/judge_dredd_ver1.jpg"><img class="alignnone size-thumbnail wp-image-389" style="margin-left: 10px; float:right;" title="judge_dredd_ver1" src="http://blog.olivier-elmekki.com/wp-content/uploads/2009/10/judge_dredd_ver1-150x150.jpg" alt="" width="150" height="150" /></a>Hadopi version 2 a donc été approuvée par le conseil constitutionnel.</p>
<p>Pour rappel, ce même conseil avait rejeté une version précédente en faisant appel à <a href="http://www.assemblee-nationale.fr/histoire/dudh/1789.asp">l&#8217;article 11 de la déclaration des droits de l&#8217;homme de 1789</a>, estimant qu&#8217;un filtrage du réseau nuisait à la liberté d&#8217;expression. En effet, Internet permet de communiquer et empêcher l&#8217;accès à Internet revient à nuire à la « libre communication des pensées et des opinions ».</p>
<p><span id="more-385"></span></p>
<p>Le point contesté était qu&#8217;une privation de liberté ne pouvait se faire sans l&#8217;intervention d&#8217;un juge (comme c&#8217;est le cas par exemple pour une peine de prison).</p>
<p>Or la loi que vient d&#8217;approuver aujourd&#8217;hui le conseil constitutionnel valide la mise en place de procédures simplifiées. Qu&#8217;est-ce qu&#8217;une procédure simplifiée? Ce n&#8217;est pas une comparution immédiate, telle qu&#8217;elle existe déjà dans les cas les plus extrêmes, c&#8217;est bien pire : il s&#8217;agit d&#8217;un jugement &#8220;interne&#8221; et immédiat dans lequel la présence de l&#8217;accusé n&#8217;est pas nécessaire.</p>
<p>Judge Dredd, bienvenue en France.</p>
<p>Notons cependant, ce passage du <a href="http://www.assemblee-nationale.fr/13/rapports/r1841.asp">rapport des discussions</a> :</p>
<p style="text-align: justify;"><span style="font-size: 13pt; font-family: 'Times New Roman';"><strong>M. Christian Paul. </strong>Quelle désinvolture, monsieur le Rapporteur, dans votre présentation des choses ! Nous sommes tout autant que vous garants de la qualité de la loi et de la défense des libertés !</span></p>
<p style="text-align: justify;"><span style="font-size: 13pt; font-family: 'Times New Roman';">Notre amendement vise donc à supprimer le recours aux ordonnances pénales. Vous nous dites, madame la ministre, que l’avis du Conseil d’État ne mentionne pas les ordonnances pénales. Je vous crois bien sûr. Mais n’est-il pas un peu facile de vous prévaloir de cet avis quand il vous arrange, tout en refusant de nous donner connaissance de l’ensemble du document ?</span></p>
<p style="text-align: justify;"><span style="font-size: 13pt; font-family: 'Times New Roman';">Monsieur le rapporteur, en acceptant une procédure de masse, vous réduisez les droits de la défense et proposez une justice expéditive. Cela n’est pas supportable. L’ordonnance pénale est une procédure écrite et non <a href="http://fr.wikipedia.org/wiki/Principe_du_contradictoire_dans_les_proc%C3%A9dures_juridictionnelles_en_France">contradictoire</a> : l’auteur des faits n’est pas entendu par le juge.</span></p>
<p style="text-align: justify;"><span style="font-size: 13pt; font-family: 'Times New Roman';"><strong>Mme Martine Billard. </strong>Même argumentaire.</span></p>
<p style="text-align: justify;"><span style="font-size: 13pt; font-family: 'Times New Roman';"><strong>M. le rapporteur.</strong> Avis défavorable. L’ordonnance pénale est certes une procédure simplifiée, mais elle est assortie de toutes les garanties. La personne incriminée peut être entendue par le juge si elle le souhaite et demander à être jugée au cours d’une audience publique.</span></p>
<p style="text-align: justify;"><span style="font-size: 13pt; font-family: 'Times New Roman';"><em>La Commission <strong>rejette </strong>les deux amendements.</em></span></p>
<p style="text-align: justify;">Ainsi, si vous êtes un jour victime d&#8217;Hadopi, sachez que vous pouvez refuser la « procédure simplifiée » et exiger un procès loyal.</p>
<p style="text-align: justify;">Notons encore (tout de même) qu&#8217;il est bien habile de rejeter les soupçons de privation des droits fondamentaux sur les même juges qui subissent déjà des attaques en règle pour être assujettis au pouvoir exécutif, qui se met en même temps à l&#8217;écart des critiques constitutionnelles. Chapeau bas pour Machiavel.</p>
 <img src="http://blog.olivier-elmekki.com/wp-content/plugins/feed-statistics.php?view=1&post_id=385" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://blog.olivier-elmekki.com/2009/10/23/hadopi-2-la-loi-cest-moi/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Mise en ligne de Stick&#8217;innov et framework Typolight</title>
		<link>http://blog.olivier-elmekki.com/2009/09/04/mise-en-ligne-de-stickinnov-et-framework-typolight/</link>
		<comments>http://blog.olivier-elmekki.com/2009/09/04/mise-en-ligne-de-stickinnov-et-framework-typolight/#comments</comments>
		<pubDate>Fri, 04 Sep 2009 13:39:27 +0000</pubDate>
		<dc:creator>kik</dc:creator>
		
		<category><![CDATA[typolight]]></category>

		<guid isPermaLink="false">http://blog.olivier-elmekki.com/?p=367</guid>
		<description><![CDATA[Stick&#8217;innov est une société de vente de stickers muraux, vous proposant les classiques stickers adhésifs et pochoirs, ainsi qu&#8217;un produit nouveau : le sticker magnétique. Celui-ci peut être choisi avec un support en laize magnétique ou en peinture aimantée. Un large catalogue vous permet de rajouter une touche personnelle corespondant aux différentes ambiences de votre [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.stick-innov.fr/accueil.html">Stick&#8217;innov</a> est une société de vente de stickers muraux, vous proposant les classiques stickers adhésifs et pochoirs, ainsi qu&#8217;un produit nouveau : le sticker magnétique. Celui-ci peut être choisi avec un support en <a href="http://www.stick-innov.fr/mode-demploi-stickers-magnetiques-support-vinyle-magnetique.html">laize magnétique</a> ou en <a href="http://www.stick-innov.fr/mode-demploi-stickers-magnetiques-support-peinture-aimantee.html">peinture aimantée</a>. Un large catalogue vous permet de rajouter une touche personnelle corespondant aux différentes ambiences de votre logement, pour <a href="http://www.stick-innov.fr/adhesif/Abstrait-35/modele/334.html">adoucir votre salon</a>, ajouter <a href="http://www.stick-innov.fr/adhesif/Nature-9/modele/111.html">une note exotique</a> ou créer la surprise au détour <a href="http://www.stick-innov.fr/adhesif/Panneaux-33/modele/380.html">d&#8217;une fantaisie</a>.</p>
<p><span id="more-367"></span></p>
<p>J&#8217;ai réalisé ce site avec <a href="http://www.bouctoubou.com/">Telly Delalande</a>, pour le compte de la société Stick&#8217;Innov. Telly s&#8217;est occupé de la charte graphique et de l&#8217;intégration et j&#8217;ai pris en charge le développement moteur et la couche javascript. Pour distinguer le site de ses concurents et lui offrir une avance en référencement, nous avons fait le choix de réaliser l&#8217;application sans utiliser  flash, au profit d&#8217;une interface javascript non obstrusive et dégradable.</p>
<p>Le site est realisé entièrement sous <a href="http://www.typolight.org/">Typolight</a>, autant pour les pages statiques, que pour les fonctions motrices et que pour la partie boutique. Il constitue une première démonstration publique de ce qui est faisable avec Typolight et mon extension framework. Cette application étant commerciale et réalisée pour un tiers, je ne peux en montrer le code, mais je peux démontrer certaines particularités du framework.</p>
<h3>Les routes</h3>
<p>Ce qui est peut-être le plus flagrant pour un utilisateur de Typolight est l&#8217;usage des routes. Prenons par exemple l&#8217;adresse : http://www.stick-innov.fr/adhesif/Abstrait-35/modele/105.html . Ceci est rendu possible en utilisant une &#8220;route&#8221;. Une route est caractérisée par une définition, reflétant l&#8217;url, qui lorsqu&#8217;elle correspond renvoie à une page donnée avec des paramètres donnés. Ces routes peuvent être configurées soit dans le config/config.php de votre module, soit en backend. Ici, je l&#8217;ai mise dans le config.php, ce qui donne :</p>

<div class="wp_syntax"><div class="code"><pre class="php php" style="font-family:monospace;">array_insert<span style="color: #009900;">&#40;</span> <span style="color: #000088;">$GLOBALS</span><span style="color: #009900;">&#91;</span> <span style="">'TL_ROUTES'</span> <span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> <span style="color:#800080;">0</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
    <span style="color: #0000ff;">&quot;fr_adhesif&quot;</span>          <span style="color: #339933;">=&amp;</span>gt; <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
      <span style="">'route'</span>         <span style="color: #339933;">=&amp;</span>gt; <span style="">'adhesif/:theme/modele/:modele_id'</span><span style="color: #339933;">,</span>
      <span style="">'staticParams'</span>  <span style="color: #339933;">=&amp;</span>gt; <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
        <span style="">'action'</span> <span style="color: #339933;">=&amp;</span>gt; <span style="">'index'</span><span style="color: #339933;">,</span>
        <span style="">'type'</span>   <span style="color: #339933;">=&amp;</span>gt; <span style="">'adhesif'</span><span style="color: #339933;">,</span>
      <span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
      <span style="">'method'</span>    <span style="color: #339933;">=&amp;</span>gt; <span style="">'GET'</span><span style="color: #339933;">,</span>
      <span style="">'resolveTo'</span>     <span style="color: #339933;">=&amp;</span>gt; <span style="">'adhesif'</span><span style="color: #339933;">,</span>
    <span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
  <span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#41;</span>;</pre></div></div>

<p>La définition de la route est donc ici : &#8216;adhesif/:theme/modele/:modele_id&#8217;. :theme et :modele_id sont des variables. N&#8217;importe quelle valeur peut y être introduite et sera injectée dans les paramètres GET, récupérable avec $this-&gt;Input-&gt;get( &#8216;nom_du_param&#8217; ).</p>
<p>L&#8217;option &#8217;staticParams&#8217; permet de rajouter arbitrairement des paramètres supplémentaires. Ici, &#8216;action&#8217; est utilisé pour déterminer quelle action le contrôleur devra executer et &#8216;type&#8217; est un paramètre que j&#8217;ai ajouté pour pouvoir ne faire qu&#8217;un contrôleur pour les trois types de produits.</p>
<p>L&#8217;option &#8216;method&#8217; détermine quel verbe http accepte la route. En utilisant GET, nous interdisons l&#8217;usage de POST. Si nous utilisons un POST sur cette url, l&#8217;application répondra par une 404. Cela permet de router vers des actions ou pages différentes le GET et le POST sur une même url. Les options de &#8216;method&#8217; sont : &#8216;GET&#8217;, &#8216;POST&#8217; ou &#8216;GET/POST&#8217;. Ce dernier accepte les deux verbes.</p>
<p>Enfin, l&#8217;option &#8216;resolveTo&#8217; indique la page vers laquelle la route redirige.</p>
<p>Cette route a un nom : &#8216;fr_adhesif&#8217;. Ce nom est utilisé pour générer une url à partir d&#8217;un nom, grâce à Route::compose(). Ainsi, si nous avons :</p>

<div class="wp_syntax"><div class="code"><pre class="php php" style="font-family:monospace;">array_insert<span style="color: #009900;">&#40;</span> <span style="color: #000088;">$GLOBALS</span><span style="color: #009900;">&#91;</span> <span style="">'TL_ROUTES'</span> <span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> <span style="color:#800080;">0</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
    <span style="color: #0000ff;">&quot;product_list&quot;</span>          <span style="color: #339933;">=&amp;</span>gt; <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
      <span style="">'route'</span>         <span style="color: #339933;">=&amp;</span>gt; <span style="">'voir/les/produits'</span><span style="color: #339933;">,</span>
      <span style="">'staticParams'</span>  <span style="color: #339933;">=&amp;</span>gt; <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
        <span style="">'action'</span> <span style="color: #339933;">=&amp;</span>gt; <span style="">'list'</span><span style="color: #339933;">,</span>
      <span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
      <span style="">'method'</span>    <span style="color: #339933;">=&amp;</span>gt; <span style="">'GET'</span><span style="color: #339933;">,</span>
      <span style="">'resolveTo'</span>     <span style="color: #339933;">=&amp;</span>gt; <span style="">'produits'</span><span style="color: #339933;">,</span>
    <span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
  <span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#41;</span>;</pre></div></div>

<p>et que nous voulons faire un lien en utilisant cette route dans une vue, nous pouvons faire :</p>

<div class="wp_syntax"><div class="code"><pre class="php php" style="font-family:monospace;"><span style="color: #339933;">&lt;</span>a href<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;&amp;lt;?php echo Route::compose( 'product_list' ) ?&amp;gt;&quot;</span><span style="color: #339933;">&gt;</span>Voir les produits<span style="color: #339933;">&lt;/</span>a<span style="color: #339933;">&gt;</span></pre></div></div>

<p>ou, avec un insert tag :</p>

<div class="wp_syntax"><div class="code"><pre class="php php" style="font-family:monospace;"><span style="color: #339933;">&lt;</span>a href<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;{{Route::product_list}}&quot;</span><span style="color: #339933;">&gt;</span>Voir les produits<span style="color: #339933;">&lt;/</span>a<span style="color: #339933;">&gt;</span></pre></div></div>

<p>Il est ensuite possible de modifier la définition de la route sans avoir à modifier ce code.</p>
<p>Dans le cas de la première route que j&#8217;ai montrée, il y a également deux paramètres dynamiques, :theme et :modele_id. Ces paramètres sont ajoutés en passant un array associatif :</p>

<div class="wp_syntax"><div class="code"><pre class="php php" style="font-family:monospace;"><span style="color: #339933;">&lt;</span>a href<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;&amp;lt;?php echo Route::compose( 'fr_adhesif', array( 'theme' =&amp;gt; $theme-&amp;gt;urlName, 'modele_id' =&amp;gt; $modele-&amp;gt;id ) ) ?&amp;gt;&quot;</span><span style="color: #339933;">&gt;</span>Voir les produits<span style="color: #339933;">&lt;/</span>a<span style="color: #339933;">&gt;</span></pre></div></div>

<p>Enfin, les routes supportent l&#8217;internationalisation. Si nous avons :</p>

<div class="wp_syntax"><div class="code"><pre class="php php" style="font-family:monospace;">array_insert<span style="color: #009900;">&#40;</span> <span style="color: #000088;">$GLOBALS</span><span style="color: #009900;">&#91;</span> <span style="">'TL_ROUTES'</span> <span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> <span style="color:#800080;">0</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
    <span style="color: #0000ff;">&quot;fr_adhesif&quot;</span>          <span style="color: #339933;">=&amp;</span>gt; <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
      <span style="">'route'</span>         <span style="color: #339933;">=&amp;</span>gt; <span style="">'adhesif/:theme/modele/:modele_id'</span><span style="color: #339933;">,</span>
      <span style="">'staticParams'</span>  <span style="color: #339933;">=&amp;</span>gt; <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
        <span style="">'action'</span> <span style="color: #339933;">=&amp;</span>gt; <span style="">'index'</span><span style="color: #339933;">,</span>
        <span style="">'type'</span>   <span style="color: #339933;">=&amp;</span>gt; <span style="">'adhesif'</span><span style="color: #339933;">,</span>
      <span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
      <span style="">'method'</span>    <span style="color: #339933;">=&amp;</span>gt; <span style="">'GET'</span><span style="color: #339933;">,</span>
      <span style="">'resolveTo'</span>     <span style="color: #339933;">=&amp;</span>gt; <span style="">'adhesif'</span><span style="color: #339933;">,</span>
    <span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
    <span style="color: #0000ff;">&quot;en_adhesif&quot;</span>          <span style="color: #339933;">=&amp;</span>gt; <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
      <span style="">'route'</span>         <span style="color: #339933;">=&amp;</span>gt; <span style="">'adhesive/:theme/model/:modele_id'</span><span style="color: #339933;">,</span>
      <span style="">'staticParams'</span>  <span style="color: #339933;">=&amp;</span>gt; <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
        <span style="">'action'</span> <span style="color: #339933;">=&amp;</span>gt; <span style="">'index'</span><span style="color: #339933;">,</span>
        <span style="">'type'</span>   <span style="color: #339933;">=&amp;</span>gt; <span style="">'adhesif'</span><span style="color: #339933;">,</span>
      <span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
      <span style="">'method'</span>    <span style="color: #339933;">=&amp;</span>gt; <span style="">'GET'</span><span style="color: #339933;">,</span>
      <span style="">'resolveTo'</span>     <span style="color: #339933;">=&amp;</span>gt; <span style="">'adhesif'</span><span style="color: #339933;">,</span>
    <span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
  <span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#41;</span>;</pre></div></div>

<p>nous pouvons utiliser :</p>

<div class="wp_syntax"><div class="code"><pre class="php php" style="font-family:monospace;"><span style="color: #339933;">&lt;</span>a href<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;&amp;lt;?php echo Route::composeI18n( 'adhesif', array( 'theme' =&amp;gt; $theme-&amp;gt;urlName, 'modele_id' =&amp;gt; $modele-&amp;gt;id ) ) ?&amp;gt;&quot;</span><span style="color: #339933;">&gt;</span>Voir les produits<span style="color: #339933;">&lt;/</span>a<span style="color: #339933;">&gt;</span></pre></div></div>

<p>La langue courante sera utilisée pour déterminer quelle route il faut suivre.</p>
<p>Un dernier point : l&#8217;ordre des routes importe. Il est possible d&#8217;avoir des urls auxquelles plusieurs routes correspondent, comme par exemple si on a &#8220;voir/produits/tous&#8221; et &#8220;voir/produits/:produit_id&#8221;. Si cela arrive, la première route rencontrée l&#8217;emportera.</p>
<h3>Les contrôleurs</h3>
<p>Les contrôleurs de Typolight ( ModuleQuelqueChose, héritant de FrontendModule ) sont pensés pour n&#8217;executer qu&#8217;une seule action, bien qu&#8217;il soit possible de les forcer. Il y a la méthode generate() qui sert à initialiser le module, et la méthode compile() qui passe les variables à la vue ( template, dans le vocabulaire Typolight ). L&#8217;extension framework rajoute une nouvelle classe : RoutedModule.</p>
<p>RoutedModule est pensé pour permettre de gérer facilement des actions multiples. Quand un RoutedModule est généré, il regarde s&#8217;il existe un paramètre GET &#8216;action&#8217;. S&#8217;il y en a un et qu&#8217;une méthode du même nom existe dans le module, celle-ci est appelée et la vue est automatiquement déclarée selon le schémas : &#8216;fe&#8217; + nom du contrôleur + &#8216;_&#8217; + nom de l&#8217;action. Sinon, la méthode index() est utilisée. Prenons l&#8217;exemple d&#8217;un contrôleur simple :</p>

<div class="wp_syntax"><div class="code"><pre class="php php" style="font-family:monospace;"><span style="color: #339933;">&amp;</span>lt; ?php
&nbsp;
<span style="color: #000000; font-weight: bold;">class</span> ControllerProduct <span style="color: #000000; font-weight: bold;">extends</span> RoutedModule
<span style="color: #009900;">&#123;</span>
  protected <span style="color: #000088;">$controller</span> <span style="color: #339933;">=</span> <span style="">'products'</span>;
&nbsp;
  <span style="color: #666666; font-style: italic;">/* List products */</span>
  protected <span style="color: #000000; font-weight: bold;">function</span> index<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$product</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Product<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt;Template<span style="color: #339933;">-&amp;</span>gt;products <span style="color: #339933;">=</span> <span style="color: #000088;">$product</span><span style="color: #339933;">-&amp;</span>gt;all;
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #666666; font-style: italic;">/* Show a product */</span>
  protected <span style="color: #000000; font-weight: bold;">function</span> show<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$product</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Product<span style="color: #009900;">&#40;</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt;Input<span style="color: #339933;">-&amp;</span>gt;get<span style="color: #009900;">&#40;</span> <span style="">'product_id'</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span>;
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt;Template<span style="color: #339933;">-&amp;</span>gt;product <span style="color: #339933;">=</span> <span style="color: #000088;">$product</span>;
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #666666; font-style: italic;">/* Create a new product */</span>
  protected <span style="color: #000000; font-weight: bold;">function</span> create<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$product</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Product<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>;
    <span style="color: #000088;">$success</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">false</span>;
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> <span style="color: #000088;">$posted</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt;Input<span style="color: #339933;">-&amp;</span>gt;post<span style="color: #009900;">&#40;</span> <span style="">'product'</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
      <span style="color: #000088;">$product</span><span style="color: #339933;">-&amp;</span>gt;data <span style="color: #339933;">=</span> <span style="color: #000088;">$posted</span>;
&nbsp;
      <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> <span style="color: #000088;">$product</span><span style="color: #339933;">-&amp;</span>gt;save<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span>
      <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$success</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">true</span>;
      <span style="color: #009900;">&#125;</span>
&nbsp;
      <span style="color: #b1b100;">else</span>
      <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt;Template<span style="color: #339933;">-&amp;</span>gt;errors <span style="color: #339933;">=</span> <span style="color: #000088;">$product</span><span style="color: #339933;">-&amp;</span>gt;errors;
      <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt;Template<span style="color: #339933;">-&amp;</span>gt;product <span style="color: #339933;">=</span> <span style="color: #000088;">$product</span>;
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt;Template<span style="color: #339933;">-&amp;</span>gt;success <span style="color: #339933;">=</span> <span style="color: #000088;">$success</span>;
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #666666; font-style: italic;">/* Update a product */</span>
  protected <span style="color: #000000; font-weight: bold;">function</span> update<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$product</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Product<span style="color: #009900;">&#40;</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt;Input<span style="color: #339933;">-&amp;</span>gt;get<span style="color: #009900;">&#40;</span> <span style="">'product_id'</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span>;
    <span style="color: #000088;">$success</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">false</span>;
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> <span style="color: #000088;">$posted</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt;Input<span style="color: #339933;">-&amp;</span>gt;post<span style="color: #009900;">&#40;</span> <span style="">'product'</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
      <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> <span style="color: #000088;">$product</span><span style="color: #339933;">-&amp;</span>gt;update_attributes<span style="color: #009900;">&#40;</span> <span style="color: #000088;">$posted</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span>
      <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$success</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">true</span>;
      <span style="color: #009900;">&#125;</span>
&nbsp;
      <span style="color: #b1b100;">else</span>
      <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt;Template<span style="color: #339933;">-&amp;</span>gt;errors <span style="color: #339933;">=</span> <span style="color: #000088;">$product</span><span style="color: #339933;">-&amp;</span>gt;errors;
      <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt;Template<span style="color: #339933;">-&amp;</span>gt;product <span style="color: #339933;">=</span> <span style="color: #000088;">$product</span>;
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt;Template<span style="color: #339933;">-&amp;</span>gt;success <span style="color: #339933;">=</span> <span style="color: #000088;">$success</span>;
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #666666; font-style: italic;">/* Delete a product */</span>
  protected <span style="color: #000000; font-weight: bold;">function</span> delete<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$product</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Product<span style="color: #009900;">&#40;</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt;Input<span style="color: #339933;">-&amp;</span>gt;get<span style="color: #009900;">&#40;</span> <span style="">'product_id'</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span>;
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span> <span style="color: #000088;">$product</span><span style="color: #339933;">-&amp;</span>gt;delete<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
      <span style="color: #000088;">$this</span><span style="color: #339933;">-&amp;</span>gt;redirect<span style="color: #009900;">&#40;</span> Route<span style="color: #339933;">::</span><span style="color: #004000;">compose</span><span style="color: #009900;">&#40;</span> <span style="">'product_list'</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span>;
    <span style="color: #009900;">&#125;</span>
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Ceux qui se sont déjà servi de Ruby on Rails trouveront ici une note familière. Un utilisateur de Typolight pourra s&#8217;interroger sur les méthodes de Product. Product hérite en fait d&#8217;une autre classe du framework, EModel, que je traiterai une autre fois.</p>
<p>La première chose à faire est de donner un nom au contrôleur :</p>

<div class="wp_syntax"><div class="code"><pre class="php php" style="font-family:monospace;">protected <span style="color: #000088;">$controller</span> <span style="color: #339933;">=</span> <span style="">'products'</span>;</pre></div></div>

<p>Ensuite, on définit les différentes actions, et le paramètre GET &#8216;action&#8217; déterminera lequel utiliser. La vue est automatiquement retrouvée d&#8217;après le nom du contrôleur et de l&#8217;action, comme je l&#8217;ai expliqué plus haut. Ici, on aura donc les vues : fe_products_index.tpl, fe_products_show.tpl, fe_products_create.tpl, fe_products_update.tpl et fe_products_delete.tpl .</p>
<p>RoutedModule offre de nombreuses autres fonctionalités, comme la possibilité de forcer l&#8217;action sans prendre en compte le paramètre d&#8217;action ( utile lorsqu&#8217;on a plusieurs RoutedModule dans une même page ), les getters et les setters, le cache, la gestion de json, et autres.</p>
<p>Si vous désirez essayer l&#8217;extension framework, vous pouvez la <a href="http://github.com/oelmekki/typolight_framework/tree/master">télécharger sur github</a>. Je suis sur le point de publier mon troisième site l&#8217;utilisant et je le considère donc comme stable. La version 1.0 devrait sortir sous peu, après un cleanup de l&#8217;API et l&#8217;écriture de documentation.</p>
 <img src="http://blog.olivier-elmekki.com/wp-content/plugins/feed-statistics.php?view=1&post_id=367" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://blog.olivier-elmekki.com/2009/09/04/mise-en-ligne-de-stickinnov-et-framework-typolight/feed/</wfw:commentRss>
		</item>
		<item>
		<title>CMS ou Framework? Le choix de Typolight</title>
		<link>http://blog.olivier-elmekki.com/2009/08/16/cms-ou-framework-le-choix-de-typolight/</link>
		<comments>http://blog.olivier-elmekki.com/2009/08/16/cms-ou-framework-le-choix-de-typolight/#comments</comments>
		<pubDate>Sun, 16 Aug 2009 12:03:02 +0000</pubDate>
		<dc:creator>kik</dc:creator>
		
		<category><![CDATA[typolight]]></category>

		<guid isPermaLink="false">http://blog.olivier-elmekki.com/?p=359</guid>
		<description><![CDATA[La question est vieille, même si les développeurs refusent de se la poser clairement. Autant le dire tout de suite, j&#8217;ai moi aussi été un développeur qui ne voulait pas entendre parler de CMS. Les CMS, c&#8217;est bons pour les intégrateurs qui n&#8217;ont pas de dév, ça ne permet que de répondre aux besoins les [...]]]></description>
			<content:encoded><![CDATA[<p>La question est vieille, même si les développeurs refusent de se la poser clairement. Autant le dire tout de suite, j&#8217;ai moi aussi été un développeur qui ne voulait pas entendre parler de CMS. Les CMS, c&#8217;est bons pour les intégrateurs qui n&#8217;ont pas de dév, ça ne permet que de répondre aux besoins les plus courants en rendant toute extension pénible et tortueuse, c&#8217;est souvent mal écrit, tout ça.</p>
<p><span id="more-359"></span></p>
<h3>Premier contact avec Typolight</h3>
<p>Lorsque j&#8217;ai commencé mes activités de freelance, j&#8217;ai rencontré <a href="http://www.bouctoubou.com/">Telly Delalande</a>, avec lequel je travaille régulièrement aujourd&#8217;hui. Telly est passionné par un CMS qui s&#8217;appelle <a href="http://www.typolight.org/">Typolight</a>, et dont il m&#8217;a assuré que c&#8217;était <a href="http://blog.bouctoubou.com/typolight-le-meilleur-cms-au-monde/">le meilleur CMS du monde</a>. Son article a provoqué de telles réactions que j&#8217;ai décidé de lancer un troll moi aussi :)</p>
<p>Plus sérieusement, quand Telly m&#8217;a parlé de Typolight, j&#8217;ai accepté d&#8217;y jeter un oeil sans trop y croire. Premier constat : <a href="http://dev.typolight.org/wiki/DevelopmentIndex">la documentation pour développeur</a> est franchement lacunaire. Ok, qu&#8217;à cela ne tienne, &#8220;use the source, Luke&#8221;. J&#8217;ouvre le code pour essayer de comprendre comment tout cela fonctionne. Et là survient la première surprise : c&#8217;est bien codé, très bien codé, même. Il y a bien quelques vieilleries PHP-iennes, comme l&#8217;absence d&#8217;une vraie classe modèle ( la classe Model est un singleton destiné à mapper l&#8217;user courant ) et donc la profusion de requêtes sql dans les contrôleurs, mais le tout est propre est agréable à lire (sauf quelques fichiers plus anciens que les autres).</p>
<p>Je décide donc de faire un essai, et de mettre l&#8217;extensibilité à l&#8217;épreuve.</p>
<h3>Les modules</h3>
<p>L&#8217;extension de Typolight se fait comme dans beaucoup de CMS par l&#8217;ajout de modules. C&#8217;est donc assez banal, mais ça m&#8217;a plu sur le coup comme je venais juste d&#8217;essayer <a href="http://www.merbivore.com/">Merb</a> dont le concept de modulabilité m&#8217;avait beaucoup intéressé ( oui, ca se fait très bien par l&#8217;intermédiaire des plugins dans Rails ou Symfony, mais permettre quelque chose et encourager son utilisation dans le design même d&#8217;une application sont deux choses aux résultats totalement différents ).</p>
<p>Les modules de Typolight sont donc des répertoires, placés dans system/modules/, et dans lesquels on peut mettre tous les fichiers nécessaires à une fonctionalité : modèles, contrôleurs, vues, css, js, fichier de migration db, fichier de configuration, etc.</p>
<p>Tout de suite, les limitations apparaissent. Un contrôleur dans un module ne gère qu&#8217;une seule action. Cependant, l&#8217;application étant entièrement orientée objet et pensée pour la surcharge, il m&#8217;a été facile de rajouter un classe de contrôleur permettant de gérer plusieurs actions. Tout comme il m&#8217;a été possible de rajouter une gestion de routes complètement arbitraire. Tout comme il m&#8217;a été possible de rajouter un classe que j&#8217;ai nommée EModel, et qui reprend les fonctionnalités classiques d&#8217;un modèle dans les frameworks : associations, validations, recherches selon paramètres, etc. Les bases étaient posées.</p>
<h3>Utiliser Typolight comme un framework</h3>
<p>Au fur et à mesure que mes besoins se précisaient, je rajoutais des fonctionnalités dans mon module &#8220;<a href="http://github.com/oelmekki/typolight_framework/tree/master">framework</a>&#8221; qui me permettait de développer d&#8217;autres modules sans sentir de contraites CMS-iennes. Chaque fois, j&#8217;étais surpris d&#8217;avec quelle facilité c&#8217;était faisable. Bien sûr, il faut parcourir le code et le connaître un minimum dans son ensemble pour se permettre des modifications aussi conséquentes, mais c&#8217;est chaque fois la même surprise : c&#8217;est possible, et proprement en plus.</p>
<p>Aujourd&#8217;hui, j&#8217;utilise Typolight d&#8217;une manière très similaire à mon utilisation de Ruby on Rails. J&#8217;ai intégré <a href="http://cukes.info/">cucumber</a> et <a href="http://www.phpspec.org/">phpspec</a> par l&#8217;intermédiaire d&#8217;un module &#8220;<a href="http://github.com/oelmekki/typolight_testing/tree/master">testing</a>&#8220;, je fais donc du <a href="http://en.wikipedia.org/wiki/Behavior_Driven_Development">bdd</a>, à base de user stories suivant lesquelles je déroule mes vues, contrôleurs, modèles et routes dans un soucis de réutilisabilité.</p>
<p>Je me retrouve donc dans la situation où l&#8217;argument de manque d&#8217;extensibilité est brisé.</p>
<h3>Focus!</h3>
<p>Dans le même mouvement, je me retrouve avec une pluvalue d&#8217;avantages qui relève de tous les inconvénients du framework quand on le compare au CMS : pas de perte de temps à coder des fonctionnalités banales que je ferai de toutes façons moins complètes que celles présentes dans un CMS, développées depuis des années.</p>
<p>C&#8217;est là qu&#8217;apparaît le point vraiment intéressant : le fait de pouvoir se permettre de se focaliser entièrement et uniquement sur les fonctionnalités spécifiques dont a besoin le client. Cela rend le développement rapide, beaucoup plus rapide. Recoupé avec la possibilité de faire du bdd, cela permet de produire des applications complètes, stables et peu coûteuses.</p>
<h3>CMS ou framework? Les deux mon capitaine.</h3>
<p>Cela m&#8217;amène à me poser la question : en quoi les CMS et les frameworks sont incompatibles? Les développeurs condamnent régulièrement les CMS pour leur manque d&#8217;extensibilité, mais il ne s&#8217;agit pas là d&#8217;une fatalité. C&#8217;est simplement un fait courant. Pour ma part, je dirais que le problème est surtout que beaucoup de CMS ont une base largement impérative, avec des require partout, l&#8217;OO n&#8217;apparaissant que dans la couche intermédiaire de l&#8217;application.</p>
<p>Un CMS pensé proprement (la notion de propreté voulant surtout dénoter la conformité aux bonnes pratiques du jour) peut très bien être extensible et peut même être pensé comme un framework.</p>
<p>Je n&#8217;irai pas dire que Typolight est ce CMS de rêve, mais il s&#8217;en rapproche incroyablement plus que les CMS dont nous avons l&#8217;habitude. Il rend en tous cas concrètement possible la fusion entre CMS et framework.</p>
<p>Peut-être est-ce à nous, développeurs, de proposer aujourd&#8217;hui des solutions CMS/Framework qui garantissent à la fois la possibilité d&#8217;être utilisées par des non-développeurs, de mettre en place en quelques minutes les fonctionnalités courantes, et d&#8217;offrir une extensibilité complète.</p>
 <img src="http://blog.olivier-elmekki.com/wp-content/plugins/feed-statistics.php?view=1&post_id=359" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://blog.olivier-elmekki.com/2009/08/16/cms-ou-framework-le-choix-de-typolight/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Datamith, convertisseur de base de donnée</title>
		<link>http://blog.olivier-elmekki.com/2009/02/14/datamith-convertisseur-de-base-de-donnee/</link>
		<comments>http://blog.olivier-elmekki.com/2009/02/14/datamith-convertisseur-de-base-de-donnee/#comments</comments>
		<pubDate>Sat, 14 Feb 2009 21:58:16 +0000</pubDate>
		<dc:creator>kik</dc:creator>
		
		<category><![CDATA[sysadmin]]></category>

		<guid isPermaLink="false">http://blog.olivier-elmekki.com/?p=354</guid>
		<description><![CDATA[Je viens de publier Datamith, un framework ruby permettant de convertir des base de données MySQL.
L&#8217;idée est de permettre de définir des règles de conversion pour importer le contenu d&#8217;une base de données dans une autre.

Dans son utilisation la plus simple, vous pouvez définir un ensemble de règle traduisant une base de donnée dans une [...]]]></description>
			<content:encoded><![CDATA[<p>Je viens de publier <a href="http://olivier-elmekki.com/datamith-fr.html">Datamith</a>, un framework ruby permettant de convertir des base de données MySQL.</p>
<p>L&#8217;idée est de permettre de définir des règles de conversion pour importer le contenu d&#8217;une base de données dans une autre.</p>
<p><span id="more-354"></span></p>
<p>Dans son utilisation la plus simple, vous pouvez définir un ensemble de règle traduisant une base de donnée dans une autre, par exemple pour changer de moteur de blog ou encore pour faire passer les données d&#8217;une application externe dans un module de CMS.</p>
<p>Il est également possible de s&#8217;en servir pour synchroniser une base de donnée. Si les entrées de la base de donnée source ont une clef primaire dont la valeur existe déjà dans la base de donnée de destination, les donnée de cette seconde base de donnée seront mis à jour (en suivant les règles définies).</p>
<p>Enfin, et c&#8217;est peut-être le plus intéressant, le framework peut être utilisé pour fusionner des bases de données. Imaginez que vous avez deux applications qui ont fait leur vie chacune de leur côté. Vous aimeriez importer les utilisateurs de l&#8217;une dans l&#8217;autre, mais il existe déjà des utilisateurs qui ont le même id. Datamith vous permet d&#8217;insérer ces utilisateurs tout en préservant les associations (par exemple le champs user_id de la table post).</p>
<p>Pour en savoir plus, je vous invite à voir <a href="http://olivier-elmekki.com/datamith-fr.html">la page de Datamith</a>, ainsi que sa <a href="http://olivier-elmekki.com/datamith/">documentation</a>. Le code est <a href="http://github.com/oelmekki/datamith/tree/master">téléchargeable sur Github</a>.</p>
 <img src="http://blog.olivier-elmekki.com/wp-content/plugins/feed-statistics.php?view=1&post_id=354" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://blog.olivier-elmekki.com/2009/02/14/datamith-convertisseur-de-base-de-donnee/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Débugger les événements js avec firebugUJS</title>
		<link>http://blog.olivier-elmekki.com/2009/01/25/debugger-les-evenements-js-avec-firebugujs/</link>
		<comments>http://blog.olivier-elmekki.com/2009/01/25/debugger-les-evenements-js-avec-firebugujs/#comments</comments>
		<pubDate>Sun, 25 Jan 2009 16:07:39 +0000</pubDate>
		<dc:creator>kik</dc:creator>
		
		<category><![CDATA[javascript]]></category>

		<category><![CDATA[jquery]]></category>

		<guid isPermaLink="false">http://blog.olivier-elmekki.com/?p=346</guid>
		<description><![CDATA[Avec le retour en force de javascript, la quête des &#8220;bonne pratiques&#8221; a trouvé un nouveau lieu d&#8217;investigation. Elle y a pris un nom : UJS (unobstrusive javascript).

Cette tendance conseille de faire une distinction nette entre le javascript et le HTML (comme on distingue le CSS du HTML) et de ne voir en javascript qu&#8217;un [...]]]></description>
			<content:encoded><![CDATA[<p>Avec le retour en force de javascript, la quête des &#8220;bonne pratiques&#8221; a trouvé un nouveau lieu d&#8217;investigation. Elle y a pris un nom : <a href="http://fr.wikipedia.org/wiki/Javascript_discret">UJS</a> (unobstrusive javascript).</p>
<p><span id="more-346"></span></p>
<p>Cette tendance conseille de faire une distinction nette entre le javascript et le HTML (comme on distingue le CSS du HTML) et de ne voir en javascript qu&#8217;un &#8220;bonus&#8221;, ne perturbant pas l&#8217;utilisation du site si javascript venait à être désactivé par le navigateur.</p>
<p>Concrètement, cela passe par un développement de l&#8217;application excluant javascript, puis par l&#8217;implémentation d&#8217;une surcouche comportementale (animations, événements) dans un fichier javascript externe.</p>
<p>Il est donc exclu d&#8217;inclure de larges portions de javascript dans une balise script du HTML ou de définir dans les balises des attributs d&#8217;événements, comme onclick ou onmouseover.</p>
<h3>Le problème</h3>
<p>Si je veux exécuter la fonction <em>name_clicked()</em> lorsque je clique sur le <em>li</em> avec la classe <em>name</em>, je ferai ainsi avec jQuery :</p>

<div class="wp_syntax"><div class="code"><pre class="javascript javascript" style="font-family:monospace;">$<span style="color: #009900;">&#40;</span> <span style="color: #3366CC;">'li.name'</span> <span style="color: #009900;">&#41;</span>.<span style="color: #660066;">click</span><span style="color: #009900;">&#40;</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span> name_clicked<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span>;</pre></div></div>

<p>Le problème ici est que je ne disposerai d&#8217;aucun moyen pour savoir si l&#8217;événement à bien été attaché à un <em>li</em> en particulier. Si je clique sur le <em>li</em> et que rien ne se passe, est-ce un problème avec <em>name_clicked()</em> ou avec l&#8217;événement? Le seul moyen que j&#8217;ai de vérifier est de parsemer mon code de <em>alert()</em> ou de <em>console.log()</em>, ce qui est généralement la solution de dernier recours.</p>
<h3>La solution</h3>
<p><a href="http://remi.org/">Ryan Taylor</a> a publié <a href="http://remi.org/2009/01/06/using-firebug-to-debug-unobtrusive-javascript.html">au début du mois</a> une extension pour firebug qui permet de lister les événements ajoutés à un élément du DOM : <a href="http://github.com/remi/firebug-ujs/tree/master">firebugUJS</a>.</p>
<p>Son fonctionnement est simple : vous inspectez un élément comme d&#8217;habitude et vous choisissez dans la fenêtre de l&#8217;inspecteur de styles du menu HTML l&#8217;onglet <em>Events. </em>Le code du callback de l&#8217;événement y est alors présenté.</p>
<p><img src="/wp-content/uploads/2009/01/screen.jpg" alt="screenshot firebugUJS" /></p>
<h3>Limitations</h3>
<p>L&#8217;extension est encore à ses débuts de développement. Elle ne supporte pour l&#8217;instant principalement que <a href="http://jquery.com/">jQuery</a> et <a href="http://www.danwebb.net/2006/9/3/low-pro-unobtrusive-scripting-for-prototype">LowPro</a> (un effort pour rendre Prototype moins obstrusif).</p>
<p>Après une semaine d&#8217;essai, j&#8217;en suis relativement satisfait (relativement, parce que c&#8217;est donc un début et que je passe les problèmes pour cette raison). Cette extension m&#8217;a déjà permis de gagner du temps, mais il y a encore quelques petites choses à corriger. En particulier, les événements n&#8217;apparaissent parfois pas (il faut recharger la page une seconde fois), une quantité importante d&#8217;informations plus utiles au développeur de l&#8217;extension qu&#8217;à moi apparaissent dans la partie console de firebug (ce qui est tout à fait excusable) et surtout : il m&#8217;est déjà arrivé deux fois de devoir désactiver l&#8217;extension parce qu&#8217;elle faisait planter une application qui utilisait lourdement javascript (piwik la première fois, l&#8217;ajout d&#8217;image dans wordpress la seconde fois).</p>
<p>Malgré cela, je continue d&#8217;utiliser cette extension car je fais un usage intensif des événements js et qu&#8217;elle m&#8217;a déjà permis de gagner beaucoup de temps. Si ce n&#8217;est pas votre cas, vous voudrez probablement attendre une version plus stable.</p>
<p>Une affaire à suivre, donc :)</p>
 <img src="http://blog.olivier-elmekki.com/wp-content/plugins/feed-statistics.php?view=1&post_id=346" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://blog.olivier-elmekki.com/2009/01/25/debugger-les-evenements-js-avec-firebugujs/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Sortie de jQuery-1.3</title>
		<link>http://blog.olivier-elmekki.com/2009/01/14/sortie-de-jquery-13/</link>
		<comments>http://blog.olivier-elmekki.com/2009/01/14/sortie-de-jquery-13/#comments</comments>
		<pubDate>Wed, 14 Jan 2009 15:35:06 +0000</pubDate>
		<dc:creator>kik</dc:creator>
		
		<category><![CDATA[jquery]]></category>

		<guid isPermaLink="false">http://blog.olivier-elmekki.com/?p=341</guid>
		<description><![CDATA[jQuery-1.3 vient juste d&#8217;être publié. Une grande partie du travail a consisté à rendre jQuery encore plus rapide, notamment sur la sélection et l&#8217;injection de code HTML. Des progrès ont également été apportés dans le domaine de la compatibilité entre navigateurs (ce qui est en fait l&#8217;un des premiers objectifs d&#8217;un framework javascript).
Outre cela, il [...]]]></description>
			<content:encoded><![CDATA[<p>jQuery-1.3 vient juste <a href="http://blog.jquery.com/2009/01/14/jquery-13-and-the-jquery-foundation/">d&#8217;être publié</a>. Une grande partie du travail a consisté à rendre jQuery encore plus rapide, notamment sur la sélection et l&#8217;injection de code HTML. Des progrès ont également été apportés dans le domaine de la compatibilité entre navigateurs (ce qui est en fait l&#8217;un des premiers objectifs d&#8217;un framework javascript).</p>
<p>Outre cela, il y a deux changements majeurs à noter, sur lesquels je voudrais revenir : Sizzle et .live() .</p>
<p><span id="more-341"></span></p>
<h3>Le nouveau sélecteur Sizzle</h3>
<p>John Resig <a href="http://ajaxian.com/archives/sizzle-john-resig-has-a-new-selector-engine">nous avait déjà promis</a> un nouveau moteur de sélection, Sizzle. Il promettait qu&#8217;il serait environ quatre fois plus rapide que celui des autres frameworks. Si on en croit les <a href="http://docs.jquery.com/Release:jQuery_1.3">benchmarks publiés</a>, ce n&#8217;est bien sûr pas le cas mais il n&#8217;en reste pas moins que ce moteur est plus rapide que les autres (et même <em>beaucoup</em> plus rapide que ceux de Prototype et Mootools).</p>
<p>Mais si cela est intéressant en soi, il y a une autre surprise derrière Sizzle, relativement inatendue et qui me semble d&#8217;un grand intérêt : il est réalisé de manière indépendante à jQuery et un appel à été lancé aux développeurs des autres frameworks pour y contribuer.</p>
<p>Le but de Sizzle est donc à la fois d&#8217;être d&#8217;une performance sans égal et de faire converger les énergies (l&#8217;un entraînant l&#8217;autre et vice-versa). C&#8217;est une belle initiative, nous verrons ce que cela donnera. On peut soit s&#8217;attendre à une incompatibilité totale de points de vues, et ce ne sera que &#8220;le sélecteur de jQuery qui peut aussi être utilisé tout seul&#8221;, soit s&#8217;attendre à voir émerger de ceci un standard sur la sélection en javascript. Time will tell&#8230;</p>
<h3>Les Live events</h3>
<p>C&#8217;est ici, à mon avis, le changement le plus excitant. Ce n&#8217;est pas tout à fait révolutionnaire parce qu&#8217;il ne s&#8217;agit en fait que d&#8217;intégrer le plugin <a href="http://brandonaaron.net/docs/livequery/">Live Query</a> de <a href="http://blog.brandonaaron.net/">Brandon Aaron</a>. Néanmoins, l&#8217;intégrer dans le core de jQuery va permettre d&#8217;en faire une utilisation plus naturelle et systématique (et ne plus se poser la question : &#8220;est-ce que ça vaut le coup que j&#8217;intègre un plugin juste pour cette petite fonctionalité que je veux rajouter?&#8221;).</p>
<p>En quoi consiste ces live events? Lorsque vous attachez un événement, vous l&#8217;attachez à un élément du DOM. Il faut donc que cet élément existe. Considérons ce bout de code :</p>

<div class="wp_syntax"><div class="code"><pre class="javascript javascript" style="font-family:monospace;">$<span style="color: #009900;">&#40;</span> <span style="color: #3366CC;">'#menu li'</span> <span style="color: #009900;">&#41;</span>.<span style="color: #660066;">click</span><span style="color: #009900;">&#40;</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span> $<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">une_fonction</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>; <span style="color: #009900;">&#125;</span> <span style="color: #009900;">&#41;</span>;
$<span style="color: #009900;">&#40;</span> <span style="color: #3366CC;">'#menu'</span> <span style="color: #009900;">&#41;</span>.<span style="color: #660066;">append</span><span style="color: #009900;">&#40;</span> <span style="color: #3366CC;">'
	&lt;li&gt;nouvelle option&lt;/li&gt;
'</span> <span style="color: #009900;">&#41;</span>;</pre></div></div>

<p>Le nouveau li ici n&#8217;aura pas l&#8217;événement voulu attaché, seuls les autres executeront une_fonction() lorsqu&#8217;ils seront clickés.</p>
<p>Avec la fonction .live(), vous attachez l&#8217;événement non plus à un élément du DOM mais à un sélecteur (du moins, c&#8217;est l&#8217;impression donnée à l&#8217;usage, je passe l&#8217;implémentation technique). Ainsi, vous pouvez faire :</p>

<div class="wp_syntax"><div class="code"><pre class="javascript javascript" style="font-family:monospace;">$<span style="color: #009900;">&#40;</span> <span style="color: #3366CC;">'#menu li'</span> <span style="color: #009900;">&#41;</span>.<span style="color: #660066;">live</span><span style="color: #009900;">&#40;</span> <span style="color: #3366CC;">'click'</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span> $<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">une_fonction</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>; <span style="color: #009900;">&#125;</span> <span style="color: #009900;">&#41;</span>;
$<span style="color: #009900;">&#40;</span> <span style="color: #3366CC;">'#menu'</span> <span style="color: #009900;">&#41;</span>.<span style="color: #660066;">append</span><span style="color: #009900;">&#40;</span> <span style="color: #3366CC;">'
	&lt;li&gt;;nouvelle option&lt;/li&gt;
'</span> <span style="color: #009900;">&#41;</span>;</pre></div></div>

<p>Ici, le nouveau li répondra à l&#8217;événement défini. Pour annuler le live event, il suffit de passer .die() au même sélecteur. De plus, die() permet de choisir quel événement supprimer : tous, tous ceux qui correspondent à un type d&#8217;événement particulier ou encore tous ceux qui corespondent à une fonction particulière, soit :</p>

<div class="wp_syntax"><div class="code"><pre class="javascript javascript" style="font-family:monospace;">$<span style="color: #009900;">&#40;</span> <span style="color: #3366CC;">'#content .popup'</span> <span style="color: #009900;">&#41;</span>.<span style="color: #660066;">die</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> ;
$<span style="color: #009900;">&#40;</span> <span style="color: #3366CC;">'#content .popup'</span> <span style="color: #009900;">&#41;</span>.<span style="color: #660066;">die</span><span style="color: #009900;">&#40;</span> <span style="color: #3366CC;">'click'</span> <span style="color: #009900;">&#41;</span> ;
$<span style="color: #009900;">&#40;</span> <span style="color: #3366CC;">'#content .popup'</span> <span style="color: #009900;">&#41;</span>.<span style="color: #660066;">die</span><span style="color: #009900;">&#40;</span> <span style="color: #3366CC;">'click'</span><span style="color: #339933;">,</span> turnBackgroundDark <span style="color: #009900;">&#41;</span> ;</pre></div></div>

<p>La où cela devient vraiment intéressant, c&#8217;est quand on combine live() avec la puissance des sélecteurs. Ainsi, imaginons qu&#8217;on ait une liste d&#8217;utilisateurs, certains en-ligne et d&#8217;autres hors-ligne, avec des fonctions ajax qui vérifient si les utilisateurs arrivent ou partent et modifient leur status en conséquence. Nous voulons que l&#8217;utilisateur puisse démarrer une conversation avec les utilisateurs en ligne :</p>

<div class="wp_syntax"><div class="code"><pre class="javascript javascript" style="font-family:monospace;">$<span style="color: #009900;">&#40;</span> <span style="color: #3366CC;">'ul#users li:contains( '</span>en<span style="color: #339933;">-</span>ligne<span style="color: #3366CC;">' ) ).live( '</span>click<span style="color: #3366CC;">', function(){ startChat(this); } );</span></pre></div></div>

<p>L&#8217;événement click sera automatiquement ajouté et supprimé selon le status de l&#8217;utilisateur.</p>
 <img src="http://blog.olivier-elmekki.com/wp-content/plugins/feed-statistics.php?view=1&post_id=341" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://blog.olivier-elmekki.com/2009/01/14/sortie-de-jquery-13/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Typolight: Création de module backend pour gérer des ressources</title>
		<link>http://blog.olivier-elmekki.com/2009/01/06/typolight-creation-de-module-backend-pour-gerer-des-ressources/</link>
		<comments>http://blog.olivier-elmekki.com/2009/01/06/typolight-creation-de-module-backend-pour-gerer-des-ressources/#comments</comments>
		<pubDate>Tue, 06 Jan 2009 01:03:19 +0000</pubDate>
		<dc:creator>kik</dc:creator>
		
		<category><![CDATA[typolight]]></category>

		<guid isPermaLink="false">http://blog.olivier-elmekki.com/?p=299</guid>
		<description><![CDATA[La création d&#8217;une extension pour Typolight étant remplies de pièges et de problèmes inattendus, j&#8217;ai choisi de diviser les tutoriels sur la création d&#8217;un module backend en plusieurs éléments plus simples.
Dans ce tutoriel, nous verrons comment créer un module backend dans Typolight pour gérer des ressources simples. Par ressource, nous entendons une entité dotées d&#8217;attributs, [...]]]></description>
			<content:encoded><![CDATA[<p>La création d&#8217;une extension pour Typolight étant remplies de pièges et de problèmes inattendus, j&#8217;ai choisi de diviser les tutoriels sur la création d&#8217;un module backend en plusieurs éléments plus simples.</p>
<p>Dans ce tutoriel, nous verrons comment créer un module backend dans Typolight pour gérer des ressources simples. Par ressource, nous entendons une entité dotées d&#8217;attributs, stockées dans la base de donnée et avec laquelle l&#8217;application peut interagir. Les actions basiques que l&#8217;application peut accomplir sur ces ressources correspondent au paradigme CRUD : créer, lire, modifier, effacer. C&#8217;est précisément ces actions que recouvre un module backend.</p>
<p><span id="more-299"></span></p>
<p>Pré-requis:</p>
<ul>
<li>vous devez avoir des connaissances de base de PHP</li>
<li> vous devez avoir des connaissances de base de MySQL (ou du moteur de db que vous utilisez)</li>
<li> vous devez être à l&#8217;aise avec le fonctionnement de l&#8217;interface de Typolight</li>
</ul>
<p>Il est fortement recommandé que vous réalisiez les différentes étapes en même temps que votre lecture de ce tutoriel.</p>
<h3>Conception des ressources</h3>
<p>La première étape est de se représenter clairement les ressources qu&#8217;on va utiliser. Cela offre l&#8217;avantage de pouvoir utiliser l&#8217;interface de création de module de Typolight pour écrire automatiquement le squelette des fichiers.</p>
<p>Pour le tutoriel, nous prendrons l&#8217;exemple suivant.</p>
<p>Nous réalisons un site pour une entreprise disposant de plusieurs filiales. L&#8217;entreprise propose de multiples services, et chaque filiale propose quelques uns de ces services. Un service, par ailleurs, peut être proposé par plusieurs filiales. De services et des filiales peuvent apparaître ou disparaître. Une filiale peut voir sa liste de services proposés se modifier.</p>
<p>Ceux qui ont l&#8217;habitude de travailler sur des ressources auront repéré ici une relation <em>many_to_many</em> ( généralement réalisée grâce à une table de jointure ) entre les <em>filiales</em> et les <em>services</em>. On peut aussi y voir une relation <em>filiales</em> <em>has_many</em> <em>services</em>, et c&#8217;est ce que nous utiliserons, car <em>has_many</em> est mieux supporté par Typolight ( on pourra en outre par la suite pallier à cette insuffisance en utilisant les modèles ).</p>
<p>Pour ceux qui n&#8217;ont pas l&#8217;habitude de travailler sur les relations, cela signifie simplement qu&#8217;il faudra, dans notre base de donnée, un attribut de <em>filiales</em> permettant de lister les ids des services concernés (c&#8217;est ainsi que Typolight procède), ce qui s&#8217;exprime par : une filiale has many (a plusieurs) services.</p>
<p>Les autres attributs étant plus simples, nous pouvons nous représenter l&#8217;allure de nos ressources. Nous aurons donc deux types de ressources, <em>filiales</em> et <em>services</em> avec les attributs suivants :</p>
<p>Filiales :</p>
<ul>
<li> nom</li>
<li> adresse</li>
<li> ville</li>
<li> téléphone</li>
<li> mail</li>
<li> services</li>
</ul>
<p>Services :</p>
<ul>
<li> nom</li>
<li> description</li>
<li> tarif</li>
</ul>
<p>Cela nous suffit pour démarrer.</p>
<h3>Création automatique du squelette du module</h3>
<p>Afin de gagner du temps, nous utilisons le module &#8220;créateur de modules&#8221; présent dans la section &#8220;système&#8221; des menus de l&#8217;interface backend. Ce module permet de créer le squelette des fichiers dont vous aurez besoin par la suite.</p>
<p>Il est difficile de savoir exactement tous les fichiers dont on va avoir besoin, mais on peut ensuite dupliquer un fichier existant pour faire une nouvelle classe. Pour cette raison, je vous conseille de toujours créer un module frontend et les fichiers de langues, même si vous n&#8217;avez pour l&#8217;instant que la partie backend clairement en tête.</p>
<p>Une fois que vous avez renseigné les informations d&#8217;identification de l&#8217;extension, cochez &#8220;ajouter un module back-office&#8221;. Parmi les trois champs textes qui vous sont proposés, vous ne vous servirez la plupart du temps que du second.</p>
<p>Pour accélérer l&#8217;écriture d&#8217;un module backend, Typolight offre la possibilité d&#8217;utiliser des DCA ( Data Configuration Array ). Il s&#8217;agit en fait de tableaux PHP dont les différents éléments définissent la manière dont une table sql doit être représentée en back-office, et quelles opérations peuvent être réalisées dessus. Autrement dit : pour peu que vous traitiez des ressources, les DCA font tout le boulot.</p>
<p>Pour créer automatiquement les fichiers DCA relatifs à une table sql, et pour créer le fichier .sql de définition de cette table par la même occasion, donnez simplement le nom de cette table dans le champs &#8220;Tables du module back office&#8221; ( vous pouvez séparer plusieurs tables par des virgules ). Dans le cas de notre module, nous rentrons donc : &#8220;tl_filiere_services,tl_filiere_filiales&#8221;.</p>
<p>Le champs &#8220;Classes du module back office&#8221; permet de créer des modules écrit en PHP standard, si vous avez des besoins vraiment spécifiques que les DCA ne couvrent pas, ou si votre module n&#8217;implique pas des ressources. Le champs &#8220;Modèles du module back office&#8221; est utilisé pour créer les vues que ces modules emploieront ( généralement préfixé par &#8220;be_&#8221; ). Nous nous focalisons pour cette fois sur la gestion des ressources et nous n&#8217;avons donc pas besoin de ces deux champs, vous pouvez les laisser vide.</p>
<p>Comme précisé plus haut, nous allons aussi ajouter un module frontend, bien que nous ne nous en serviront pas pour l&#8217;instant. Le champs &#8220;Classes du module front office&#8221; concerne les contrôleurs. C&#8217;est généralement ce type de fichier qui concentre la plus grosse partie d&#8217;une extension. Les vues utilisées par ces contrôleurs sont définies dans &#8220;Modèles du module front office&#8221; ( il ne faut pas ici confondre le terme &#8220;modèle&#8221; avec le modèle de MVC, il s&#8217;agit en fait des vues ). Le champs &#8220;Tables du module front office&#8221; permet de lister des tables sql qui seront ajoutées dans la base de donnée, mais pour lesquelles des fichiers DCA ne seront pas créés. Nous créons donc, pour disposer ensuite du squelette, le contrôleur <em>FiliereFrontend</em> et la vue <em>fe_filiere</em>.</p>
<p>Une fois les informations de votre module complétées, sauvegarder et fermer, et créer les fichiers en cliquant sur l&#8217;icône correspondante.</p>
<h3>Création de la déclaration SQL</h3>
<p>Vous disposez maintenant des fichiers nécessaires, installés dans <em>system/modules/</em>. Nous allons commencer par nous occuper de la définition sql de nos ressources. Cela se fait dans le fichier <em>config/database.sql</em> du module.</p>
<p>Les champs `pid` et `sorting`, parmi les champs ajoutés automatiquement, ne nous serviront pas. Le premier sert à contenir l&#8217;id du parent, dans les relations de type <em>belongs to</em>. Le second est utilisé lorsque l&#8217;utilisateur doit pouvoir définir un ordre arbitraire, comme dans le cas des éléments de contenus ou des articles. Nous pouvons donc supprimer ces deux champs dans les deux déclarations (n&#8217;oubliez pas de supprimer la clef pid aussi).</p>
<p>Le champs `tstamp` est automatiquement mis à jour lorsque vous sauvegardez une ressource, avant de pouvoir retrouver la date de dernière modification. Il peut être utile de rajouter par ailleurs un champs `created_at`.</p>
<p>Nous pouvons maintenant commencer à ajouter nos propres champs.</p>
<p style="padding-left: 30px;"><em>Attention tricky</em> : lorsque vous éditez les déclarations de table. Le script <em>install.php</em> est assez exigeant sur leur formatage. Si vous mettez des espaces en trop ou en moins, il continuera de vous dire obstinément que la base de donnée n&#8217;est pas à jour quand même elle le sera.</p>
<p>Vous devez déjà également vous faire une idée de quel type d&#8217;élément de formulaire concernera le champs. Voici quelques exemples :</p>
<pre>input type text,
chemin de fichier:          varchar(255) NOT NULL default '',
textarea:                   text NULL,
checkbox:                   char(1) NOT NULL default '',
liste de checkboxes,
select multiple,
liste de input type text:   blob NULL,
date:                       int(10) unsigned NOT NULL default '0'
                            (les dates sont stockées sous forme de timestamp unix)</pre>
<p>En reprenant la description des ressources que nous avons vue dans la première partie de ce tutoriel, les définitions sql seront donc :</p>

<div class="wp_syntax"><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
</pre></td><td class="code"><pre class="sql sql" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">--</span>
<span style="color: #808080; font-style: italic;">-- Table `tl_filiere_services`</span>
<span style="color: #808080; font-style: italic;">-- </span>
&nbsp;
<span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">TABLE</span> <span style="color: #ff0000;">`tl_filiere_services`</span> <span style="color: #66cc66;">&#40;</span>
  <span style="color: #ff0000;">`id`</span> int<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">10</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">UNSIGNED</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span> <span style="color: #993333; font-weight: bold;">AUTO_INCREMENT</span><span style="color: #66cc66;">,</span>
  <span style="color: #ff0000;">`tstamp`</span> int<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">10</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">UNSIGNED</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span> <span style="color: #993333; font-weight: bold;">DEFAULT</span> <span style="color: #ff0000;">'0'</span><span style="color: #66cc66;">,</span>
  <span style="color: #ff0000;">`name`</span> varchar<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">255</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span> <span style="color: #993333; font-weight: bold;">DEFAULT</span> <span style="color: #ff0000;">''</span><span style="color: #66cc66;">,</span>
  <span style="color: #ff0000;">`description`</span> text <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span>
  <span style="color: #ff0000;">`price`</span> varchar<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">255</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span> <span style="color: #993333; font-weight: bold;">DEFAULT</span> <span style="color: #ff0000;">''</span><span style="color: #66cc66;">,</span>
  <span style="color: #993333; font-weight: bold;">PRIMARY</span> <span style="color: #993333; font-weight: bold;">KEY</span>  <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">`id`</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#41;</span> ENGINE<span style="color: #66cc66;">=</span>MyISAM <span style="color: #993333; font-weight: bold;">DEFAULT</span> CHARSET<span style="color: #66cc66;">=</span>utf8;
&nbsp;
<span style="color: #808080; font-style: italic;">-- --------------------------------------------------------</span>
&nbsp;
<span style="color: #808080; font-style: italic;">--</span>
<span style="color: #808080; font-style: italic;">-- Table `tl_filiere_filiales`</span>
<span style="color: #808080; font-style: italic;">-- </span>
&nbsp;
<span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">TABLE</span> <span style="color: #ff0000;">`tl_filiere_filiales`</span> <span style="color: #66cc66;">&#40;</span>
  <span style="color: #ff0000;">`id`</span> int<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">10</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">UNSIGNED</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span> <span style="color: #993333; font-weight: bold;">AUTO_INCREMENT</span><span style="color: #66cc66;">,</span>
  <span style="color: #ff0000;">`tstamp`</span> int<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">10</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">UNSIGNED</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span> <span style="color: #993333; font-weight: bold;">DEFAULT</span> <span style="color: #ff0000;">'0'</span><span style="color: #66cc66;">,</span>
  <span style="color: #ff0000;">`name`</span> varchar<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">255</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span> <span style="color: #993333; font-weight: bold;">DEFAULT</span> <span style="color: #ff0000;">''</span><span style="color: #66cc66;">,</span>
  <span style="color: #ff0000;">`city`</span> varchar<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">255</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span> <span style="color: #993333; font-weight: bold;">DEFAULT</span> <span style="color: #ff0000;">''</span><span style="color: #66cc66;">,</span>
  <span style="color: #ff0000;">`phone`</span> varchar<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">255</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span> <span style="color: #993333; font-weight: bold;">DEFAULT</span> <span style="color: #ff0000;">''</span><span style="color: #66cc66;">,</span>
  <span style="color: #ff0000;">`email`</span> varchar<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">255</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span> <span style="color: #993333; font-weight: bold;">DEFAULT</span> <span style="color: #ff0000;">''</span><span style="color: #66cc66;">,</span>
  <span style="color: #ff0000;">`services`</span> blob <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span>
  <span style="color: #993333; font-weight: bold;">PRIMARY</span> <span style="color: #993333; font-weight: bold;">KEY</span>  <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">`id`</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#41;</span> ENGINE<span style="color: #66cc66;">=</span>MyISAM <span style="color: #993333; font-weight: bold;">DEFAULT</span> CHARSET<span style="color: #66cc66;">=</span>utf8;</pre></td></tr></table></div>

<h3>Le DCA</h3>
<p>C&#8217;est ici que se fait la plus grosse partie du travail, dans le DCA des tables. Nous allons commencer par nous occuper du DCA de <em>tl_filiere_filiales</em>.</p>
<p>Un DCA est un énorme tableau PHP, composé de nombreux tableaux imbriqués ( ça vous rappelle des souvenirs? :) ). L&#8217;avantage majeure est de permettre de créer des modules très rapidement. L&#8217;inconvénient majeur est d&#8217;être particulièrement indébugable. La plupart du temps, une erreur dans le DCA se traduit par une erreur dans la classe <em>DC_Table</em> ou (pire encore) par rien du tout, sinon que &#8220;ça ne marche pas&#8221;, et les logs restent muets sur le problème. J&#8217;ai pris l&#8217;habitude de dire : &#8220;le truc génial dans les modules Typolight, c&#8217;est les DCA. Le truc horrible dans les modules Typolight, c&#8217;est les DCA.&#8221;. Dans les premiers temps, les DCA vous feront perdre plus de temps qu&#8217;en gagner, mais je trouve personnellement que ça en vaut la peine, tant tout est facilité une fois qu&#8217;on les a en main. Pour faire ses armes avec les DCA, le mieux à faire et de bien prendre soin de les générer par le créateur de module et de se référer aux nombreux DCA présents dans <em>system/modules/backend/dca</em> pour avoir des points de comparaison. Vous réaliserez bientôt à quel point Typolight est une application exigeante lorsqu&#8217;il s&#8217;agit de développer avec.</p>
<p>Vous trouverez des informations fort utiles dans <a href="http://dev.typolight.org/wiki/DevelopmentIndex">la section développement de la documentation</a> de Typolight ( en anglais ).</p>
<p>Voici une explication générale des principales clefs de premier niveau d&#8217;un DCA :<br />
<em>config</em>: les options générales du module. De nombreux options différentes y sont regroupées : la détermination des tables parent et enfants, les callbacks lors des actions destructives sur les ressources, les limitations de ces opérations, etc.<br />
<em>list</em>: la manières dont les ressources seront listées ( affichage de l&#8217;ensemble des ressources ). Selon quel(s) attribut(s) on les classe? Est-ce que c&#8217;est une simple liste? Un arbre? Quelles informations pour chaque ressource apparaissent dans cette liste? Quelles actions peuvent être exécutées? Y a-t-il un panneau de navigation? Si oui, que propose-t-il?<br />
<em>palettes,subpalettes</em>: ces options concernent plus particulièrement la gestion d&#8217;une ressource isolée. Quels sont les différents champs qui seront éditables, et dans quel ordre seront-ils disposés? Certains champs ne doivent apparaître que si un autre champs a une valeur précise (on ne modifie pas la source d&#8217;un fichier si on n&#8217;a pas coché &#8220;ajouter un fichier&#8221;). Les subpalettes permettent de déterminer ces sections annexes du formulaire.<br />
<em>fields</em>: le coeur du DCA. Si &#8216;palettes&#8217; décident quels champs apparaîtront, &#8216;fields&#8217; décide ce que seront ces champs. Un <em>textarea</em>? Un <em>input text</em>? Une liste de <em>checkboxes</em>?</p>
<p>Plusieurs options dans les DCA permettent de fournir les données en passant une fonction, sous la forme d&#8217;un tableau <em>array( &#8216;classe&#8217;, &#8216;méthode&#8217; )</em>. Bien que la classe appelée puisse être n&#8217;importe quelle classe accessible à l&#8217;application, il est d&#8217;usage de rajouter une classe directement dans le fichier du DCA, en lui donnant le nom de la table sql concernée et en la faisant hériter de <em>Backend</em>. Cela fait particulièrement sens si la méthode en question n&#8217;est vraiment utile que dans le cadre du DCA, comme par exemple les méthodes servant à déterminer les informations présentées dans la liste des ressources.</p>
<h3>Détermination des palettes</h3>
<p>Puisque nous avons déjà commencé à penser les éléments de formulaires liés aux champs, nous allons commencer par la clef &#8216;palettes&#8217; et la clef &#8216;fields&#8217;. Si vous comptez faire d&#8217;importantes modifications dans &#8216;config&#8217; et &#8216;list&#8217;, leurs valeurs par défaut vous permettrons quand même de tester &#8216;fields&#8217;.</p>
<p>Le tableau de la clef  &#8216;palettes&#8217; doit au moins comporter une clef &#8216;default&#8217;. Sa valeur est une chaîne de caractères représentant dans l&#8217;ordre les différents champs qui seront présentés, en utilisant le nom du champs dans la base de données. Dans notre DCA de <em>tl_filiere_services</em>, nous auront donc : &#8216;name;description,price;&#8217;. Les noms de champs peuvent être séparés par des virgules ou des points virgules. La différence est que le point virgule sépare des groupes, en traçant une ligne. C&#8217;est une notation qu&#8217;on retrouvera plusieurs fois dans Typolight.</p>
<p>Outre la clef &#8216;default&#8217;, il peut y avoir également une clef &#8216;__selector__&#8217;. Les selectors servent à modifier dynamiquement le formulaire de la ressource, selon les champs déclarés dans le tableau fourni en valeur de cette clef. Il y a deux types valides de sélecteurs : ceux dont le champs est représenté par une checkbox et les autres. Le sélecteur par checkbox sera une subpalette, le sélecteur normal sera plusieurs nouvelles palettes.</p>
<p>Dans le premier cas, le sélecteur est associé à une subpalette, qui liste les éléments à rajouter. Dans le second cas, une palette est ajoutée pour chaque valeur que peut prendre le champs concerné. Il est en outre possible de faire des palettes propres à plusieurs sélecteurs string en donnant au nom de la palette la liste des valeurs concaténées, comme par exemple la palette &#8220;flashexternal&#8221; de tl_module, pour type =&gt; flash et source =&gt; external. C&#8217;est assez complexe, mais on ne s&#8217;en sert heureusement pratiquement jamais.</p>
<p>Bien souvent, la seule palette &#8220;default&#8221; suffit, et c&#8217;est d&#8217;ailleurs ce que nous allons utiliser. Nous pouvons supprimer la clef &#8220;subpalettes&#8221;. La clef &#8220;palettes&#8221;, elle, devient :</p>

<div class="wp_syntax"><div class="code"><pre class="php php" style="font-family:monospace;"><span style="">'palettes'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span>
<span style="color: #009900;">&#40;</span>
  <span style="">'default'</span> <span style="color: #339933;">=&gt;</span> <span style="">'name;description,price;'</span>
<span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span></pre></div></div>

<h3>Définition des champs</h3>
<p>Nous avons donc ici trois champs à définir. Chaque champs est défini par un tableau associatif dont la clef la plus importante est &#8216;inputType&#8217;. Vous trouverez une liste des clefs utilisables dans la <a href="http://dev.typolight.org/wiki/DevelopmentFields">documentation pour développeurs</a>. Encore une fois, vous êtes fortement invités à aller voir les DCA déjà existants pour vous en inspirer.</p>
<p>La clef &#8216;label&#8217; servira à déterminer, dans les fichiers de langue, le texte présenté comme nom du champs et la description qui en est faite si l&#8217;utilisateur backend est en mode <em>explain</em>.</p>
<p>La clef &#8216;exclude&#8217; permet de désactiver par défaut le champs pour les non-administrateurs. Il faut manuellement leur définir des droits pour ce champs pour qu&#8217;ils puissent le modifier. C&#8217;est une bonne pratique que de définir cette propriété sur tous les champs, pour être sûr que la base de donnée ne soit pas accessible involontairement.</p>
<p>La clef &#8216;inputType&#8217; définit quel type d&#8217;élément de formulaire sera utilisé. Les éléments de formulaire appartiennent à la classe <em>Widget</em>. Vous pouvez utiliser tous ceux qui sont déjà définis dans d&#8217;autres modules ( notamment dans <em>system/modules/backend</em> ) ou en créer vous même. Les &#8216;inputTypes&#8217; les plus fréquents sont : &#8216;text&#8217;, &#8216;textarea&#8217;, &#8217;select&#8217;, &#8216;checkbox&#8217;, &#8216;radio&#8217;&#8230;</p>
<p>La clef &#8216;eval&#8217; permet de préciser le fonctionnement du widget. On peut aussi passer l&#8217;option &#8220;mandatory&#8221; pour rendre le champs obligatoire, l&#8217;option &#8220;rte&#8221; pour rajouter un éditeur wysiwyg sur un textarea, &#8220;rgxp&#8221; pour valider un champs text selon une expression régulière ( malheureusement prédéfinie ), etc. Vous trouverez une liste des options possible ici : <em>http://dev.typolight.org/wiki/DevelopmentEvaluation</em> .</p>
<p>Voici ce que nous aurons pour tl_filiere_services</p>

<div class="wp_syntax"><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="code"><pre class="php php" style="font-family:monospace;"><span style="">'fields'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span>
<span style="color: #009900;">&#40;</span>
  <span style="">'name'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span>
  <span style="color: #009900;">&#40;</span>
    <span style="">'label'</span>        <span style="color: #339933;">=&gt;</span> <span style="color: #339933;">&amp;</span><span style="color: #000088;">$GLOBALS</span><span style="color: #009900;">&#91;</span><span style="">'TL_LANG'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'tl_filiere_services'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'name'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span>
    <span style="">'exclude'</span>      <span style="color: #339933;">=&gt;</span> <span style="color: #000000; font-weight: bold;">true</span><span style="color: #339933;">,</span>
    <span style="">'inputType'</span>    <span style="color: #339933;">=&gt;</span> <span style="">'text'</span><span style="color: #339933;">,</span>
    <span style="">'eval'</span>         <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="">'mandatory'</span><span style="color: #339933;">=&gt;</span>true<span style="color: #339933;">,</span> <span style="">'maxlength'</span><span style="color: #339933;">=&gt;</span><span style="color: #cc66cc;">255</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
  <span style="">'description'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span>
  <span style="color: #009900;">&#40;</span>
    <span style="">'label'</span>        <span style="color: #339933;">=&gt;</span> <span style="color: #339933;">&amp;</span><span style="color: #000088;">$GLOBALS</span><span style="color: #009900;">&#91;</span><span style="">'TL_LANG'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'tl_filiere_services'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'description'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span>
    <span style="">'exclude'</span>      <span style="color: #339933;">=&gt;</span> <span style="color: #000000; font-weight: bold;">true</span><span style="color: #339933;">,</span>
    <span style="">'inputType'</span>    <span style="color: #339933;">=&gt;</span> <span style="">'textarea'</span><span style="color: #339933;">,</span>
    <span style="">'eval'</span>         <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="">'rte'</span> <span style="color: #339933;">=&gt;</span> <span style="">'tinyMCE'</span> <span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
  <span style="">'price'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span>
  <span style="color: #009900;">&#40;</span>
    <span style="">'label'</span>        <span style="color: #339933;">=&gt;</span> <span style="color: #339933;">&amp;</span><span style="color: #000088;">$GLOBALS</span><span style="color: #009900;">&#91;</span><span style="">'TL_LANG'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'tl_filiere_services'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'price'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span>
    <span style="">'exclude'</span>      <span style="color: #339933;">=&gt;</span> <span style="color: #000000; font-weight: bold;">true</span><span style="color: #339933;">,</span>
    <span style="">'inputType'</span>    <span style="color: #339933;">=&gt;</span> <span style="">'text'</span><span style="color: #339933;">,</span>
    <span style="">'eval'</span>         <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="">'mandatory'</span><span style="color: #339933;">=&gt;</span>true<span style="color: #339933;">,</span> <span style="">'maxlength'</span><span style="color: #339933;">=&gt;</span><span style="color: #cc66cc;">255</span><span style="color: #339933;">,</span> <span style="">'rgxp'</span> <span style="color: #339933;">=&gt;</span> <span style="">'digit'</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#41;</span></pre></td></tr></table></div>

<p>&#8216;name&#8217; est donc un input de type text, obligatoire avec 255 caractères maximum, &#8216;description&#8217; est un textarea avec un éditeur wysiwyg et price est un input de type text, obligatoire, de 255 caractères maximum composés uniquement de chiffres.</p>
<h3>Premiers tests, config.php</h3>
<p>À ce point, il est bon de s&#8217;assurer que tout fonctionne correctement. Commencez par lancer <em>install.php</em> pour mettre à jour la base de donnée.</p>
<p>Pour activer un module, il faut le charger dans le tableau de configuration globale par l&#8217;intermédiaire de <em>config/config.php</em> . Nous voulons pour l&#8217;instant juste tester le module backend de <em>tl_filiere_services</em>, nous rajoutons donc une entrée à $GLOBALS[ 'BE_MOD' ] dans la catégorie &#8216;content&#8217; ( cela aura pour effet de faire apparaître le module dans la section &#8220;contenu&#8221; de la sidebar du backend ).</p>

<div class="wp_syntax"><div class="code"><pre class="php php" style="font-family:monospace;"><span style="color: #000088;">$GLOBALS</span><span style="color: #009900;">&#91;</span> <span style="">'BE_MOD'</span> <span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span> <span style="">'content'</span> <span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span> <span style="">'tl_filiere_services'</span> <span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
  <span style="">'tables'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span> <span style="">'tl_filiere_services'</span> <span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#41;</span>;</pre></div></div>

<p>Le fait d&#8217;utiliser la clef &#8216;tables&#8217; stipule que nous allons utiliser des DCA. La valeur est un tableau pour qu&#8217;il soit possible de préciser plusieurs tables dans le cas d&#8217;une présentation sous la forme parent/enfants.</p>
<p>D&#8217;autres options peuvent être précisées, comme vous le voyez dans les commentaires du fichier créé automatiquement. &#8216;icon&#8217; est le chemin de l&#8217;icône qui sera utilisé à côté du lien dans la sidebar du backend, &#8217;stylesheet&#8217; et &#8216;javascript&#8217; permettent de rajouter des styles et scripts persos. &#8216;callback&#8217; permet de définir la classe de module backend qui sera utilisé lorsqu&#8217;on décide de faire un module sans DCA et &#8216;key&#8217; permet de rajouter ses actions personnalisées ( l&#8217;équivalent de ['list']['operations'] dans un DCA ) si on veut utiliser autre chose que le CRUD par défaut.</p>
<p>Nous pouvons maintenant faire un premier test, en nous rendant dans l&#8217;interface backend. Si tout se passe bien, vous voyez apparaître &#8220;tl_filiere_services&#8221; dans la section &#8220;contenu&#8221; de la sidebar. Nous donnerons un nom plus correct en utilisant les fichiers de langues. De même, dans la liste des ressources, le bouton &#8220;nouveau&#8221; n&#8217;a pas de label. Cela sera déterminé également dans les fichiers de langues, nous allons nous contenter de vérifier pour l&#8217;instant que le CRUD fonctionne correctement.</p>
<p>Créez quelques ressources, éditez-les, effacez-les. Puis passez à la suite quand vous serez assuré que tout fonctionne.</p>
<h3>Paramétrage général du DCA</h3>
<p>Nous allons ensuite revenir sur le fichier DCA de <em>tl_filiere_services</em>. Nos ressources étant relativement simples, nous n&#8217;avons pas besoin de rajouter quoi que ce soit dans &#8216;config&#8217;. Au pire, vous aurez besoin des callbacks. Il s&#8217;agit de tableau à deux entrées, classe et méthode, qui seront appelé lors d&#8217;événements particuliers ( save, delete, load ). Cela peut être utile si par exemple vous voulez vous assurer qu&#8217;une url est atteignable lorsque vous la sauvegardez, ou encore que vous voulez effacer un fichier uploadé propre à la ressource lorsque vous l&#8217;effacez. Les autres options, pour la plupart, concernent les relations parent/enfant ou à des besoins très spécifiques et rares ( je vous laisse vous référer au guide du développeur pour des informations complètes ).</p>
<p>La clef &#8216;list&#8217; est la seconde clef la plus important du DCA. Elle vous permet de définir comment la liste des ressources sera présentée. &#8217;sorting&#8217; et &#8216;label&#8217; sont d&#8217;une importance cruciale pour cela. &#8216;global_operations&#8217; et &#8216;operations&#8217; n&#8217;ont la plupart du temps pas à être changée, et offrent les actions classiques de CRUD.</p>
<p>vous trouverez la documentation de la clef &#8216;list&#8217; <a href="http://dev.typolight.org/wiki/DevelopmentListing">ici</a> :</p>
<p>&#8217;sorting&#8217; sert à déterminer comment les ressources seront classées. Le mode permet de choisir si les ressources seront simplement placées les unes à la suite des autres, ou par groupe selon leur parent, ou par une ordre défini par l&#8217;utilisateur (requiert le champs &#8217;sorting&#8217; dans la table) ou encore sous forme d&#8217;arbre&#8230;</p>
<p>&#8216;flag&#8217; permet de définir un second niveau de classement : ascendant, descendant, alphabétique, par date&#8230; Le classement sera effectué sur le ou les champs indiqués dans le array de la clef &#8216;fields&#8217;.</p>
<p>Si vous désirez ajouter un panneau de navigation, c&#8217;est également ici que cela se fait ( un exemple de ceci sera donnée dans le DCA de <em>tl_filiere_filiales </em>).</p>
<p>La clef &#8216;label&#8217; permet de déterminer quelles informations seront présentées pour chaque ressource dans la liste des ressources. Les champs montrés seront déterminés par &#8216;fields&#8217; et leur formatage sera déterminé par &#8216;format&#8217;, qui prend le même type de string que <em>printf()</em>. Si vous désirez quelque chose de plus complexe, en particulier si vous avez besoin de manipuler les données des champs plutôt que de les afficher tels quels, vous pouvez utiliser un callback avec &#8216;label_callback&#8217;. La méthode utilisées devra renvoyer un string, qui sera ajouté à la suite du texte déjà fourni par format et fields, si précisé.</p>
<p style="padding-left: 30px;"><em>tip</em>: Si vous devez fournir beaucoup de contenu, vous pouvez limiter la taille d&#8217;un block en lui donnant comme classes limit_height et hN, où N est la hauteur en pixel. Cela aura pour effet de mettre une flèche clickable pour afficher l&#8217;ensemble du contenu et de le réduire à la taille choisi par défaut.</p>
<p>Dans notre cas, nous allons classer les services par ordre alphabétique en montrant simplement leur nom. Étant donné que les services ont peu d&#8217;informations et que celles-ci sont relativement uniques, nous n&#8217;avons pas vraiment besoin de l&#8217;opération &#8220;copy&#8221; et nous la supprimons donc.</p>
<p>Voici donc notre DCA au final :</p>

<div class="wp_syntax"><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
83
84
85
86
87
88
89
</pre></td><td class="code"><pre class="php php" style="font-family:monospace;"><span style="color: #000088;">$GLOBALS</span><span style="color: #009900;">&#91;</span><span style="">'TL_DCA'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'tl_filiere_services'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span>
<span style="color: #009900;">&#40;</span>
  <span style="color: #666666; font-style: italic;">// Config</span>
  <span style="">'config'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span>
  <span style="color: #009900;">&#40;</span>
    <span style="">'dataContainer'</span>    <span style="color: #339933;">=&gt;</span> <span style="">'Table'</span><span style="color: #339933;">,</span>
    <span style="">'enableVersioning'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000000; font-weight: bold;">true</span>
  <span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
&nbsp;
  <span style="color: #666666; font-style: italic;">// List</span>
  <span style="">'list'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span>
  <span style="color: #009900;">&#40;</span>
    <span style="">'sorting'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span>
    <span style="color: #009900;">&#40;</span>
      <span style="">'mode'</span>    <span style="color: #339933;">=&gt;</span> <span style="color: #cc66cc;">1</span><span style="color: #339933;">,</span>
      <span style="">'fields'</span>  <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="">'name'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
      <span style="">'flag'</span>    <span style="color: #339933;">=&gt;</span> <span style="color: #cc66cc;">1</span>
    <span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
    <span style="">'label'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span>
    <span style="color: #009900;">&#40;</span>
      <span style="">'fields'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="">'name'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
      <span style="">'format'</span> <span style="color: #339933;">=&gt;</span> <span style="">'%s'</span>
    <span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
    <span style="">'global_operations'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span>
    <span style="color: #009900;">&#40;</span>
      <span style="">'all'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span>
      <span style="color: #009900;">&#40;</span>
        <span style="">'label'</span>       <span style="color: #339933;">=&gt;</span> <span style="color: #339933;">&amp;</span><span style="color: #000088;">$GLOBALS</span><span style="color: #009900;">&#91;</span><span style="">'TL_LANG'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'MSC'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'all'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span>
        <span style="">'href'</span>        <span style="color: #339933;">=&gt;</span> <span style="">'act=select'</span><span style="color: #339933;">,</span>
        <span style="">'class'</span>       <span style="color: #339933;">=&gt;</span> <span style="">'header_edit_all'</span><span style="color: #339933;">,</span>
        <span style="">'attributes'</span>  <span style="color: #339933;">=&gt;</span> <span style="">'onclick=&quot;Backend.getScrollOffset();&quot;'</span>
      <span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
    <span style="">'operations'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span>
    <span style="color: #009900;">&#40;</span>
      <span style="">'edit'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span>
      <span style="color: #009900;">&#40;</span>
        <span style="">'label'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #339933;">&amp;</span><span style="color: #000088;">$GLOBALS</span><span style="color: #009900;">&#91;</span><span style="">'TL_LANG'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'tl_filiere_services'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'edit'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span>
        <span style="">'href'</span>  <span style="color: #339933;">=&gt;</span> <span style="">'act=edit'</span><span style="color: #339933;">,</span>
        <span style="">'icon'</span>  <span style="color: #339933;">=&gt;</span> <span style="">'edit.gif'</span>
      <span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
      <span style="">'delete'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span>
      <span style="color: #009900;">&#40;</span>
        <span style="">'label'</span>       <span style="color: #339933;">=&gt;</span> <span style="color: #339933;">&amp;</span><span style="color: #000088;">$GLOBALS</span><span style="color: #009900;">&#91;</span><span style="">'TL_LANG'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'tl_filiere_services'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'delete'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span>
        <span style="">'href'</span>        <span style="color: #339933;">=&gt;</span> <span style="">'act=delete'</span><span style="color: #339933;">,</span>
        <span style="">'icon'</span>        <span style="color: #339933;">=&gt;</span> <span style="">'delete.gif'</span><span style="color: #339933;">,</span>
        <span style="">'attributes'</span>  <span style="color: #339933;">=&gt;</span> <span style="">'onclick=&quot;if (!confirm(<span style="">\'</span>'</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$GLOBALS</span><span style="color: #009900;">&#91;</span><span style="">'TL_LANG'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'MSC'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'deleteConfirm'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">.</span> <span style="">'<span style="">\'</span>)) return false; Backend.getScrollOffset();&quot;'</span>
      <span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
      <span style="">'show'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span>
      <span style="color: #009900;">&#40;</span>
        <span style="">'label'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #339933;">&amp;</span><span style="color: #000088;">$GLOBALS</span><span style="color: #009900;">&#91;</span><span style="">'TL_LANG'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'tl_filiere_services'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'show'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span>
        <span style="">'href'</span>  <span style="color: #339933;">=&gt;</span> <span style="">'act=show'</span><span style="color: #339933;">,</span>
        <span style="">'icon'</span>  <span style="color: #339933;">=&gt;</span> <span style="">'show.gif'</span>
      <span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
&nbsp;
  <span style="color: #666666; font-style: italic;">// Palettes</span>
  <span style="">'palettes'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span>
  <span style="color: #009900;">&#40;</span>
    <span style="">'default'</span> <span style="color: #339933;">=&gt;</span> <span style="">'name;description,price;'</span>
  <span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
&nbsp;
  <span style="color: #666666; font-style: italic;">// Fields</span>
  <span style="">'fields'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span>
  <span style="color: #009900;">&#40;</span>
    <span style="">'name'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span>
    <span style="color: #009900;">&#40;</span>
      <span style="">'label'</span>       <span style="color: #339933;">=&gt;</span> <span style="color: #339933;">&amp;</span><span style="color: #000088;">$GLOBALS</span><span style="color: #009900;">&#91;</span><span style="">'TL_LANG'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'tl_filiere_services'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'name'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span>
      <span style="">'exclude'</span>     <span style="color: #339933;">=&gt;</span> <span style="color: #000000; font-weight: bold;">true</span><span style="color: #339933;">,</span>
      <span style="">'inputType'</span>   <span style="color: #339933;">=&gt;</span> <span style="">'text'</span><span style="color: #339933;">,</span>
      <span style="">'eval'</span>        <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="">'mandatory'</span><span style="color: #339933;">=&gt;</span>true<span style="color: #339933;">,</span> <span style="">'maxlength'</span><span style="color: #339933;">=&gt;</span><span style="color: #cc66cc;">255</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
    <span style="">'description'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span>
    <span style="color: #009900;">&#40;</span>
      <span style="">'label'</span>      <span style="color: #339933;">=&gt;</span> <span style="color: #339933;">&amp;</span><span style="color: #000088;">$GLOBALS</span><span style="color: #009900;">&#91;</span><span style="">'TL_LANG'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'tl_filiere_services'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'description'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span>
      <span style="">'exclude'</span>    <span style="color: #339933;">=&gt;</span> <span style="color: #000000; font-weight: bold;">true</span><span style="color: #339933;">,</span>
      <span style="">'inputType'</span>  <span style="color: #339933;">=&gt;</span> <span style="">'textarea'</span><span style="color: #339933;">,</span>
      <span style="">'eval'</span>       <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="">'rte'</span> <span style="color: #339933;">=&gt;</span> <span style="">'tinyMCE'</span> <span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
    <span style="">'price'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span>
    <span style="color: #009900;">&#40;</span>
      <span style="">'label'</span>      <span style="color: #339933;">=&gt;</span> <span style="color: #339933;">&amp;</span><span style="color: #000088;">$GLOBALS</span><span style="color: #009900;">&#91;</span><span style="">'TL_LANG'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'tl_filiere_services'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'price'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span>
      <span style="">'exclude'</span>    <span style="color: #339933;">=&gt;</span> <span style="color: #000000; font-weight: bold;">true</span><span style="color: #339933;">,</span>
      <span style="">'inputType'</span>  <span style="color: #339933;">=&gt;</span> <span style="">'text'</span><span style="color: #339933;">,</span>
      <span style="">'eval'</span>       <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="">'maxlength'</span><span style="color: #339933;">=&gt;</span><span style="color: #cc66cc;">255</span><span style="color: #339933;">,</span> <span style="">'rgxp'</span> <span style="color: #339933;">=&gt;</span> <span style="">'digit'</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#41;</span>;</pre></td></tr></table></div>

<h3>tl_filiere_filiales</h3>
<p>Nous allons maintenant pouvoir nous occuper du DCA de <em>tl_filiere_filiales</em> :</p>

<div class="wp_syntax"><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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
</pre></td><td class="code"><pre class="php php" style="font-family:monospace;"><span style="color: #000088;">$GLOBALS</span><span style="color: #009900;">&#91;</span><span style="">'TL_DCA'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'tl_filiere_filiales'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span>
<span style="color: #009900;">&#40;</span>
  <span style="color: #666666; font-style: italic;">// Config</span>
  <span style="">'config'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span>
  <span style="color: #009900;">&#40;</span>
    <span style="">'dataContainer'</span>    <span style="color: #339933;">=&gt;</span> <span style="">'Table'</span><span style="color: #339933;">,</span>
    <span style="">'enableVersioning'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000000; font-weight: bold;">true</span>
  <span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
&nbsp;
  <span style="color: #666666; font-style: italic;">// List</span>
  <span style="">'list'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span>
  <span style="color: #009900;">&#40;</span>
    <span style="">'sorting'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span>
    <span style="color: #009900;">&#40;</span>
      <span style="">'mode'</span>        <span style="color: #339933;">=&gt;</span> <span style="color: #cc66cc;">1</span><span style="color: #339933;">,</span>
      <span style="">'fields'</span>      <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="">'name'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
      <span style="">'flag'</span>        <span style="color: #339933;">=&gt;</span> <span style="color: #cc66cc;">1</span><span style="color: #339933;">,</span>
      <span style="">'panelLayout'</span> <span style="color: #339933;">=&gt;</span> <span style="">'filter,search,limit;'</span>
    <span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
    <span style="">'label'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span>
    <span style="color: #009900;">&#40;</span>
      <span style="">'fields'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="">'name'</span><span style="color: #339933;">,</span> <span style="">'city'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
      <span style="">'format'</span> <span style="color: #339933;">=&gt;</span> <span style="">'%s @ %s'</span>
    <span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
    <span style="">'global_operations'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span>
    <span style="color: #009900;">&#40;</span>
      <span style="">'all'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span>
      <span style="color: #009900;">&#40;</span>
        <span style="">'label'</span>       <span style="color: #339933;">=&gt;</span> <span style="color: #339933;">&amp;</span><span style="color: #000088;">$GLOBALS</span><span style="color: #009900;">&#91;</span><span style="">'TL_LANG'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'MSC'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'all'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span>
        <span style="">'href'</span>        <span style="color: #339933;">=&gt;</span> <span style="">'act=select'</span><span style="color: #339933;">,</span>
        <span style="">'class'</span>       <span style="color: #339933;">=&gt;</span> <span style="">'header_edit_all'</span><span style="color: #339933;">,</span>
        <span style="">'attributes'</span>  <span style="color: #339933;">=&gt;</span> <span style="">'onclick=&quot;Backend.getScrollOffset();&quot;'</span>
      <span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
    <span style="">'operations'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span>
    <span style="color: #009900;">&#40;</span>
      <span style="">'edit'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span>
      <span style="color: #009900;">&#40;</span>
        <span style="">'label'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #339933;">&amp;</span><span style="color: #000088;">$GLOBALS</span><span style="color: #009900;">&#91;</span><span style="">'TL_LANG'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'tl_filiere_filiales'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'edit'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span>
        <span style="">'href'</span>  <span style="color: #339933;">=&gt;</span> <span style="">'act=edit'</span><span style="color: #339933;">,</span>
        <span style="">'icon'</span>  <span style="color: #339933;">=&gt;</span> <span style="">'edit.gif'</span>
      <span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
      <span style="">'copy'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span>
      <span style="color: #009900;">&#40;</span>
        <span style="">'label'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #339933;">&amp;</span><span style="color: #000088;">$GLOBALS</span><span style="color: #009900;">&#91;</span><span style="">'TL_LANG'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'tl_filiere_filiales'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'copy'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span>
        <span style="">'href'</span>  <span style="color: #339933;">=&gt;</span> <span style="">'act=copy'</span><span style="color: #339933;">,</span>
        <span style="">'icon'</span>  <span style="color: #339933;">=&gt;</span> <span style="">'copy.gif'</span>
      <span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
      <span style="">'delete'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span>
      <span style="color: #009900;">&#40;</span>
        <span style="">'label'</span>      <span style="color: #339933;">=&gt;</span> <span style="color: #339933;">&amp;</span><span style="color: #000088;">$GLOBALS</span><span style="color: #009900;">&#91;</span><span style="">'TL_LANG'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'tl_filiere_filiales'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'delete'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span>
        <span style="">'href'</span>       <span style="color: #339933;">=&gt;</span> <span style="">'act=delete'</span><span style="color: #339933;">,</span>
        <span style="">'icon'</span>       <span style="color: #339933;">=&gt;</span> <span style="">'delete.gif'</span><span style="color: #339933;">,</span>
        <span style="">'attributes'</span> <span style="color: #339933;">=&gt;</span> <span style="">'onclick=&quot;if (!confirm(<span style="">\'</span>'</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$GLOBALS</span><span style="color: #009900;">&#91;</span><span style="">'TL_LANG'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'MSC'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'deleteConfirm'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">.</span> <span style="">'<span style="">\'</span>)) return false; Backend.getScrollOffset();&quot;'</span>
      <span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
      <span style="">'show'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span>
      <span style="color: #009900;">&#40;</span>
        <span style="">'label'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #339933;">&amp;</span><span style="color: #000088;">$GLOBALS</span><span style="color: #009900;">&#91;</span><span style="">'TL_LANG'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'tl_filiere_filiales'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'show'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span>
        <span style="">'href'</span>  <span style="color: #339933;">=&gt;</span> <span style="">'act=show'</span><span style="color: #339933;">,</span>
        <span style="">'icon'</span>  <span style="color: #339933;">=&gt;</span> <span style="">'show.gif'</span>
      <span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
&nbsp;
  <span style="color: #666666; font-style: italic;">// Palettes</span>
  <span style="">'palettes'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span>
  <span style="color: #009900;">&#40;</span>
    <span style="">'default'</span> <span style="color: #339933;">=&gt;</span> <span style="">'name;city,phone,email;services;'</span>
  <span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
&nbsp;
  <span style="color: #666666; font-style: italic;">// Fields</span>
  <span style="">'fields'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span>
  <span style="color: #009900;">&#40;</span>
    <span style="">'name'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span>
    <span style="color: #009900;">&#40;</span>
      <span style="">'label'</span>     <span style="color: #339933;">=&gt;</span> <span style="color: #339933;">&amp;</span><span style="color: #000088;">$GLOBALS</span><span style="color: #009900;">&#91;</span><span style="">'TL_LANG'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'tl_filiere_filiales'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'name'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span>
      <span style="">'exclude'</span>   <span style="color: #339933;">=&gt;</span> <span style="color: #000000; font-weight: bold;">true</span><span style="color: #339933;">,</span>
      <span style="">'search'</span>    <span style="color: #339933;">=&gt;</span> <span style="color: #000000; font-weight: bold;">true</span><span style="color: #339933;">,</span>
      <span style="">'inputType'</span> <span style="color: #339933;">=&gt;</span> <span style="">'text'</span><span style="color: #339933;">,</span>
      <span style="">'eval'</span>      <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="">'mandatory'</span><span style="color: #339933;">=&gt;</span>true<span style="color: #339933;">,</span> <span style="">'maxlength'</span><span style="color: #339933;">=&gt;</span><span style="color: #cc66cc;">255</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
    <span style="">'city'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span>
    <span style="color: #009900;">&#40;</span>
      <span style="">'label'</span>     <span style="color: #339933;">=&gt;</span> <span style="color: #339933;">&amp;</span><span style="color: #000088;">$GLOBALS</span><span style="color: #009900;">&#91;</span><span style="">'TL_LANG'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'tl_filiere_filiales'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'city'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span>
      <span style="">'exclude'</span>   <span style="color: #339933;">=&gt;</span> <span style="color: #000000; font-weight: bold;">true</span><span style="color: #339933;">,</span>
      <span style="">'filter'</span>    <span style="color: #339933;">=&gt;</span> <span style="color: #000000; font-weight: bold;">true</span><span style="color: #339933;">,</span>
      <span style="">'search'</span>    <span style="color: #339933;">=&gt;</span> <span style="color: #000000; font-weight: bold;">true</span><span style="color: #339933;">,</span>
      <span style="">'inputType'</span> <span style="color: #339933;">=&gt;</span> <span style="">'text'</span><span style="color: #339933;">,</span>
      <span style="">'eval'</span>      <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="">'mandatory'</span><span style="color: #339933;">=&gt;</span>true<span style="color: #339933;">,</span> <span style="">'maxlength'</span><span style="color: #339933;">=&gt;</span><span style="color: #cc66cc;">255</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
    <span style="">'phone'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span>
    <span style="color: #009900;">&#40;</span>
      <span style="">'label'</span>      <span style="color: #339933;">=&gt;</span> <span style="color: #339933;">&amp;</span><span style="color: #000088;">$GLOBALS</span><span style="color: #009900;">&#91;</span><span style="">'TL_LANG'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'tl_filiere_filiales'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'phone'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span>
      <span style="">'exclude'</span>    <span style="color: #339933;">=&gt;</span> <span style="color: #000000; font-weight: bold;">true</span><span style="color: #339933;">,</span>
      <span style="">'inputType'</span>  <span style="color: #339933;">=&gt;</span> <span style="">'text'</span><span style="color: #339933;">,</span>
      <span style="">'eval'</span>       <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="">'mandatory'</span><span style="color: #339933;">=&gt;</span>true<span style="color: #339933;">,</span> <span style="">'maxlength'</span><span style="color: #339933;">=&gt;</span><span style="color: #cc66cc;">255</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
    <span style="">'email'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span>
    <span style="color: #009900;">&#40;</span>
      <span style="">'label'</span>      <span style="color: #339933;">=&gt;</span> <span style="color: #339933;">&amp;</span><span style="color: #000088;">$GLOBALS</span><span style="color: #009900;">&#91;</span><span style="">'TL_LANG'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'tl_filiere_filiales'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'email'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span>
      <span style="">'exclude'</span>    <span style="color: #339933;">=&gt;</span> <span style="color: #000000; font-weight: bold;">true</span><span style="color: #339933;">,</span>
      <span style="">'search'</span>     <span style="color: #339933;">=&gt;</span> <span style="color: #000000; font-weight: bold;">true</span><span style="color: #339933;">,</span>
      <span style="">'inputType'</span>  <span style="color: #339933;">=&gt;</span> <span style="">'text'</span><span style="color: #339933;">,</span>
      <span style="">'eval'</span>       <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="">'mandatory'</span><span style="color: #339933;">=&gt;</span>true<span style="color: #339933;">,</span> <span style="">'maxlength'</span><span style="color: #339933;">=&gt;</span><span style="color: #cc66cc;">255</span><span style="color: #339933;">,</span> <span style="">'rgxp'</span><span style="color: #339933;">=&gt;</span><span style="">'email'</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
    <span style="">'services'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span>
    <span style="color: #009900;">&#40;</span>
      <span style="">'label'</span>      <span style="color: #339933;">=&gt;</span> <span style="color: #339933;">&amp;</span><span style="color: #000088;">$GLOBALS</span><span style="color: #009900;">&#91;</span><span style="">'TL_LANG'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'tl_filiere_filiales'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'services'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span>
      <span style="">'exclude'</span>    <span style="color: #339933;">=&gt;</span> <span style="color: #000000; font-weight: bold;">true</span><span style="color: #339933;">,</span>
      <span style="">'inputType'</span>  <span style="color: #339933;">=&gt;</span> <span style="">'checkboxWizard'</span><span style="color: #339933;">,</span>
      <span style="">'foreignKey'</span> <span style="color: #339933;">=&gt;</span> <span style="">'tl_filiere_services.name'</span><span style="color: #339933;">,</span>
      <span style="">'eval'</span>       <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="">'multiple'</span><span style="color: #339933;">=&gt;</span>true<span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#41;</span>;</pre></td></tr></table></div>

<p>Nous retrouvons ici en substance ce que nous avons déjà vu avec le DCA précédent. Les quatre premières champs sont de type texte. Le champs &#8216;email&#8217; est validé par une expression régulière s&#8217;assurant que cette adresse est légale.</p>
<p>Le champs &#8217;services&#8217; est de type &#8216;checkboxWizard&#8217;. Il s&#8217;agit d&#8217;un widget propre à Typolight qui crée une liste de checkboxes. Leur valeur est déterminée par la clef &#8216;foreignKey&#8217;. Cette clef sert à définir une table et un champs. Une checkbox sera créée pour chaque entrée de cette table. Le label de la checkbox sera la valeur du champs indiqué et la valeur de la checkbox sera l&#8217;id de l&#8217;entrée. Les valeurs des checkboxes sur ON seront stockée en tant que array serialisé dans la base de donnée ( d&#8217;où le type blob pour `services` dans la définition sql de la table <em>tl_filiere_filiales</em> ).</p>
<p>Si une filiale n&#8217;avait dû avoir qu&#8217;un seul service, nous aurions pu utiliser &#8217;select&#8217; comme inputType plutôt que checkboxWizard, pour utiliser un select classique. Un select peut se référer de la même manière à une table et l&#8217;un de ses champs pour déterminer sa valeur et son contenu texte. Il est possible également de lui passer arbitrairement des valeurs avec la clef &#8216;options&#8217;, ou d&#8217;utiliser un callback avec &#8216;options_callback&#8217;.</p>
<p>Nous voyons également ici l&#8217;usage de panelLayout, présent dans ['list']['sorting']. Quatre options sont disponibles : search, sort, filter et limit. Vous pouvez préciser leur disposition en les plaçant dans l&#8217;ordre que vous voulez, dans un string. Les séparer par des virgules les met les uns à la suite des autres, utiliser un point virgule fait passer à la ligne.</p>
<p>Pour déterminer qu&#8217;un champs peut être filtré, il suffit de placer &#8216;filter&#8217; =&gt; true dans sa déclaration. De même, pour déterminer qu&#8217;il peut être cherché, il faut y mettre &#8217;search&#8217; =&gt; true. &#8216;limit&#8217; ajoute un pager à la page.</p>
<h3>Retour sur le fichier de configuration.</h3>
<p>Il faut maintenant ajouter ce nouveau module dans le fichier de configuration. Comme nous en avons deux, il peut être intéressant de les grouper. Plutôt que de simplement les mettre dans la section &#8216;Contenu&#8217;, nous allons créer une nouvelle section, &#8216;Filière&#8217;. Nous utiliserons le nom du module ( dans mon cas, &#8216;filiere&#8217; ) dans le fichier de configuration, et le fichier de langue se chargera d&#8217;y attribuer la valeur &#8216;Filière&#8217; pour le français.</p>

<div class="wp_syntax"><div class="code"><pre class="php php" style="font-family:monospace;"><span style="color: #000088;">$GLOBALS</span><span style="color: #009900;">&#91;</span> <span style="">'BE_MOD'</span> <span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span> <span style="">'filiere'</span> <span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span>
<span style="color: #009900;">&#40;</span>
  <span style="">'tl_filiere_services'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span>
  <span style="color: #009900;">&#40;</span>
    <span style="">'tables'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span> <span style="">'tl_filiere_services'</span> <span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
  <span style="">'tl_filiere_filiales'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span>
  <span style="color: #009900;">&#40;</span>
    <span style="">'tables'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span> <span style="">'tl_filiere_filiales'</span> <span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
<span style="color: #009900;">&#41;</span>;</pre></div></div>

<p>Cela remplace donc ce que nous avions mis dans le fichier de configuration précédemment. La nouvelle section sera ajoutée à la fin de la liste. Il est possible de la placer plus précisément avec la fonction array_insert(). Si nous avions voulu le mettre en première position, cela aura donné :</p>

<div class="wp_syntax"><div class="code"><pre class="php php" style="font-family:monospace;">array_insert<span style="color: #009900;">&#40;</span> <span style="color: #000088;">$GLOBALS</span><span style="color: #009900;">&#91;</span> <span style="">'BE_MOD'</span> <span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> <span style="color:#800080;">0</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span>
  <span style="color: #009900;">&#40;</span>
    <span style="">'filiere'</span>  <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span>
    <span style="color: #009900;">&#40;</span>
      <span style="">'tl_filiere_services'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span>
      <span style="color: #009900;">&#40;</span>
        <span style="">'tables'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span> <span style="">'tl_filiere_services'</span> <span style="color: #009900;">&#41;</span>
      <span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
      <span style="">'tl_filiere_filiales'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span>
      <span style="color: #009900;">&#40;</span>
        <span style="">'tables'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span> <span style="">'tl_filiere_filiales'</span> <span style="color: #009900;">&#41;</span>
      <span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
    <span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#41;</span>;</pre></div></div>

<h3>Écriture des fichiers de langue</h3>
<p>Il ne reste plus qu&#8217;à créer les fichiers de langue. Si vous avez utilisé le créateur de modules et que vous avez spécifié les langues que vous souhaitez maintenir, les fichiers ont été créés automatiquement dans languages/. Nous allons nous concentrer sur languages/fr/.</p>
<p>Dans ce dossier, comme dans tout dossier de langue, vous trouverez par défaut les fichiers suivants :<br />
- <em>default.php</em> : un fichier fourre-tout où vous pouvez mettre tout ce qui ne rentre pas ailleurs. Utile, sémantiquement, pour mettre les définitions de langues qui peuvent être partagées entre plusieurs extensions.<br />
- <em>modules.php</em> : le fichier de langue général, permettant de donner une nom aux sections et modules dans la sidebar du back-office et en divers endroits.<br />
- <em>un fichier de langue par dca</em> : sert à définir le nom des champs, les noms des boutons et les divers contenus textes internationalisables utilisés par le module.</p>
<p>Nous n&#8217;utiliserons pas ici default.php. Dans modules.php, nous aurons :</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
</pre></td><td class="code"><pre class="php php" style="font-family:monospace;"><span style="color: #000088;">$GLOBALS</span><span style="color: #009900;">&#91;</span><span style="">'TL_LANG'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'MOD'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'filiere'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="">'Fillières'</span>;
<span style="color: #000088;">$GLOBALS</span><span style="color: #009900;">&#91;</span><span style="">'TL_LANG'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'MOD'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'tl_filiere_filiales'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="">'Filliales'</span><span style="color: #339933;">,</span> <span style="">'Gérez les informations relatives à vos filiales.'</span><span style="color: #009900;">&#41;</span>;
<span style="color: #000088;">$GLOBALS</span><span style="color: #009900;">&#91;</span><span style="">'TL_LANG'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'MOD'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'tl_filiere_services'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="">'Services'</span><span style="color: #339933;">,</span> <span style="">'Gérez les informations relatives à vos services.'</span><span style="color: #009900;">&#41;</span>;</pre></td></tr></table></div>

<p>La première entrée corespond au nom de la section que nous avons utilisé dans le fichier <em>config.php</em>. Les deux suivantes représentent les deux DCA. Leur valeur est un tableau à deux entrées, la première étant le titre, la seconde la description. Cette description est notament utilisées dans l&#8217;accueil du back-office, dans la section principale.</p>
<p>Dans le fichier <em>tl_filiere_services.php</em> ( toujours dans <em>languages/fr/</em> ), nous avons :</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
</pre></td><td class="code"><pre class="php php" style="font-family:monospace;"><span style="color: #0000ff; font-style: italic;">/**
 * Fields
 */</span>
<span style="color: #000088;">$GLOBALS</span><span style="color: #009900;">&#91;</span><span style="">'TL_LANG'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'tl_filiere_services'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'name'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="">'Nom'</span><span style="color: #339933;">,</span> <span style="">'Donnez un nom à ce service.'</span><span style="color: #009900;">&#41;</span>;
<span style="color: #000088;">$GLOBALS</span><span style="color: #009900;">&#91;</span><span style="">'TL_LANG'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'tl_filiere_services'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'description'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="">'Description'</span><span style="color: #339933;">,</span> <span style="">'Décrivez le service.'</span><span style="color: #009900;">&#41;</span>;
<span style="color: #000088;">$GLOBALS</span><span style="color: #009900;">&#91;</span><span style="">'TL_LANG'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'tl_filiere_services'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'price'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="">'Tarif'</span><span style="color: #339933;">,</span> <span style="">'Entrez la valeur numérique du tarif, sans précisez la devise, en séparant la décimale par un point. Exemple: &quot;19.99&quot;'</span><span style="color: #009900;">&#41;</span>;
&nbsp;
<span style="color: #0000ff; font-style: italic;">/**
 * Buttons
 */</span>
<span style="color: #000088;">$GLOBALS</span><span style="color: #009900;">&#91;</span><span style="">'TL_LANG'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'tl_filiere_services'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'new'</span><span style="color: #009900;">&#93;</span>    <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="">'Nouveau service'</span><span style="color: #339933;">,</span> <span style="">'Cliquez ici pour créer un nouveau service'</span><span style="color: #009900;">&#41;</span>;
<span style="color: #000088;">$GLOBALS</span><span style="color: #009900;">&#91;</span><span style="">'TL_LANG'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'tl_filiere_services'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'edit'</span><span style="color: #009900;">&#93;</span>   <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="">'Modifier'</span><span style="color: #339933;">,</span> <span style="">'Cliquez ici pour modifier les informations relatives à ce service.'</span><span style="color: #009900;">&#41;</span>;
<span style="color: #000088;">$GLOBALS</span><span style="color: #009900;">&#91;</span><span style="">'TL_LANG'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'tl_filiere_services'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'delete'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="">'Effacer'</span><span style="color: #339933;">,</span> <span style="">'Cliquez ici pour effacer le service.'</span><span style="color: #009900;">&#41;</span>;
<span style="color: #000088;">$GLOBALS</span><span style="color: #009900;">&#91;</span><span style="">'TL_LANG'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'tl_filiere_services'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'show'</span><span style="color: #009900;">&#93;</span>   <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="">'Voir'</span><span style="color: #339933;">,</span> <span style="">'Cliquez ici pour afficher les informations relatives à ce service.'</span><span style="color: #009900;">&#41;</span>;</pre></td></tr></table></div>

<p>Les champs fields sont ceux utilisés dans le DCA pour représenter les différents input. On y associe un tableau à deux entrées, le premier étant le titre, le second étant la description placée en dessous du widget si l&#8217;utilisateur à choisi d&#8217;avoir l&#8217;aide affichée.</p>
<p>Le même principe s&#8217;applique pour les boutons : le titre en première valeur, la description ( placée dans l&#8217;attribut title du lien ) en seconde valeur.</p>
<p>Vous pouvez également placer ici les textes de langue utilisés par votre DCA, comme par exemple les options fixes d&#8217;un select ( un squelette est placé dans le fichier lorsqu&#8217;il est créé automatiquement, dans la partie &#8220;References&#8221; du fichier ).</p>
<p>En dernier lieu, voici le fichier tl_filiere_filiales.php :</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
</pre></td><td class="code"><pre class="php php" style="font-family:monospace;"><span style="color: #0000ff; font-style: italic;">/**
 * Fields
 */</span>
<span style="color: #000088;">$GLOBALS</span><span style="color: #009900;">&#91;</span><span style="">'TL_LANG'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'tl_filiere_filiales'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'name'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="">'Nom'</span><span style="color: #339933;">,</span> <span style="">'Donnez le nom de cette filiale.'</span><span style="color: #009900;">&#41;</span>;
<span style="color: #000088;">$GLOBALS</span><span style="color: #009900;">&#91;</span><span style="">'TL_LANG'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'tl_filiere_filiales'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'city'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="">'Ville'</span><span style="color: #339933;">,</span> <span style="">'Donnez la ville de cette filiale.'</span><span style="color: #009900;">&#41;</span>;
<span style="color: #000088;">$GLOBALS</span><span style="color: #009900;">&#91;</span><span style="">'TL_LANG'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'tl_filiere_filiales'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'phone'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="">'Téléphone'</span><span style="color: #339933;">,</span> <span style="">'Quel est le numéro de téléphone de cette filiale?'</span><span style="color: #009900;">&#41;</span>;
<span style="color: #000088;">$GLOBALS</span><span style="color: #009900;">&#91;</span><span style="">'TL_LANG'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'tl_filiere_filiales'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'email'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="">'Email'</span><span style="color: #339933;">,</span> <span style="">'Donnez l\adresse email de cette filiale.'</span><span style="color: #009900;">&#41;</span>;
<span style="color: #000088;">$GLOBALS</span><span style="color: #009900;">&#91;</span><span style="">'TL_LANG'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'tl_filiere_filiales'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'services'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="">'Services'</span><span style="color: #339933;">,</span> <span style="">'Liste des services que cette filiale propose.'</span><span style="color: #009900;">&#41;</span>;
&nbsp;
<span style="color: #0000ff; font-style: italic;">/**
 * Buttons
 */</span>
<span style="color: #000088;">$GLOBALS</span><span style="color: #009900;">&#91;</span><span style="">'TL_LANG'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'tl_filiere_filiales'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'new'</span><span style="color: #009900;">&#93;</span>    <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="">'Nouvelle filiale'</span><span style="color: #339933;">,</span> <span style="">'Cliquez ici pour créer une nouvelle filiale.'</span><span style="color: #009900;">&#41;</span>;
<span style="color: #000088;">$GLOBALS</span><span style="color: #009900;">&#91;</span><span style="">'TL_LANG'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'tl_filiere_filiales'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'edit'</span><span style="color: #009900;">&#93;</span>   <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="">'Modifier'</span><span style="color: #339933;">,</span> <span style="">'Cliquez ici pour modifier les informations de cette filiale.'</span><span style="color: #009900;">&#41;</span>;
<span style="color: #000088;">$GLOBALS</span><span style="color: #009900;">&#91;</span><span style="">'TL_LANG'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'tl_filiere_filiales'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'copy'</span><span style="color: #009900;">&#93;</span>   <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="">'Dupliquer'</span><span style="color: #339933;">,</span> <span style="">'Cliquez ici pour créer une nouvelle filiale sur la base des informations de celle-ci.'</span><span style="color: #009900;">&#41;</span>;
<span style="color: #000088;">$GLOBALS</span><span style="color: #009900;">&#91;</span><span style="">'TL_LANG'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'tl_filiere_filiales'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'delete'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="">'Effacer'</span><span style="color: #339933;">,</span> <span style="">'Cliquez ici pour effacer cette filiale.'</span><span style="color: #009900;">&#41;</span>;
<span style="color: #000088;">$GLOBALS</span><span style="color: #009900;">&#91;</span><span style="">'TL_LANG'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'tl_filiere_filiales'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="">'show'</span><span style="color: #009900;">&#93;</span>   <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="">'Voir'</span><span style="color: #339933;">,</span> <span style="">'Cliquez ici pour voir les informations de cette filiale.'</span><span style="color: #009900;">&#41;</span>;</pre></td></tr></table></div>

<p>Il ne vous reste plus qu&#8217;à faire l&#8217;équivalent de ces fichiers pour chaque langue que vous voudrez maintenir.</p>
<p>Vous trouverez les fichiers de ce que nous venons de faire <a href="http://olivier-elmekki.com/tl_files/filiere.tar.bz2">ici</a>. Certains fichiers sont vides, ils sont relatifs aux modules frontend et seront utilisés dans un autre tutoriel. En effet, si vous disposez maintenant de quoi gérer basiquement des ressources en back-office, elles sont en l&#8217;état totalement inaccessibles au visiteur de votre site. Il va donc s&#8217;agir maintenant de coder un module frontend permettant d&#8217;utiliser ces ressources. Je reviendrai d&#8217;abord dans le prochain tuto sur l&#8217;utilisation des modèles. Ensuite, nous verrons les modules frontend. Enfin, nous reviendront plus en profondeur sur les modules backend. La suite au prochain épisode, merci de m&#8217;avoir lu.</p>
 <img src="http://blog.olivier-elmekki.com/wp-content/plugins/feed-statistics.php?view=1&post_id=299" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://blog.olivier-elmekki.com/2009/01/06/typolight-creation-de-module-backend-pour-gerer-des-ressources/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
