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

<channel>
	<title>Amicalement Web - Astuces et Bons plans dans le développement web &#187; admin</title>
	<atom:link href="http://www.amicalement-web.net/tag/admin/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.amicalement-web.net</link>
	<description>Astuces et bons plans d&#039;un web developpeur</description>
	<lastBuildDate>Wed, 04 Jan 2012 14:54:26 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Symfony2 : créer un admin sécurisé</title>
		<link>http://www.amicalement-web.net/symfony2-creer-un-admin-securise/2010/12/23/</link>
		<comments>http://www.amicalement-web.net/symfony2-creer-un-admin-securise/2010/12/23/#comments</comments>
		<pubDate>Thu, 23 Dec 2010 10:00:25 +0000</pubDate>
		<dc:creator>Tim</dc:creator>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[admin]]></category>
		<category><![CDATA[config]]></category>
		<category><![CDATA[Symfony]]></category>
		<category><![CDATA[symfony2]]></category>

		<guid isPermaLink="false">http://www.amicalement-web.net/?p=1603</guid>
		<description><![CDATA[Non je ne suis pas mort ! Une grosse année qui arrive à son terme et qui m&#8217;aura un peu éloigné du blog ces derniers mois, mais me voilà de retour aux affaires avec la sortie imminente de Symfony2. J&#8217;ai donc décidé de monter un petit site pour tester en conditions réelles ce nouveau framework. [...]]]></description>
			<content:encoded><![CDATA[<p><a  href="http://www.amicalement-web.net/symfony2-creer-un-admin-securise/2010/12/22/"><img src="http://www.amicalement-web.net/wp-content/uploads/Sans-titre-3.png" alt="" title="Sans-titre-3" width="614" height="100" class="alignnone size-full wp-image-1617" /></a><br />
Non je ne suis pas mort ! Une grosse année qui arrive à son terme et qui m&#8217;aura un peu éloigné du blog ces derniers mois, mais me voilà de retour aux affaires avec la sortie imminente de Symfony2. J&#8217;ai donc décidé de monter un petit site pour tester en conditions réelles ce nouveau framework. Et tant qu&#8217;à débroussailler le terrain, autant faire partager mes difficultés.</p>
<p>L&#8217;idée dans le tuto d&#8217;aujourd&#8217;hui est de faire un petit point sur la partie &laquo;&nbsp;security&nbsp;&raquo; très bien documentée sur le site officiel mais qui change assez des habitudes de symfony 1 et donc semble un peu déroutante au début.<br />
<span id="more-1603"></span></p>
<blockquote><p>
Ce billet est issu de ma propre et récente expérience sur le sujet et sur la branche master de fabien. Les choses peuvent changer ou être inexactes. Dans ce dernier cas, n&#8217;hésitez pas à me reprendre via les commentaires ;)
</p></blockquote>
<h3>Contexte</h3>
<p>Pour l&#8217;illustration, je vais simplement partir de la sandbox officielle d&#8217;origine configurée sur l&#8217;url suivante en local chez moi :</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">http:<span style="color: #000000; font-weight: bold;">//</span>sandbox.local</pre></div></div>

<p> et où je vais vous montrer comment y intégrer votre admin avec un formulaire d&#8217;identification sur l&#8217;url suivante :</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">http:<span style="color: #000000; font-weight: bold;">//</span>sandbox.local<span style="color: #000000; font-weight: bold;">/</span>admin<span style="color: #000000; font-weight: bold;">/</span></pre></div></div>

<p>L&#8217;utilisateur sera géré directement via la config, pas de bdd, on veut quelque chose de très simple et rapide à mettre en place.</p>
<p>Première chose à comprendre dans une application Symfony2, il n&#8217;y a plus qu&#8217;une application&#8230; Oui hein, ça parait fou dis comme ça :D Toute la séparation se situe au niveau des bundles, chacun d&#8217;eux pouvant embarquer des modèles, controllers, vues différentes, tout en pouvant communiquer avec les autres bundles. Fini les galères pour faire des liens entre un backend et un frontend !</p>
<p>Pour notre admin, nous allons donc générer un nouveau bundle dans notre application via la commande :</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">php app<span style="color: #000000; font-weight: bold;">/</span>console init:bundle Application<span style="color: #000000; font-weight: bold;">/</span>AdminBundle</pre></div></div>

<p>On se retrouve donc avec un controller basique dans ce bundle qui sera la base de notre admin. Première chose à faire, l&#8217;activer dans le fichier <code>app/AppKernel.php</code> via la méthode <code>registerBundles</code>.</p>
<h3>Mise en place url admin</h3>
<p>On va maintenant tenter d&#8217;y accéder via l&#8217;url <code>/admin/</code></p>
<p>Pour ça, c&#8217;est très simple ! On va modifier notre fichier routing.yml (ou xml ou php hein, mais moi j&#8217;aime bien le yml ! ) comme ceci :</p>

<div class="wp_syntax"><div class="code"><pre class="json" style="font-family:monospace;">#path:app/config/routing.yml
&nbsp;
homepage:
    pattern:  /
    defaults: { _controller: FrameworkBundle:Default:index }
&nbsp;
hello:
    resource: HelloBundle/Resources/config/routing.yml
&nbsp;
admin:
   resource: AdminBundle/Resources/config/routing.yml
   prefix: /admin</pre></div></div>

<p>et du coup créer le fichier de routing de notre nouveau AdminBundle. Pour ça, on va faire quelque chose de très simple aussi:</p>

<div class="wp_syntax"><div class="code"><pre class="yaml" style="font-family:monospace;">#src/Application/AdminBundle/Resources/config/routing.yml
admin_homepage:
  pattern:  /
  defaults: { _controller: AdminBundle:Default:index }</pre></div></div>

<p>Et par magie, maintenant, si vous accédez à l&#8217;url :</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">http:<span style="color: #000000; font-weight: bold;">//</span>sandbox.local<span style="color: #000000; font-weight: bold;">/</span>admin<span style="color: #000000; font-weight: bold;">/</span></pre></div></div>

<p>Vous obtenez le mot &laquo;&nbsp;Hello&nbsp;&raquo; qui n&#8217;est d&#8217;autre que la vue par défaut qui a été générée par la commande <code>init:bundle</code><br />
Pour pas se perdre, on va modifier la vue, pour y indiquer le mot admin, ca sera plus clair.</p>
<h3>Sécuriser l&#8217;url d&#8217;admin</h3>
<p>2e étape, comment sécuriser tout ça pour ne pas laisser tout le monde accéder à votre admin. Pour ça il y a en fait plusieurs solutions.</p>
<ul>
<li>Sécuriser toutes les urls de votre application, en autorisant les connexions anonymes partout, sauf dans votre admin</li>
<li>Sécuriser toutes les urls de votre admin seulement</li>
</ul>
<p>La 1ere a l&#8217;avantage de faire écrire très peu de ligne de config, mais honnêtement, je ne sais pas s&#8217;il y en a une de meilleure que l&#8217;autre, donc je présente la première dans ce tuto, mais je vous met le code de la deuxième à la fin. Elles font sensiblement la même chose.</p>
<p>On va donc se lancer dans la config du component security. Pour ça, on se retrouve dans notre <code>config.yml</code> pour y ajouter un provider, qui sera en fait le compte utilisateur de notre admin.</p>

<div class="wp_syntax"><div class="code"><pre class="yml" style="font-family:monospace;">#app/config/config.yml
security.config:
  providers:
    admin:
      users:
        monadmin: { password: monpass, roles: ROLE_ADMIN }</pre></div></div>

<p>Nous voici avec un compte &laquo;&nbsp;monadmin&nbsp;&raquo; identifié grâce au mot de passe &laquo;&nbsp;monpass&nbsp;&raquo; qui sera crédité de l&#8217;autorisation &laquo;&nbsp;ROLE_ADMIN&nbsp;&raquo; (pour pourriez mettre TOTO à la place de ADMIN, ca changerait rien, par contrel mot ROLE est apparemment obligatoire) </p>
<p>Pour l&#8217;instant, ca ne change rien. Définissons maintenant une règle firewall ! Le mot utilisé pour définir ce nouveau service fait sourire j&#8217;avoue, en fait il s&#8217;agit de définir des règles de sécurité pour des motifs d&#8217;urls.</p>
<p>On reste dans notre config.yml qu&#8217;on enrichit comme ceci:</p>

<div class="wp_syntax"><div class="code"><pre class="yml" style="font-family:monospace;">#app/config/config.yml
security.config:
  providers:
    main:
      users:
        monadmin: { password: monpass, roles: ROLE_ADMIN  }
&nbsp;
  firewalls:
    admin:
      pattern: .*
      http_basic: true</pre></div></div>

<p>Et là, vous obtenez normalement une demande d&#8217;authentification HTTP sur tout votre site. Ok! Maintenant, on va autoriser des connexions anonymes, c&#8217;est à dire qu&#8217;on ne va pas forcer les gens à se connecter:</p>

<div class="wp_syntax"><div class="code"><pre class="yml" style="font-family:monospace;">#app/config/config.yml
security.config:
  providers:
    main:
      users:
        monadmin: { password: monpass, roles: ROLE_ADMIN }
&nbsp;
  firewalls:
    admin:
      pattern: .*
      http_basic: true
      anonymous: true</pre></div></div>

<p>Maintenant, voyons voir pour mettre en place un formulaire plus conventionnel (et il me semble plus secure si bien fait, mais à confirmer).</p>

<div class="wp_syntax"><div class="code"><pre class="yml" style="font-family:monospace;">#app/config/config.yml
security.config:
  providers:
    main:
      users:
        monadmin: { password: monpass, roles: ROLE_ADMIN }
&nbsp;
  firewalls:
    admin:
      pattern: .*
      form_login: true
      anonymous: true</pre></div></div>

<p>Ici on a changé le mode d&#8217;authentification pour celui d&#8217;un formulaire classique, grâce à l&#8217;option <code>form-login</code></p>
<p>Maintenant, on va verrouiller l&#8217;accès à notre admin. Pour ce faire, on va demander une autorisation pour notre url <code>/admin</code>:</p>

<div class="wp_syntax"><div class="code"><pre class="yml" style="font-family:monospace;">#app/config/config.yml
security.config:
  providers:
    main:
      users:
        monadmin: { password: monpass, roles: ROLE_ADMIN }
&nbsp;
  firewalls:
    admin:
      pattern: .*
      form_login: true
      anonymous: true
&nbsp;
  access_control:
      - { path: /admin/.*, role: ROLE_ADMIN }</pre></div></div>

<p>Et maintenant, si vous essayez d&#8217;accéder à l&#8217;url :</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">http:<span style="color: #000000; font-weight: bold;">//</span>sandbox.local<span style="color: #000000; font-weight: bold;">/</span>admin<span style="color: #000000; font-weight: bold;">/</span></pre></div></div>

<p>Vous êtes redirigés vers l&#8217;url:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">http:<span style="color: #000000; font-weight: bold;">//</span>sandbox.local<span style="color: #000000; font-weight: bold;">/</span>login<span style="color: #000000; font-weight: bold;">/</span></pre></div></div>

<p>qui se termine en 404! Jusqu&#8217;ici c&#8217;est normal.</p>
<p>Symfony2 par défaut, utilise 3 urls pour la gestion de l&#8217;authentification :</p>
<ul>
<li>login</li>
<li>login_check</li>
<li>logout</li>
</ul>
<p>Nous allons donc les rajouter dans notre routing.yml tout simplement. Attention de bien les mettre au début, histoire d&#8217;éviter tout conflit avec une autre de vos règles.</p>

<div class="wp_syntax"><div class="code"><pre class="yml" style="font-family:monospace;">_security_login:
  pattern: /login
  defaults: { _controller: AdminBundle:Default:login }
&nbsp;
_security_check:
  pattern: /login_check
&nbsp;
_security_logout:
    pattern: /logout</pre></div></div>

<p>Le login a besoin de nous pour constituer le formulaire d&#8217;identification, les 2 autres doivent seulement exister ! Les patterns des urls peuvent varier, mais il faut alors donner les nouveaux paths dans le config.yml, nous verrons ça plus tard.</p>
<p>Maintenant, si nous accédons à notre admin nous avons bien sûr l&#8217;exception suivante:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">Method <span style="color: #0000ff;">&quot;Application\AdminBundle\Controller\DefaultController::loginAction&quot;</span> does not exist<span style="color: #339933;">.</span></pre></div></div>

<p>On la crée donc:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #666666; font-style: italic;">// src/Application/AdminBundle/Controller/DefaultController.php</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">namespace</span> Application\AdminBundle\Controller<span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">use</span> Symfony\Bundle\FrameworkBundle\Controller\Controller<span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">use</span> Symfony\Component\Security\SecurityContext<span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// à rajouter</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">class</span> DefaultController <span style="color: #000000; font-weight: bold;">extends</span> Controller
<span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> indexAction<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;">render</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'AdminBundle:Default:index.php'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> loginAction<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
       <span style="color: #666666; font-style: italic;">// get the error if any (works with forward and redirect -- see below)</span>
      <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'request'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">attributes</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">has</span><span style="color: #009900;">&#40;</span>SecurityContext<span style="color: #339933;">::</span><span style="color: #004000;">AUTHENTICATION_ERROR</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
          <span style="color: #000088;">$error</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'request'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">attributes</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span>SecurityContext<span style="color: #339933;">::</span><span style="color: #004000;">AUTHENTICATION_ERROR</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>
          <span style="color: #000088;">$error</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'request'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getSession</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span>SecurityContext<span style="color: #339933;">::</span><span style="color: #004000;">AUTHENTICATION_ERROR</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #009900;">&#125;</span>
&nbsp;
      <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">render</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'AdminBundle:Default:login.twig'</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;">// last username entered by the user</span>
          <span style="color: #0000ff;">'last_username'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'request'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getSession</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span>SecurityContext<span style="color: #339933;">::</span><span style="color: #004000;">LAST_USERNAME</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
          <span style="color: #0000ff;">'error'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$error</span><span style="color: #339933;">,</span>
      <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Donc là, j&#8217;ai simplement récupéré le code fourni dans la doc officielle, pas de mystère non plus. Et voici la vue correspondante :</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;form</span> <span style="color: #000066;">action</span>=<span style="color: #ff0000;">&quot;{% path &quot;</span>_security_check<span style="color: #ff0000;">&quot; %}&quot;</span> <span style="color: #000066;">method</span>=<span style="color: #ff0000;">&quot;post&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
&nbsp;
  {% if error %}
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;div</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;notification error png_bg&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;div<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
			{{ error }}
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/div<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/div<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  {% endif %}
&nbsp;
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;p<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;label<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Username<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/label<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;input</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;text-input&quot;</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;text&quot;</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;_username&quot;</span> <span style="color: #000066;">value</span>=<span style="color: #ff0000;">&quot;{{ last_username }}&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
   <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/p<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
   <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;p<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;label<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Password<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/label<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;input</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;text-input&quot;</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;password&quot;</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;_password&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
   <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/p<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
   <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;p</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;remember-password&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;input</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;checkbox&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>Remember me
   <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/p<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
   <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;p<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;input</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;button&quot;</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;submit&quot;</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;login&quot;</span> <span style="color: #000066;">value</span>=<span style="color: #ff0000;">&quot;Sign In&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
   <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/p<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/form<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>

<p>Là aussi, très basique mais ça vous donne l&#8217;occasion d&#8217;essayer twig ;) Ce qui compte pour le coup, c&#8217;est surtout les attributs name des input (_username et _password), et de rediriger vers <code>/login_check</code></p>
<blockquote><p>
A noter que l&#8217;utilisation du tag path dans la dernière version de twig n&#8217;est plus d&#8217;actualité. C&#8217;est désormais une fonction, donc à utiliser comme ceci {{ path(&#8216;_security_check&#8217;) }}
</p></blockquote>
<p>Alors oui, il faudrait un layout et tout, mais bon, on va aller droit à l&#8217;essentiel.</p>
<p>On retrouve bien notre formulaire de login maintenant, si on essaye d&#8217;accéder à notre admin ! Encore mieux, si on essaye de s&#8217;authentifier, avec le couple login/password défini au début, on obtient notre page &laquo;&nbsp;admin!&nbsp;&raquo; Et il suffit d&#8217;ajouter une dernière ligne à notre config, pour ajouter le listener manquant sur le <code>/logout</code> :</p>

<div class="wp_syntax"><div class="code"><pre class="yml" style="font-family:monospace;">#app/config/config.yml
security.config:
  providers:
    main:
      users:
        monadmin: { password: monpass, roles: ROLE_ADMIN }
&nbsp;
  firewalls:
    admin:
      pattern: .*
      form_login: true
      anonymous: true
      logout: true
&nbsp;
  access_control:
      - { path: /admin/.*, role: ROLE_ADMIN }</pre></div></div>

<p>Et maintenant, vous pouvez vous déloguer sur l&#8217;url :</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">http:<span style="color: #000000; font-weight: bold;">//</span>sandbox.local<span style="color: #000000; font-weight: bold;">/</span><span style="color: #7a0874; font-weight: bold;">logout</span></pre></div></div>

<p>Histoire d&#8217;illustrer un peu plus, voici une autre config qui fonctionne aussi et qui permet de ne sécuriser que l&#8217;admin:</p>

<div class="wp_syntax"><div class="code"><pre class="yml" style="font-family:monospace;">security.config:
  providers:
    main:
      users:
        monadmin: { password: monpass, roles: ROLE_TOTO }
&nbsp;
  firewalls:
    admin: { pattern: /admin/.*, form_login: true }
    login: { pattern: /login, anonymous: true, form_login: true }
    login_check: { pattern: /login_check, anonymous: true, form_login: true }
    logout: { pattern: /logout, form_login: true, logout: true }
&nbsp;
  access_control:
       - { path: /admin/.*, role: ROLE_TOTO }</pre></div></div>

<p>Il y a bien sûr, beaucoup de tuning possible, pour encoder le password par exemple, mais maintenant qu&#8217;on a la base, je vous laisse <a  href="http://docs.symfony-reloaded.org/guides/security/index.html" rel="extern">lire vraiment la doc</a> entière cette fois-ci ;)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.amicalement-web.net/symfony2-creer-un-admin-securise/2010/12/23/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Symfony Live 2010 : 1ere journée</title>
		<link>http://www.amicalement-web.net/symfony-live-2010-1ere-journee/2010/02/17/</link>
		<comments>http://www.amicalement-web.net/symfony-live-2010-1ere-journee/2010/02/17/#comments</comments>
		<pubDate>Wed, 17 Feb 2010 13:16:34 +0000</pubDate>
		<dc:creator>Tim</dc:creator>
				<category><![CDATA[Actualité]]></category>
		<category><![CDATA[admin]]></category>
		<category><![CDATA[community]]></category>
		<category><![CDATA[conference]]></category>
		<category><![CDATA[doctrine]]></category>
		<category><![CDATA[i18n]]></category>
		<category><![CDATA[Symfony]]></category>

		<guid isPermaLink="false">http://www.amicalement-web.net/?p=1217</guid>
		<description><![CDATA[Pour ceux qui suivent un peu l&#8217;actu Symfony, vous n&#8217;êtes pas sans savoir que se tient aujourd&#8217;hui et demain, le Symfony Live, un des évènements majeur du monde Symfony. Peut-être même que vous y êtes :D Et bien ça tombe bien car Vince et moi même avons la chance d&#8217;y être également ! Se rendre [...]]]></description>
			<content:encoded><![CDATA[<p><a  href="http://www.amicalement-web.net/symfony-live-2010-1ere-journee/2010/02/17"><img src="http://www.amicalement-web.net/wp-content/uploads/cite-internationale.jpg" alt="" title="cite-internationale" width="614" height="100" class="alignnone size-full wp-image-1246" /></a> Pour ceux qui suivent un peu l&#8217;actu Symfony, vous n&#8217;êtes pas sans savoir que se tient aujourd&#8217;hui et demain, le <a  href="http://www.symfony-live.com/">Symfony Live</a>, un des évènements majeur du monde Symfony. Peut-être même que vous y êtes :D</p>
<p>Et bien ça tombe bien car Vince et moi même avons la chance d&#8217;y être également !<br />
<span id="more-1217"></span></p>
<h3>Se rendre au Symfony Live</h3>
<p>Bon ce fut tout un marathon pour moi, levé 5h30 (et ceux qui me connaissent savent que c&#8217;est déjà un exploit :D), tram puis métro pour attraper mon TGV Marseille-Paris de 6h30.<br />
Arrivé à la gare de Lyon à 9h30, on repart pour une session métro, pour enchainer sur à nouveau un peu de tram avant d&#8217;arriver devant la Cité Internationale, endroit de Paris que je ne connaissais pas !</p>
<p>C&#8217;est déjà une belle surprise, l&#8217;endroit est fort sympathique, très joli, mais très graaand. Et j&#8217;ai pas trouvé les grandes affiches que j&#8217;attendais &laquo;&nbsp;Symfony C&#8217;est par là&nbsp;&raquo;. Bon finalement je débarque sur les coups de 10h30, badge, tour de cou et petit sac de goodies pour m&#8217;accueillir et me voilà dans l&#8217;arène.</p>
<p>Heureusement, il restait quelques croissants, parce que forcément j&#8217;avais fait l&#8217;impasse sur le petit déjeuner et je vais pas vous rappeler les tarifs prohibitifs de la SNCF. Juste de quoi me réveiller un peu et commencer à mettre en route mon cerveau qui jusque là ne voulait qu&#8217;une chose, se coucher.</p>
<h3>la matinée</h3>
<h4>Internationalisation</h4>
<p>On commence la journée par la présentation de <a  href="http://rabaix.net/">Thomas Rabaix</a> concernant l&#8217;internationalisation et Symfony. </p>
<p>Quelques rappels sur ce qu&#8217;est l&#8217;internationalisation, <strong>des astuces sympa comme comment traduire vos routes</strong>, mais aussi et surtout la présentation du plugin qu&#8217;il a réalisé pour <a  href="http://www.menugourmet.com/">Menu Gourmet</a> : <a  href="http://www.symfony-project.org/plugins/mgI18nPlugin">mgI18nPlugin</a>. Il permet de <strong>traduire à la volée</strong> toutes les chaînes statiques de votre page en utilisant une petit interface qui se place au dessus du site, à essayer d&#8217;urgence !<br />
Bref très bonne première présentation.</p>
<p>Vous pourrez trouver les slides de sa présentation <a  href="http://rabaix.net/en/articles/2010/02/16/symfony-live-2010-internationalization">sur son site</a>.</p>
<h4>Admin generator en détail</h4>
<p>John Cleveley nous a fait une petite piqure de rappel des nouveautés de l&#8217;admin generator depuis la version 1.0. Il a aussi été l&#8217;auteur du slide le plus classe de la journée concernant l&#8217;administration &laquo;&nbsp;backend&nbsp;&raquo; : un éléphant se soulageant le derrière dans un seau &#8230; ;-)</p>
<p>Il a rappelé que l&#8217;admin generator c&#8217;était bien, mais pas forcément pour tout. <strong>Qu&#8217;il fallait réfléchir au besoin avant de l&#8217;utiliser</strong>, plutôt que de partir avec tête baissée et se rendre compte plus tard qu&#8217;on passe plus de temps à galérer avec par rapport à ce qu&#8217;on veut faire qu&#8217;autre chose (sa remarque est d&#8217;ailleurs valable pour tout développement : c&#8217;est généralement une bonne idée de réfléchir avant de se lancer ! ).</p>
<p>Si vous voulez créer votre propre thème, vous pouvez vous inspirer de <a  href="http://www.symfony-project.org/plugins/sfAdminDashPlugin">sfAdminDashPlugin</a> et de <a  href="http://www.symfony-project.org/plugins/sfAdminThemejRollerPlugin">sfAdminThemejRollerPlugin</a>.</p>
<p>Il a aussi re-précisé que sfContext::getInstance c&#8217;était le mal (même si lui l&#8217;utilisait dans ses slides) et a fini par parler de la facilité de modifier/étendre les filtres grâce au form framework. En ce qui concerne les form, il est préférable d&#8217;en <strong>créer un nouveau pour chaque form du backend</strong>, histoire de pas confondre les forms front et back. </p>
<p>Il a conseillé d&#8217;utiliser <strong>le moins possible le generator pour les label, help etc des forms</strong>, mais de tout laisser dans le form : beaucoup plus facile à maintenir.</p>
<h4>Windows plaide coupable</h4>
<p>Surement parce qu&#8217;ils sont sponsor, on a retrouvé une équipe de Microsoft qui a plaidé pendant 50 longues minutes que Microsoft c&#8217;était aussi (et presque surtout) de l&#8217;open source et que développer dessus, c&#8217;était bien. Apparemment pas assez pour donner envie de poser des questions à l&#8217;auditoire.</p>
<p>Bon, ok sur windows, tu peux développer sur Visual Studio 2010 <strong>Ultimate</strong>, what else?</p>
<p>Du coup <a  href="http://answers.polldaddy.com/poll/2712522/">un petit sondage</a> a été lancé sur la répartition des OS pour les devs symfony</p>
<h3>L&#8217;aprèm</h3>
<h4>Symfony Internals</h4>
<p>Pas de nouveautés pour tous les développeurs qui ont pu travailler un peu en profondeur sur ce framework. <strong>Une belle revue de tout le fonctionnement interne </strong>de Symfony par Geoffrey Bachelet, et avec un accent so french ;)</p>
<p><a  href="http://www.slideshare.net/ubermuda/symfony-internals">Voir les slides</a></p>
<h4>Doctrine migration</h4>
<p>Un bon rappel sur l&#8217;enjeu des migrations et que maintenant (depuis sf 1.3) <strong>cela consiste en 3 opérations</strong> :</p>
<ul>
<li>Modifier son schema.yml pour inclure nos modifications</li>
<li>Lancer la task de diff:<br /> <code>symfony doctrine:generate-migrations-diff</code></li>
<li>Regénérer ces classes model/form/filter et lancer la migration:<br /> <code>symfony doctrine:build --all-classes --and-migrate</code></li>
</ul>
<p>Alors pourquoi s&#8217;en priver?</p>
<p><a  href="http://www.slideshare.net/denderello/symfony-live-2010-using-doctrine-migrations">Voir les slides</a></p>
<h4>Doctrine 2</h4>
<p>Est arrivé le tour de chauffe des gros sujets de la conférence. En l&#8217;occurrence Doctrine 2. Les grandes idées que Jonathan nous a montré:</p>
<ul>
<li><strong>100% réécrit</strong>, donc plus de compatibilité descendante</li>
<li><strong>~ 3 fois plus rapide</strong> que Doctrine 1.2</li>
<li>Principalement <strong>concentré sur la perf</strong>, et donc <strong>adieu la magie</strong> des findByMaColonne et consor. A l&#8217;image de Propel, les getteur et setteur seront générés dans la class model vu que les modèles justement n&#8217;hériteront plus d&#8217;une class de type Record, permettant ainsi d&#8217;alléger la charge mémoire</li>
<li>Intégration d&#8217;une classe qui s&#8217;occupera, à l&#8217;image du monde java, de <strong>gérer les flush et clear</strong>. Ca ne sera plus l&#8217;objet en lui même qu&#8217;il faudra &laquo;&nbsp;save&nbsp;&raquo; mais demander à cette nouvelle classe de le faire.</li>
</ul>
<p>Forcément, ca fait un peu peur, car au delà, d&#8217;une réécriture, ce sont des gros changements. Mais dans un souci de performance (aussi bien en terme de temps d&#8217;exécution que de charge mémoire), on prend le bon chemin. Même si la magie va disparaître&#8230;</p>
<p><a  href="http://www.slideshare.net/jwage/doctrine-2-not-the-same-old-php-orm">Voir les slides</a></p>
<h4>Offline admin generator</h4>
<p>Sur cette partie, on a retrouvé Thomat Parizot, de chez clever-age (vous savez ceux qui ont annoncé un plugin de gestion de media au dernier symfony live, mais qu&#8217;on attend toujours :p).<br />
On découvre <strong>un concept plutôt innovant</strong> dans le monde symfony, l&#8217;idée de permettre l&#8217;accès et <strong>le travail sur un backoffice sans connexion Internet</strong> semble une bonne idée. Il suffit de synchroniser, après coup, son travail.</p>
<p>Bon ok la démo n&#8217;a pas été parfaite &#8211; ahh l&#8217;effet démo &#8211; mais ya quand même un gros boulot derrière même si malheureusement c&#8217;est un concept très (trop?) <strong>dépendant de la technologie</strong>, vu qu&#8217;après Gears, il se base maintenant sur HTML5 et toutes ces nouvelles fonctionnalités. Donc très limité, mais à garder sous le coude.</p>
<h4>Help the community</h4>
<p>Skoop a redonner toutes les clés pour aider la communauté. Et que<strong> même les petites actions</strong>, comme les ouvertures de bug, sont très appréciées. </p>
<p><a  href="http://www.slideshare.net/skoop/the-symfony-community-how-to-get-help">Voir les slides</a></p>
<h4>Table ronde avec la core team</h4>
<p>Pas mal de questions sur les sujets classiques, hello world application, et consor. Voici un petit recap des questions que j&#8217;ai comprises et trouvées intéressantes:</p>
<dl>
<dt>Q: Compatibilité descendante avec la fin du support de la 1.0</dt>
<dd>R: Gros effort sur la facilité de passer à une version supérieure</dd>
<dt>Q: Documentation du système de form un peu en retrait?</dt>
<dd>R: Ne pas hésiter à aider!</dd>
<dt>Q: Symfony enseigné à l&#8217;école? Support de cours disponibles?</dt>
<dd>R: PHP déjà peut enseigné de base. Pas plus d&#8217;info à ce sujet mais ne pas hésiter à les contacter sur ce sujet</dd>
<dt>Q: Développement ne va pas trop vite?</dt>
<dd>R: La 1.4 aura bien 3 ans de support, ce qui est en soi, très long. Et puis le web évolue vite, donc il faut suivre</dd>
<dt>Q: Performance? Quid?</dt>
<dd>R: Le problème vient rarement du framework&#8230; :D </dd>
<dt>Q: Difficulté à faire adopter Symfony par leur client</dt>
<dd>R: C&#8217;est ensemble et en fournissant des cas d&#8217;utilisation précis de Symfony, qu&#8217;on pourra faire évoluer les mentalités</dd>
<dt>Q: Sismo? Bientôt dans les bacs?</dt>
<dd>R: Fabien n&#8217;a plus le temps pour l&#8217;instant. Projet en standby et clairement pas prioritaire. Et de toute façon Sismo ne fera jamais tout ce que fait Hudson et consor. Il n&#8217;a pas écarté la possibilité de ne jamais le release&#8230;</dd>
<dt>Q: Quid de la construction d&#8217;un vrai CMS Symfony une bonne foi pour toute?</dt>
<dd>R: Déjà 3 CMS existant très solides, avec 3 approches différentes. Il faut en débattre.</dd>
<dt>Q: Pourquoi reprendre plein de projets, comme Swift?</dt>
<dd>R: Une volonté de ne pas réinventer la roue et de récupérer et adapter les meilleurs pratiques et idées en PHP</dd>
<dt>Q: Et Propel dans tout ça?</dt>
<dd>R: Gros boulot de François, mais peut-être un peu trop tard?  Jamais dire jamais, mais pour l&#8217;instant après le gros switch vers Doctrine, difficile de faire machine arrière. Surtout que le futur de Propel avec sa 2.0 n&#8217;est pas du tout assuré pour l&#8217;instant</dd>
</dl>
<p>Et du coup, quelques annonces sont sorties:</p>
<ul>
<li><strong>phpbb4 sera codé en Symfony 2</strong>, ce qui en ferait le premier gros projet open source php entièrement en Symfony si je ne m&#8217;abuse</li>
<li>Symfony2 n&#8217;a plus de plugin mais des bundles&#8230;</li>
<li>Symfony2 n&#8217;utilisera plus que le meilleur des autres framework, comme le logger et le cache de Zend, <strong>au lieu de le recoder de leur côté</strong>.</li>
</ul>
<p>Voilà un petit compte rendu, les slides des différentes interventions sont disponible sur le <a  href="http://www.symfony-project.org/blog/2010/02/17/symfony-live-day-1">blog de Symfony</a>.</p>
<p class="alignright">
<em>Vos envoyés spéciaux pour l&#8217;évènement: Vince et Tim</em>
</p>
<p style="clear: both">
<small>crédit photo: http://www.flickr.com/photos/iph4n70m/4338366087/</small></p>
]]></content:encoded>
			<wfw:commentRss>http://www.amicalement-web.net/symfony-live-2010-1ere-journee/2010/02/17/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Développement Web: Les bons plans de la semaine #10</title>
		<link>http://www.amicalement-web.net/developpement-web-les-bons-plans-de-la-semaine-10/2009/08/10/</link>
		<comments>http://www.amicalement-web.net/developpement-web-les-bons-plans-de-la-semaine-10/2009/08/10/#comments</comments>
		<pubDate>Mon, 10 Aug 2009 11:00:17 +0000</pubDate>
		<dc:creator>Tim</dc:creator>
				<category><![CDATA[Bons plans]]></category>
		<category><![CDATA[admin]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://www.amicalement-web.net/?p=554</guid>
		<description><![CDATA[Nouvelle semaine qui commence vraiment à sentir les vacances, vu la difficulté que j&#8217;ai eu à glaner de bons liens à cliquer la semaine passée. A croire que les gens partent en vacances majoritairement en août&#8230; Bref, j&#8217;ai quand même réussi à trouver des choses que je pense intéressantes. Mais en rédigeant la liste, il [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.amicalement-web.net/wp-content/uploads/applications-system.png" alt="applications-system" title="applications-system" width="48" height="48" class="alignleft size-full wp-image-31" /> Nouvelle semaine qui commence vraiment à sentir les vacances, vu la difficulté que j&#8217;ai eu à glaner de bons liens à cliquer la semaine passée. A croire que les gens partent en vacances majoritairement en août&#8230;<br />
Bref, j&#8217;ai quand même réussi à trouver des choses que je pense intéressantes. Mais en rédigeant la liste, il m&#8217;est venu une interrogation:<br />
<span id="more-554"></span><br />
En partant du principe que vous aimez bien mes petites listes et que vous cliquez sur les liens, est-ce que vous êtes dérangé par les articles en anglais (majoritaires qui plus est)? Parce que je me disais que si c&#8217;était le cas, vous avez le droit de le dire hein que vous êtes pas contents, c&#8217;est aussi là pour ça les commentaires! Même si l&#8217;anglais reste la langue de l&#8217;informatique, même moi j&#8217;apprécie de bonnes ressources francophones, mais cela se fait rare.</p>
<p>Du coup, la question qui s&#8217;impose c&#8217;est, est-ce que certains d&#8217;entre vous trouverez sympa d&#8217;avoir la traduction d&#8217;un de ces articles (à raison d&#8217;un par semaine grand max hein)? Voilà, c&#8217;est dit, à vous de jouer et de me dire, histoire que je me tracasse pas pour rien.</p>
<p>Pour vous aider à réfléchir, voici la liste de la semaine:</p>
<ul>
<li><a  href="http://www.wpbeginner.com/showcase/evolution-of-wordpress-user-interface-2003-2009/">Evolution de l&#8217;interface admin de WordPress</a><br />
Petit billet sympa qui retrace grâce à différent screenshot, l&#8217;évolution de l&#8217;interface admin de WordPress, pour ceux qui ne blog pas depuis 6ans.</li>
<li><a  href="http://www.cssstickyfooter.com/">Collez vos pieds de page en bas</a><br />
C&#8217;est un des détails que les graphistes aiment, mais que les intégrateurs ont vite dégagé, pouvoir collé le footer d&#8217;une page en bas du navigateur et ce même si le contenu fait la moitié de la fenêtre. Il y a des solutions JS qui existe, en voici une pure CSS, qui demande juste quelques contraintes pour fonctionner. Pour la plupart des cas, ca ne devrait pas poser de souci.</li>
<li><a  href="http://lirent.net/wordpress/100-most-popular-wordpress-plugins.html">Les 100 plugins wordpress les plus populaires</a><br />
On a souvent du mal à s&#8217;y retrouver dans les plugins wordpress, tellement il y en a et tellement la zone qui leur est réservée sur le site officiel est pas top. Voilà donc une liste qui s&#8217;avère pratique où on mentionne tous les leaders pour chaque fonction qu&#8217;on souhaite rajouter à notre blog préféré.</li>
<li><a  href="http://www.jcryption.org/">Librairie de cryptage en javascript</a><br />
Voici une petite librairie sympa vu qu&#8217;elle propose un premier niveau de sécurité au niveau des formulaires html, en cryptant leur envoi au serveur. Bien sûr, cela reste très rudimentaire dans une grosse politique de sécurité, mais l&#8217;initiative est bonne et dans certains cas, ne serait-ce que pour compliquer le snif de requête, elle peut s&#8217;avérer utile</li>
<li><a  href="http://www.danielbroche.com/daniel_broche/2009/08/paypal-ouvre-sa-technologie.html">Paypal va s&#8217;ouvrir aux développeurs</a><br />
Je n&#8217;ai pas eu le temps d&#8217;enquêter plus que ça, donc je vous met le lien d&#8217;origine où j&#8217;ai trouvé l&#8217;info. Mais ca promet!</li>
<li><a  href="http://briancray.com/2009/07/28/increase-form-usability-replace-form-button-submit/">Améliorer l&#8217;expérience utilisation avec des détails</a><br />
Une petite astuce toujours dans la quête de la meilleur expérience utilisateur. Le principe est simple, bien faire comprendre à votre utilisateur que vous avez reçu sa demande.</li>
<li><a  href="http://devlunch.smart.fm/2009/07/29/six-things-your-mom-never-told-you-about-debugging-javascript/">6 choses que votre mère ne vous a jamais dit sur le debug javascript</a><br />
Article très sympa, et se serait lui qui serait traduit cette semaine, si jamais vous décidiez qu&#8217;il faut que je le fasse.</li>
<li><a  href="http://www.davidmassiani.com/horinaja/">Un enième plugin jquery slideshow</a><br />
Au royaume du jquery, les slideshow sont rois. On ne compte plus le nombre différentes de plugins qu&#8217;il existe. Alors pourquoi je vous parle de celui-là? 2 particularités, il gère la roulette pour le défilement mais surtout il est francophone : )) Et oui quand je trouve de la qualité dans notre belle langue, je me gène pas</li>
</ul>
<p>Et bien sûr, stay tunes cette semaine, au cas où vous croiseriez un nouveau thème dans le coin&#8230; ou pas :p</p>
]]></content:encoded>
			<wfw:commentRss>http://www.amicalement-web.net/developpement-web-les-bons-plans-de-la-semaine-10/2009/08/10/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Symfony: Domptez les filtres de l&#8217;admin generator</title>
		<link>http://www.amicalement-web.net/symfony-domptez-les-filtres-de-ladmin-generator/2009/06/16/</link>
		<comments>http://www.amicalement-web.net/symfony-domptez-les-filtres-de-ladmin-generator/2009/06/16/#comments</comments>
		<pubDate>Tue, 16 Jun 2009 16:26:01 +0000</pubDate>
		<dc:creator>Tim</dc:creator>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[admin]]></category>
		<category><![CDATA[filter]]></category>
		<category><![CDATA[howto]]></category>
		<category><![CDATA[Symfony]]></category>
		<category><![CDATA[widget]]></category>

		<guid isPermaLink="false">http://www.amicalement-web.net/?p=348</guid>
		<description><![CDATA[Un détail qui m&#8217;a toujours titillé dans le fabuleux admin generator de symfony, c&#8217;est le bloc de filtre. Le concept est bien sûr génial. Sans rien faire, vous avez déjà la possibilité de filtrer vos résultats, un gain de temps énorme, surtout quand on a un client qui sait ce qu&#8217;il veut. Mais voilà, même [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.amicalement-web.net/wp-content/uploads/system-run.png" alt="system-run" title="system-run" width="48" height="48" class="alignleft size-full wp-image-38" /> Un détail qui m&#8217;a toujours titillé dans le fabuleux <a  href="http://www.symfony-project.org/jobeet/1_2/Propel/en/12" class="extern">admin generator de symfony</a>, c&#8217;est le bloc de filtre. Le concept est bien sûr génial. Sans rien faire, vous avez déjà la possibilité de filtrer vos résultats, un gain de temps énorme, surtout quand on a un client qui sait ce qu&#8217;il veut. Mais voilà, même si depuis la 1.2, le layout de l&#8217;admin generator par défaut a subit un lifting qui le rend beau de série:<br />
<a  href="http://www.amicalement-web.net/wp-content/uploads/Image-56.png"><img src="http://www.amicalement-web.net/wp-content/uploads/Image-56-300x44.png" alt="Image 56" title="Image 56" width="300" height="44" class="alignnone size-medium wp-image-349" /></a><br />
<span id="more-348"></span><br />
On rencontre très vite, dans le cas d&#8217;un tableau avec beaucoup de colonnes, le fameux &laquo;&nbsp;bug&nbsp;&raquo; css sur un écran plus petit que mon 20&#8243; (oui parce que chez moi, c&#8217;est toujours très beau, chez mes chefs de projets et leur portable, beaucoup moins :D):<br />
<a  href="http://www.amicalement-web.net/wp-content/uploads/Image-57.png"><img src="http://www.amicalement-web.net/wp-content/uploads/Image-57-300x48.png" alt="Image 57" title="Image 57" width="300" height="48" class="alignnone size-medium wp-image-350" /></a></p>
<p>Alors bien sûr, la solution radicale, c&#8217;est de réduire le nombre de colonnes, mais souvent le client, il les veut ses colonnes! La 2e solution est de supprimer ce bloc de filtre. On fait ça très simplement dans le generator.yml:</p>

<div class="wp_syntax"><div class="code"><pre class="yaml" style="font-family:monospace;">filter:
  class: false</pre></div></div>

<p>Cependant, il arrive quand même que le filtrage soit nécessaire mais bien souvent, seulement 2 ou 3 valeurs. J&#8217;ai donc décidé de prendre le taureau par les cornes et faire la modification dont je rêve depuis longtemps, passer ce bloc de filtre, au dessus du tableau! Pour ce faire, j&#8217;ai modifié 2 fichiers. Tout d&#8217;abord, le fichier <code>_filters.php</code> qu&#8217;il faudra rajouter dans le dossier templates de vos modules visés:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">&lt;div class=&quot;sf_admin_filter&quot;&gt;
&nbsp;
	&lt;div class=&quot;content_filter&quot;&gt;
  <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$form</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">hasGlobalErrors</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">:</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
    <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$form</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">renderGlobalErrors</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
  <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">endif</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
&nbsp;
&nbsp;
  &lt;form action=&quot;<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> url_for<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'produits_collection'</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'action'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'filter'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&quot; method=&quot;post&quot;&gt;
	  <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$configuration</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getFormFilterFields</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$form</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$name</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$field</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">:</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
	  &lt;div class=&quot;bloc_filter&quot;&gt;
        <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">isset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$form</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$name</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #000088;">$form</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$name</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">isHidden</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">||</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #990000;">isset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$form</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$name</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #000088;">$field</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">isReal</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">continue</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
          <span style="color: #000000; font-weight: bold;">&lt;?php</span> include_partial<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'produits/filters_field'</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
            <span style="color: #0000ff;">'name'</span>       <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$name</span><span style="color: #339933;">,</span>
            <span style="color: #0000ff;">'attributes'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$field</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getConfig</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'attributes'</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
            <span style="color: #0000ff;">'label'</span>      <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$field</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getConfig</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'label'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
            <span style="color: #0000ff;">'help'</span>       <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$field</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getConfig</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'help'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
            <span style="color: #0000ff;">'form'</span>       <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$form</span><span style="color: #339933;">,</span>
            <span style="color: #0000ff;">'field'</span>      <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$field</span><span style="color: #339933;">,</span>
            <span style="color: #0000ff;">'class'</span>      <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'sf_admin_form_row sf_admin_'</span><span style="color: #339933;">.</span><span style="color: #990000;">strtolower</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$field</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getType</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">' sf_admin_filter_field_'</span><span style="color: #339933;">.</span><span style="color: #000088;">$name</span><span style="color: #339933;">,</span>
          <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
    &lt;/div&gt;
    <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">endforeach</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
&nbsp;
     <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$form</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">renderHiddenFields</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
     <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> link_to<span style="color: #009900;">&#40;</span>__<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Reset'</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'sf_admin'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'produits_collection'</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'action'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'filter'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'query_string'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'_reset'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'method'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'post'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
     &lt;input type=&quot;submit&quot; value=&quot;<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> __<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Filter'</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'sf_admin'</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&quot; /&gt;
  &lt;/form&gt;
  &lt;/div&gt;
&lt;/div&gt;</pre></div></div>

<p>Au final, j&#8217;ai simplement supprimé le tableau, par défaut et mis chaque widget dans un div. On obtient donc quelque chose qui change pas vraiment la donne pour l&#8217;instant:<br />
<a  href="http://www.amicalement-web.net/wp-content/uploads/Image-58.png"><img src="http://www.amicalement-web.net/wp-content/uploads/Image-58-300x36.png" alt="Image 58" title="Image 58" width="300" height="36" class="alignnone size-medium wp-image-353" /></a></p>
<p>Mais en lui appliquant un peu de css:</p>

<div class="wp_syntax"><div class="code"><pre class="css" style="font-family:monospace;">div<span style="color: #cc00cc;">#sf_admin_bar</span> <span style="color: #00AA00;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">float</span><span style="color: #00AA00;">:</span><span style="color: #993333;">none</span><span style="color: #00AA00;">;</span>
	<span style="color: #000000; font-weight: bold;">margin</span><span style="color: #00AA00;">:</span> <span style="color: #cc66cc;">0</span><span style="color: #00AA00;">;</span>
<span style="color: #00AA00;">&#125;</span>
&nbsp;
<span style="color: #cc00cc;">#sf_admin_bar</span> <span style="color: #6666ff;">.sf_admin_filter</span> form div<span style="color: #6666ff;">.bloc_filter</span> <span style="color: #00AA00;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">display</span><span style="color: #00AA00;">:</span><span style="color: #993333;">inline</span><span style="color: #00AA00;">;</span>
	<span style="color: #000000; font-weight: bold;">padding</span><span style="color: #00AA00;">:</span><span style="color: #cc66cc;">0</span> <span style="color: #933;">20px</span> <span style="color: #cc66cc;">0</span> <span style="color: #cc66cc;">0</span><span style="color: #00AA00;">;</span>
<span style="color: #00AA00;">&#125;</span>
&nbsp;
div<span style="color: #cc00cc;">#sf_admin_container</span> <span style="color: #cc00cc;">#sf_admin_bar</span> label <span style="color: #00AA00;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">display</span><span style="color: #00AA00;">:</span><span style="color: #993333;">inline</span><span style="color: #00AA00;">;</span>
	<span style="color: #000000; font-weight: bold;">float</span><span style="color: #00AA00;">:</span><span style="color: #993333;">none</span><span style="color: #00AA00;">;</span>
	<span style="color: #000000; font-weight: bold;">padding</span><span style="color: #00AA00;">:</span><span style="color: #cc66cc;">0</span><span style="color: #00AA00;">;</span>
<span style="color: #00AA00;">&#125;</span></pre></div></div>

<p>On commence à approcher de ce que l&#8217;on souhaite:<br />
<a  href="http://www.amicalement-web.net/wp-content/uploads/Image-60.png"><img src="http://www.amicalement-web.net/wp-content/uploads/Image-60-300x29.png" alt="Image 60" title="Image 60" width="300" height="29" class="alignnone size-medium wp-image-354" /></a></p>
<p>Maintenant, on habille un peu la chose, histoire de gagner en clarté:</p>

<div class="wp_syntax"><div class="code"><pre class="css" style="font-family:monospace;"><span style="color: #cc00cc;">#sf_admin_bar</span> <span style="color: #6666ff;">.sf_admin_filter</span> <span style="color: #00AA00;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">background-color</span><span style="color: #00AA00;">:</span><span style="color: #cc00cc;">#FFF</span><span style="color: #00AA00;">;</span>
	<span style="color: #000000; font-weight: bold;">margin</span><span style="color: #00AA00;">:</span><span style="color: #933;">12px</span> <span style="color: #cc66cc;">0</span><span style="color: #00AA00;">;</span>
<span style="color: #00AA00;">&#125;</span>
&nbsp;
<span style="color: #cc00cc;">#sf_admin_bar</span> <span style="color: #6666ff;">.sf_admin_filter</span> <span style="color: #6666ff;">.content_filter</span> <span style="color: #00AA00;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">border</span><span style="color: #00AA00;">:</span><span style="color: #933;">1px</span> <span style="color: #993333;">solid</span> <span style="color: #cc00cc;">#DDDDDD</span><span style="color: #00AA00;">;</span>
	<span style="color: #000000; font-weight: bold;">padding</span><span style="color: #00AA00;">:</span><span style="color: #933;">5px</span><span style="color: #00AA00;">;</span>
<span style="color: #00AA00;">&#125;</span></pre></div></div>

<p>Pour obtenir finalement:<br />
<a  href="http://www.amicalement-web.net/wp-content/uploads/Image-61.png"><img src="http://www.amicalement-web.net/wp-content/uploads/Image-61-300x38.png" alt="Image 61" title="Image 61" width="300" height="38" class="alignnone size-medium wp-image-355" /></a></p>
<p>Un dernier détail, le filtre &laquo;&nbsp;référence&nbsp;&raquo; avec sa colonne &laquo;&nbsp;is_empty&nbsp;&raquo; casse un peu notre rendu. Personnellement, je ne me sers pas de cette checkbox, on va donc redéfinir notre filtre pour la supprimer dans <code>lib/filters/MonModuleFilters.class.php</code>:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> configure<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;">widgetSchema</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'reference'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> sfWidgetFormFilterInput<span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
      <span style="color: #0000ff;">'template'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'%input%'</span>
    <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span></pre></div></div>

<p>Et voilà, une jolie barre de recherche beaucoup plus du goût des clients en général :)<br />
<a  href="http://www.amicalement-web.net/wp-content/uploads/Image-62.png"><img src="http://www.amicalement-web.net/wp-content/uploads/Image-62-300x32.png" alt="Image 62" title="Image 62" width="300" height="32" class="alignnone size-medium wp-image-352" /></a></p>
<p>Alors bien sûr, cette solution ne fonctionne qu&#8217;avec un nombre limité de filtre, sinon on aurait un rendu un peu moins visuel, mais je pense que ça reste toujours mieux que 2 blocs qui se chevauchent.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.amicalement-web.net/symfony-domptez-les-filtres-de-ladmin-generator/2009/06/16/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Traduire l&#8217;admin generator symfony</title>
		<link>http://www.amicalement-web.net/traduire-ladmin-generator-symfony/2009/06/09/</link>
		<comments>http://www.amicalement-web.net/traduire-ladmin-generator-symfony/2009/06/09/#comments</comments>
		<pubDate>Tue, 09 Jun 2009 12:08:28 +0000</pubDate>
		<dc:creator>Tim</dc:creator>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[admin]]></category>
		<category><![CDATA[i18n]]></category>
		<category><![CDATA[Symfony]]></category>
		<category><![CDATA[traduction]]></category>

		<guid isPermaLink="false">http://www.amicalement-web.net/?p=320</guid>
		<description><![CDATA[Petit billet Symfony du mardi, principalement pour combler un manque que j&#8217;ai pu voir dans google voir même dans la doc Symfony sur l&#8217;admin generator. En effet, on y lit que l&#8217;admin generator est i18n ready, en gros que le système de traduction est en place, qu&#8217;il ne reste plus que le fichier xliff (le [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.amicalement-web.net/wp-content/uploads/computer.png" alt="computer" title="computer" width="48" height="48" class="alignleft size-full wp-image-32" /> Petit billet Symfony du mardi, principalement pour combler un manque que j&#8217;ai pu voir dans google voir même dans la doc <a  href="http://www.symfony-project.org/book/1_2/14-Generators#Administration">Symfony sur l&#8217;admin generator</a>.</p>
<p>En effet, on y lit que l&#8217;admin generator est i18n ready, en gros que le système de traduction est en place, qu&#8217;il ne reste plus que le fichier xliff (le format utilisé pour la traduction dans Symfony) à faire et à placer dans <code>apps/backend/i18n</code> mais aucune ligne qui semble indiquer que les plugins sfPropelPlugin et sfDoctrinePlugin intègre déjà les traductions de la plupart des langues. Or c&#8217;est le cas!<br />
<span id="more-320"></span><br />
Du coup, pour traduire un admin generator en français (entendre par là, le rendre par défaut en français), cela prend 3 lignes. Les deux premières à ajouter dans le fichier <code>config/settings.yml</code></p>

<div class="wp_syntax"><div class="code"><pre class="yaml" style="font-family:monospace;">.all:
  .settings:
    i18n:  on      # Enable interface translation. Set to off if your application should not be translated.
    default_culture:        fr       # Default user culture</pre></div></div>

<p>Puis un lien symbolique à placer:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">ln</span> <span style="color: #660033;">-s</span> <span style="color: #000000; font-weight: bold;">/</span>votre<span style="color: #000000; font-weight: bold;">/</span>chemin<span style="color: #000000; font-weight: bold;">/</span>vers<span style="color: #000000; font-weight: bold;">/</span>symfony<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>plugins<span style="color: #000000; font-weight: bold;">/</span>sfPropelPlugin<span style="color: #000000; font-weight: bold;">/</span>i18n<span style="color: #000000; font-weight: bold;">/</span>sf_admin.fr.xml votre<span style="color: #000000; font-weight: bold;">/</span>chemin<span style="color: #000000; font-weight: bold;">/</span>vers<span style="color: #000000; font-weight: bold;">/</span>votre<span style="color: #000000; font-weight: bold;">/</span>projet<span style="color: #000000; font-weight: bold;">/</span>apps<span style="color: #000000; font-weight: bold;">/</span>backend<span style="color: #000000; font-weight: bold;">/</span>i18n<span style="color: #000000; font-weight: bold;">/</span>sf_admin.xml</pre></div></div>

<p>Et voilà, l&#8217;affaire est dans le sac, un Back office en français, ce qui fait toujours plaisir à des clients français ;)<br />
<img src="http://www.amicalement-web.net/wp-content/uploads/image-54.png" alt="image-54" title="image-54" width="299" height="85" class="alignnone size-full wp-image-321" /></p>
]]></content:encoded>
			<wfw:commentRss>http://www.amicalement-web.net/traduire-ladmin-generator-symfony/2009/06/09/feed/</wfw:commentRss>
		<slash:comments>39</slash:comments>
		</item>
		<item>
		<title>Symfony Admin generator: Transformer un filtre en multi filtre</title>
		<link>http://www.amicalement-web.net/symfony-transformer-un-filtre-en-multi-filtre/2009/05/27/</link>
		<comments>http://www.amicalement-web.net/symfony-transformer-un-filtre-en-multi-filtre/2009/05/27/#comments</comments>
		<pubDate>Wed, 27 May 2009 11:52:49 +0000</pubDate>
		<dc:creator>Tim</dc:creator>
				<category><![CDATA[Astuces]]></category>
		<category><![CDATA[admin]]></category>
		<category><![CDATA[form]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Symfony]]></category>

		<guid isPermaLink="false">http://www.amicalement-web.net/?p=240</guid>
		<description><![CDATA[Petit retour à un billet un peu plus technique le temps de préparer la suite sur twitter. Si il y a bien une chose dont on ne plus se passer une fois qu&#8217;on y a goûté dans symfony, c&#8217;est bien l&#8217;admin generator. Surtout que la doc couvre déjà pas mal de possibilités, mais avec un [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.amicalement-web.net/wp-content/uploads/applications-other.png" alt="applications-other" title="applications-other" width="48" height="48" class="alignleft size-full wp-image-30" /> Petit retour à un billet un peu plus technique le temps de préparer la suite sur twitter. Si il y a bien une chose dont on ne plus se passer une fois qu&#8217;on y a goûté dans symfony, c&#8217;est bien l&#8217;admin generator. Surtout que <a  href="http://www.symfony-project.org/book/1_2/14-Generators#Administration" class="extern">la doc couvre déjà pas mal de possibilités</a>, mais avec un peu d&#8217;imagination on peut vraiment en faire ce qu&#8217;on veut.</p>
<p>Et ca tombe bien, parce que niveau idées tordues, nos chefs de projets ou clients sont rarement les derniers, vous serez d&#8217;accord avec moi ;)</p>
<p>Lors d&#8217;une présentation d&#8217;un back office récemment, on m&#8217;a demandé s&#8217;il était possible de choisir plusieurs valeurs lors du filtrage (en l&#8217;occurence des marques de produits). &laquo;&nbsp;Certainement&nbsp;&raquo; fut ma réponse, même si j&#8217;en avais aucune idée. J&#8217;ai donc jeté un coup d&#8217;oeil sur cette histoire et c&#8217;était finalement l&#8217;histoire de 2min.<br />
<span id="more-240"></span><br />
Par défaut, on avait donc:<br />
<img src="http://www.amicalement-web.net/wp-content/uploads/image-47.png" alt="image-47" title="image-47" width="252" height="140" class="alignnone size-full wp-image-284" /></p>
<p>Sachant que les valeurs de ce filtre allait être limitée, une dizaine à tout casser, j&#8217;ai choisi de transformer le widget en liste de checkbox. Je me suis rendu dans <code>lib/filter/ProduitsFormFilter.class.php</code> et j&#8217;ai simplement rajouter:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> configure<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">// mid étant la clé étrangère du produit vers la marque</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">widgetSchema</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'mid'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> sfWidgetFormPropelChoice<span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
      <span style="color: #0000ff;">'model'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'Marques'</span><span style="color: #339933;">,</span> 
      <span style="color: #0000ff;">'multiple'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">,</span>
      <span style="color: #0000ff;">'expanded'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">,</span>
    <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">validatorSchema</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'mid'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> sfValidatorPropelChoiceMany<span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'required'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'model'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'Marques'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'column'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'mid'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span></pre></div></div>

<p>En l&#8217;occurence, j&#8217;ai simplement changé de widget, l&#8217;admin generator fait finalement le reste car par défaut la fonction de filtrage est capable de gérer une ou plusieurs valeurs! C&#8217;est quand même bien pensé tout ça. Et on obtient donc:<br />
<img src="http://www.amicalement-web.net/wp-content/uploads/image-48.png" alt="image-48" title="image-48" width="313" height="128" class="alignnone size-full wp-image-285" /></p>
<p>Rien de plus, rien de moins, une modification qui montre à quel point le système de formulaire de symfony croisé à l&#8217;admin generator facilite vraiment les choses.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.amicalement-web.net/symfony-transformer-un-filtre-en-multi-filtre/2009/05/27/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>How-to Symfony: Gestion d’un arbre en Propel via les NestedSet &#8211; Part 2</title>
		<link>http://www.amicalement-web.net/how-to-symfony-gestion-d%e2%80%99un-arbre-en-propel-via-les-nestedset-part-2/2009/05/19/</link>
		<comments>http://www.amicalement-web.net/how-to-symfony-gestion-d%e2%80%99un-arbre-en-propel-via-les-nestedset-part-2/2009/05/19/#comments</comments>
		<pubDate>Tue, 19 May 2009 11:31:07 +0000</pubDate>
		<dc:creator>Tim</dc:creator>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[admin]]></category>
		<category><![CDATA[howto]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[nestedset]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[propel]]></category>
		<category><![CDATA[Symfony]]></category>

		<guid isPermaLink="false">http://www.amicalement-web.net/?p=246</guid>
		<description><![CDATA[La dernière fois, on avait vu comment construire l&#8217;aspect graphique de notre gestion de catégorie via Symfony et Propel. On va voir maintenant comme lui associer les actions symfony qui vont bien. Au programme donc dans l&#8217;ordre: la remise en état des liens modifier/supprimer l&#8217;ajout d&#8217;un lien pour ajouter un enfant à une catégorie la [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.amicalement-web.net/wp-content/uploads/system-run.png" alt="system-run" title="system-run" width="48" height="48" class="alignleft size-full wp-image-38" /> La dernière fois, on avait vu comment construire l&#8217;aspect graphique de notre <a  href="/symfony-gestion-d-un-arbre-en-propel-via-les-nestedset-part-1/2009/05/12/">gestion de catégorie</a> via <a  href="http://www.symfony-project.org" class="extern">Symfony</a> et Propel. On va voir maintenant comme lui associer les actions symfony qui vont bien.<br />
Au programme donc dans l&#8217;ordre:</p>
<ul>
<li>la remise en état des liens modifier/supprimer</li>
<li>l&#8217;ajout d&#8217;un lien pour ajouter un enfant à une catégorie</li>
<li>la sauvegarde de l&#8217;ordre de l&#8217;arbre</li>
</ul>
<p>Ya du boulot, alors on se lance.<br />
<span id="more-246"></span><br />
Le seul problème à la remise des liens modifier/supprimer c&#8217;est leur structure HTML, en ul/li qui pose souci avec le plugin NestedSortable. On va donc revoir la chose en les mettant dans un &laquo;&nbsp;p&nbsp;&raquo; avec de simples liens. Pour cela on va éditer dans notre module le fichier <code>lib/categoriesGeneratorHelper.class.php</code> (qui doit être vierge pour l&#8217;instant) et on va surcharger les méthodes, linkToEdit et linkToDelete:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> linkToEdit<span style="color: #009900;">&#40;</span><span style="color: #000088;">$object</span><span style="color: #339933;">,</span> <span style="color: #000088;">$params</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #0000ff;">'&lt;span class=&quot;sf_admin_action_edit&quot;&gt;'</span><span style="color: #339933;">.</span>link_to<span style="color: #009900;">&#40;</span>__<span style="color: #009900;">&#40;</span><span style="color: #000088;">$params</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'label'</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: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'sf_admin'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getUrlForAction</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'edit'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$object</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'&lt;/span&gt;'</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> linkToDelete<span style="color: #009900;">&#40;</span><span style="color: #000088;">$object</span><span style="color: #339933;">,</span> <span style="color: #000088;">$params</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;">$object</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">isNew</span><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: #b1b100;">return</span> <span style="color: #0000ff;">''</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> <span style="color: #0000ff;">'&lt;span class=&quot;sf_admin_action_delete&quot;&gt;'</span><span style="color: #339933;">.</span>link_to<span style="color: #009900;">&#40;</span>__<span style="color: #009900;">&#40;</span><span style="color: #000088;">$params</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'label'</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: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'sf_admin'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getUrlForAction</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'delete'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$object</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'method'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'delete'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'confirm'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #339933;">!</span><span style="color: #990000;">empty</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$params</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'confirm'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> ? __<span style="color: #009900;">&#40;</span><span style="color: #000088;">$params</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'confirm'</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: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'sf_admin'</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">:</span> <span style="color: #000088;">$params</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'confirm'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'&lt;/span&gt;'</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span></pre></div></div>

<p>Les seules modifications concernant le changement d&#8217;un li par un span.</p>
<p>Maintenant on va modifier le partial <code>_list_td_actions.php</code> et donc le rajouter dans notre répertoire templates de notre module:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">&lt;p class=&quot;sf_admin_td_actions list_action&quot;&gt;
  &lt;span class=&quot;sf_admin_action_new&quot;&gt;
    <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> link_to<span style="color: #009900;">&#40;</span>__<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Ajout Enfant'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'categories/addChild?id='</span><span style="color: #339933;">.</span><span style="color: #000088;">$categories</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'messages'</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
  &lt;/span&gt;
  <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$helper</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">linkToEdit</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$categories</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>  <span style="color: #0000ff;">'params'</span> <span style="color: #339933;">=&gt;</span>   <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>  <span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>  <span style="color: #0000ff;">'class_suffix'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'edit'</span><span style="color: #339933;">,</span>  <span style="color: #0000ff;">'label'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'Edit'</span><span style="color: #339933;">,</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
  <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$helper</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">linkToDelete</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$categories</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>  <span style="color: #0000ff;">'params'</span> <span style="color: #339933;">=&gt;</span>   <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>  <span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>  <span style="color: #0000ff;">'confirm'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'Are you sure?'</span><span style="color: #339933;">,</span>  <span style="color: #0000ff;">'class_suffix'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'delete'</span><span style="color: #339933;">,</span>  <span style="color: #0000ff;">'label'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'Delete'</span><span style="color: #339933;">,</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
&lt;/p&gt;</pre></div></div>

<p>A noter qu&#8217;on a ajouté au passage l&#8217;action Ajout d&#8217;enfant.<br />
Il nous reste plus qu&#8217;à rajouter l&#8217;appel à ce partial dans notre <code>_tree.php</code>:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">[...]
&lt;div class=&quot;sort-handle&quot;&gt;
   <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$node</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getTitre</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
&lt;/div&gt;
<span style="color: #000000; font-weight: bold;">&lt;?php</span> include_partial<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'categories/list_td_actions'</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'categories'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$node</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'helper'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$helper</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
[...]</pre></div></div>

<p>Le résultat nous donne ceci:<br />
<a  href="http://www.amicalement-web.net/wp-content/uploads/image-311.png"><img src="http://www.amicalement-web.net/wp-content/uploads/image-311-300x134.png" alt="image-311" title="image-311" width="300" height="134" class="alignnone size-medium wp-image-247" /></a></p>
<p>Alors oui c&#8217;est moche, mais ca fonctionne! Maintenant, on passe un petit coup de CSS comme d&#8217;habitude:</p>

<div class="wp_syntax"><div class="code"><pre class="css" style="font-family:monospace;"><span style="color: #6666ff;">.list_action</span> <span style="color: #00AA00;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">position</span><span style="color: #00AA00;">:</span> <span style="color: #993333;">absolute</span><span style="color: #00AA00;">;</span>
	<span style="color: #000000; font-weight: bold;">right</span><span style="color: #00AA00;">:</span> <span style="color: #cc66cc;">0</span><span style="color: #00AA00;">;</span> <span style="color: #000000; font-weight: bold;">top</span><span style="color: #00AA00;">:</span><span style="color: #cc66cc;">0</span><span style="color: #00AA00;">;</span>
	<span style="color: #000000; font-weight: bold;">width</span><span style="color: #00AA00;">:</span> <span style="color: #933;">350px</span><span style="color: #00AA00;">;</span>
<span style="color: #00AA00;">&#125;</span>
&nbsp;
<span style="color: #6666ff;">.list_action</span> span <span style="color: #00AA00;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">padding</span><span style="color: #00AA00;">:</span> <span style="color: #cc66cc;">0</span> <span style="color: #933;">10px</span> <span style="color: #cc66cc;">0</span> <span style="color: #cc66cc;">0</span><span style="color: #00AA00;">;</span>
<span style="color: #00AA00;">&#125;</span>
&nbsp;
<span style="color: #6666ff;">.current-nesting</span> <span style="color: #00AA00;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">background-color</span><span style="color: #00AA00;">:</span> <span style="color: #cc00cc;">#FFE</span><span style="color: #00AA00;">;</span>
<span style="color: #00AA00;">&#125;</span>
&nbsp;
<span style="color: #cc00cc;">#sf_admin_container</span> <span style="color: #cc00cc;">#sf_admin_content</span> p span<span style="color: #6666ff;">.sf_admin_action_new</span> a <span style="color: #00AA00;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">background</span><span style="color: #00AA00;">:</span><span style="color: #993333;">transparent</span> <span style="color: #993333;">url</span><span style="color: #00AA00;">&#40;</span><span style="color: #ff0000; font-style: italic;">/sfPropelPlugin/images/new.png</span><span style="color: #00AA00;">&#41;</span> <span style="color: #993333;">no-repeat</span> <span style="color: #993333;">scroll</span> <span style="color: #cc66cc;">0</span> <span style="color: #cc66cc;">0</span><span style="color: #00AA00;">;</span>
<span style="color: #00AA00;">&#125;</span>
<span style="color: #cc00cc;">#sf_admin_container</span> <span style="color: #cc00cc;">#sf_admin_content</span> p span<span style="color: #6666ff;">.sf_admin_action_edit</span> a <span style="color: #00AA00;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">background</span><span style="color: #00AA00;">:</span><span style="color: #993333;">transparent</span> <span style="color: #993333;">url</span><span style="color: #00AA00;">&#40;</span><span style="color: #ff0000; font-style: italic;">/sfPropelPlugin/images/edit.png</span><span style="color: #00AA00;">&#41;</span> <span style="color: #993333;">no-repeat</span> <span style="color: #993333;">scroll</span> <span style="color: #cc66cc;">0</span> <span style="color: #cc66cc;">0</span><span style="color: #00AA00;">;</span>
<span style="color: #00AA00;">&#125;</span>
<span style="color: #cc00cc;">#sf_admin_container</span> <span style="color: #cc00cc;">#sf_admin_content</span> p span<span style="color: #6666ff;">.sf_admin_action_delete</span> a<span style="color: #00AA00;">,</span><span style="color: #6666ff;">.link_delete</span> <span style="color: #00AA00;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">background</span><span style="color: #00AA00;">:</span><span style="color: #993333;">transparent</span> <span style="color: #993333;">url</span><span style="color: #00AA00;">&#40;</span><span style="color: #ff0000; font-style: italic;">/sfPropelPlugin/images/delete.png</span><span style="color: #00AA00;">&#41;</span> <span style="color: #993333;">no-repeat</span> <span style="color: #993333;">scroll</span> <span style="color: #cc66cc;">0</span> <span style="color: #cc66cc;">0</span><span style="color: #00AA00;">;</span>
<span style="color: #00AA00;">&#125;</span></pre></div></div>

<p>Et la magie opère de nouveau:<br />
<a  href="http://www.amicalement-web.net/wp-content/uploads/image-331.png"><img src="http://www.amicalement-web.net/wp-content/uploads/image-331-300x90.png" alt="image-331" title="image-331" width="300" height="90" class="alignnone size-medium wp-image-249" /></a></p>
<p>On va maintenant créer les actions liées à cette nouvelle action dans notre fichier d&#8217;actions de notre module:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> executeAddChild<span style="color: #009900;">&#40;</span>sfWebRequest <span style="color: #000088;">$request</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;">categories</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getRoute</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getObject</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// On récupère le parent pour insérer la nouvelle catégorie sous ce parent et on le fait transiter via session </span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getUser</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setAttribute</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'categories.addChild'</span><span style="color: #339933;">,</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">categories</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getPrimaryKey</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'admin_module'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">form</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">configuration</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getForm</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setTemplate</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'new'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #009933; font-style: italic;">/**
   * On surcharge le processForm pour récupérer le parent de la catégorie à ajouter s'il existe
   *
   * @param sfWebRequest $request
   * @param sfForm $form
   */</span>
  <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000000; font-weight: bold;">function</span> processForm<span style="color: #009900;">&#40;</span>sfWebRequest <span style="color: #000088;">$request</span><span style="color: #339933;">,</span> sfForm <span style="color: #000088;">$form</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;">$parent</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getUser</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getAttribute</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'categories.addChild'</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'admin_module'</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><span style="color: #004000;">getUser</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getAttributeHolder</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">remove</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'categories.addChild'</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'admin_module'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #000088;">$root</span> <span style="color: #339933;">=</span> CategoriesPeer<span style="color: #339933;">::</span><span style="color: #004000;">retrieveByPk</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$parent</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #000088;">$form</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getObject</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">insertAsLastChildOf</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$root</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    parent<span style="color: #339933;">::</span><span style="color: #004000;">processForm</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$request</span><span style="color: #339933;">,</span><span style="color: #000088;">$form</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span></pre></div></div>

<p>Si vous cliquez maintenant sur &laquo;&nbsp;Ajouter un enfant&#8217; d&#8217;une des catégories déjà présente vous obtenez alors:<br />
<a  href="http://www.amicalement-web.net/wp-content/uploads/image-34.png"><img src="http://www.amicalement-web.net/wp-content/uploads/image-34-300x180.png" alt="image-34" title="image-34" width="300" height="180" class="alignnone size-medium wp-image-258" /></a></p>
<p>Vu que les tree left et tree right sont définis par Propel, on va les supprimer du formulaire.<br />
Dans notre <code>CategoriesForm.class.php</code> on rajoute:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> configure<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    <span style="color: #990000;">unset</span><span style="color: #009900;">&#40;</span>
      <span style="color: #000088;">$this</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'tree_left'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span>
      <span style="color: #000088;">$this</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'tree_right'</span><span style="color: #009900;">&#93;</span>
    <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span></pre></div></div>

<p>Maintenant, il ne manque plus qu&#8217;à pouvoir sauvegarder les modifications d&#8217;ordre effectuées via javascript. Pour cela on va rajouter une batch actions (elles soumettent un formulaire, il sera ainsi plus facile de faire passer les modifications faites à l&#8217;arbre).<br />
Dans notre <code>generator.yml</code> on rajoute dans l&#8217;entrée list:</p>

<div class="wp_syntax"><div class="code"><pre class="yaml" style="font-family:monospace;">  batch_actions:
    saveOrder:
      label: Sauvegarder ordre
      action: saveOrder</pre></div></div>

<p>Et dans notre partial <code>_list.php</code>, juste avant le javascript:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">&lt;div&gt;
	&lt;input type=&quot;hidden&quot; id=&quot;hashValue&quot; name=&quot;hashValue&quot; value=&quot;&quot; /&gt;
	&lt;input type=&quot;hidden&quot; name=&quot;ids&quot; value=&quot;<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #990000;">empty</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$item</span><span style="color: #009900;">&#41;</span>?<span style="color: #000088;">$item</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getPrimaryKey</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">:</span><span style="color: #0000ff;">'1'</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&quot; /&gt;
&lt;/div&gt;</pre></div></div>

<p>Le premier pour récupérer la sérialisation de la nestedlist en javascript, le deuxième pour passer outre le système de batch qui demande de sélectionner au moins un ids pour lancer l&#8217;action ensuite.</p>
<p>On obtient donc:<br />
<a  href="http://www.amicalement-web.net/wp-content/uploads/image-351.png"><img src="http://www.amicalement-web.net/wp-content/uploads/image-351.png" alt="image-351" title="image-351" width="278" height="100" class="alignnone size-full wp-image-262" /></a></p>
<p>Il ne reste plus qu&#8217;à faire l&#8217;action correspondante dans notre fichier d&#8217;actions:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> executeBatchSaveOrder<span style="color: #009900;">&#40;</span>sfWebRequest <span style="color: #000088;">$request</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$hash</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$request</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getParameter</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'hashValue'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #990000;">parse_str</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$hash</span><span style="color: #339933;">,</span> <span style="color: #000088;">$list</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    CategoriesPeer<span style="color: #339933;">::</span><span style="color: #004000;">saveOrder</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$list</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getUser</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setFlash</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'notice'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'Ordre mis à jour'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span></pre></div></div>

<p>Et les fonctions de sauvegarde dans notre modèle. La fonction mère dans le <code>CategoriesPeer.php</code>:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> static <span style="color: #000000; font-weight: bold;">function</span> saveOrder<span style="color: #009900;">&#40;</span><span style="color: #000088;">$hash</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$root</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #004000;">retrieveRoot</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$hash</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'main_list'</span><span style="color: #009900;">&#93;</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$categorie</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span> 
      <span style="color: #000088;">$u</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #004000;">retrieveByPk</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$categorie</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'id'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
      <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #990000;">empty</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$categorie</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'children'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
      <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$u</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">saveChildren</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$categorie</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'children'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #009900;">&#125;</span>
&nbsp;
      <span style="color: #000088;">$u</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">moveToLastChildOf</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$root</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #000088;">$u</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><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
  <span style="color: #009900;">&#125;</span></pre></div></div>

<p>Qui gère les &laquo;&nbsp;racines&nbsp;&raquo; et son équivalent récursif dans le model <code>Categories.php</code>:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">       <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> saveChildren<span style="color: #009900;">&#40;</span><span style="color: #000088;">$children</span><span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
	  <span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$children</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$child</span><span style="color: #009900;">&#41;</span>
	  <span style="color: #009900;">&#123;</span>
	    <span style="color: #000088;">$item</span> <span style="color: #339933;">=</span> CategoriesPeer<span style="color: #339933;">::</span><span style="color: #004000;">retrieveByPk</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$child</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'id'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #990000;">empty</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$child</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'children'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
	    <span style="color: #009900;">&#123;</span>
	      <span style="color: #000088;">$item</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">saveChildren</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$child</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'children'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	    <span style="color: #009900;">&#125;</span>
	    <span style="color: #000088;">$item</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">moveToLastChildOf</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #000088;">$item</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><span style="color: #339933;">;</span>
	  <span style="color: #009900;">&#125;</span>
	<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Et voilà! Vous pouvez maintenant déplacer vos catégories et sauvegarder leur position dans l&#8217;arbre.</p>
<p>Evidemment toute question, suggestion sont bien sûr les bienvenues. Je pense mettre les source et une démo en ligne très bientôt, voir en faire un plugin si jamais je rencontre un réel intérêt pour ce genre de gadget.</p>
<p>En attendant, une petit illustration en vidéo:<br />
<object id='stUE1TSkxIR11dR15eX1taVV5V' width='425' height='344' type='application/x-shockwave-flash' data='http://www.screentoaster.com/swf/STPlayer.swf'  codebase='http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,115,0'><param name='movie' value='http://www.screentoaster.com/swf/STPlayer.swf'/><param name='allowFullScreen' value='true'/><param name='allowScriptAccess' value='always'/><param name='flashvars' value='video=stUE1TSkxIR11dR15eX1taVV5V'/></object>
<div style='width: 425px; text-align: right;'><a  href="http://www.screentoaster.com/">Screencasts and videos online</a></div>
]]></content:encoded>
			<wfw:commentRss>http://www.amicalement-web.net/how-to-symfony-gestion-d%e2%80%99un-arbre-en-propel-via-les-nestedset-part-2/2009/05/19/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>How-to Symfony: Gestion d&#8217;un arbre en Propel via les NestedSet &#8211; Part 1</title>
		<link>http://www.amicalement-web.net/symfony-gestion-d-un-arbre-en-propel-via-les-nestedset-part-1/2009/05/12/</link>
		<comments>http://www.amicalement-web.net/symfony-gestion-d-un-arbre-en-propel-via-les-nestedset-part-1/2009/05/12/#comments</comments>
		<pubDate>Tue, 12 May 2009 16:34:01 +0000</pubDate>
		<dc:creator>Tim</dc:creator>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[admin]]></category>
		<category><![CDATA[howto]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[nestedset]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[propel]]></category>
		<category><![CDATA[Symfony]]></category>

		<guid isPermaLink="false">http://www.amicalement-web.net/?p=203</guid>
		<description><![CDATA[Les arbres en informatique c&#8217;est un peu le sujet qui fait rêver mais qui embête souvent, moi le premier. Car qui dit arbre, dit récursivité et là en général on commence à se prendre la tête dans les mains. Bah oui gérer quelque chose dont on ne connait pas la fin, ca fait toujours un [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.amicalement-web.net/wp-content/uploads/accessories-text-editor.png" alt="accessories-text-editor" title="accessories-text-editor" width="48" height="48" class="alignleft size-full wp-image-28" /> Les arbres en informatique c&#8217;est un peu le sujet qui fait rêver mais qui embête souvent, moi le premier. Car qui dit arbre, dit <a  href="http://fr.wikipedia.org/wiki/Algorithme_r%C3%A9cursif" class="extern">récursivité</a> et là en général on commence à se prendre la tête dans les mains. Bah oui gérer quelque chose dont on ne connait pas la fin, ca fait toujours un peu peur.</p>
<p>Ici, le principe va être justement de gérer un arbre de catégories, un cas qui peut revenir assez régulièrement. A noter que le concept reprend la version doctrine de <a  href="http://redotheoffice.com/?p=74" class="extern">redotheoffice</a> avec une modification quant au plugin jquery utilisé. En effet, on essaiera ici de gérer l&#8217;ordre des catégories également par drag and drop.<br />
<span id="more-203"></span><br />
En général, quand on part la tête dans le guidon, on crée une table categories, et pour créer la notion de parent, on applique une clé étrangère sur cette même table. Oui mais voilà, autant pour les opérations de suppression et d&#8217;ajout, voir même de déplacement dans l&#8217;arbre cette démarche est très performante, autant quand il s&#8217;agit d&#8217;afficher l&#8217;arbre, la galère commence.<br />
Et pourtant, c&#8217;est bien cette deuxième qu&#8217;on fait à chaque affichage de page!</p>
<p>Il existe pourtant une alternative à cette clé étrangère: les Nested Set. En français, les représentations intervallaires. Le but n&#8217;étant pas d&#8217;expliquer dans le détail ce que c&#8217;est, je vous invite à faire un tour sur développez.com où on retrouve <a  href="http://sqlpro.developpez.com/cours/arborescence/" class="extern">un très bon article illustré à ce sujet</a>.</p>
<p>Brièvement, cette méthode consiste à rajouter des champs en base, left, right et scope permettant de retrouver ses petits. Le diagramme de developpez.com résume bien:<br />
<a  href="http://www.amicalement-web.net/wp-content/uploads/sqltree3.gif"><img src="http://www.amicalement-web.net/wp-content/uploads/sqltree3-300x194.gif" alt="Nested set" title="sqltree3" width="300" height="194" class="size-medium wp-image-204" /></a></p>
<p>Ok, c&#8217;est bien, mais appliquer tout ça à symfony ca doit être lourd! Et bien nan, Propel dans sa dernière version (1.3) intègre déjà cet algorithme en tant que behavior. (Cela sous entend qu&#8217;il faut utiliser symfony 1.2)</p>
<p>Pour se faire, on va donc créer un project vierge en 1.2 histoire d&#8217;éviter tout parasitage qu&#8217;on mènera en 2 parties. La première pour la partie visuel, la deuxième pour la partie code admin generator.</p>
<p>Voici le résultat attendu à la fin de cette première partie:<br />
<a  href="http://www.amicalement-web.net/wp-content/uploads/image-301.png"><img src="http://www.amicalement-web.net/wp-content/uploads/image-301-300x109.png" alt="image-301" title="image-301" width="300" height="109" class="alignnone size-medium wp-image-237" /></a></p>
<p>On se lance donc, notre beau projet est créé, on ouvre le schema.yml que l&#8217;on modifie comme ceci:</p>

<div class="wp_syntax"><div class="code"><pre class="yaml" style="font-family:monospace;">propel:
  categories:
    _attributes: { phpName: Categories, treeMode: NestedSet }
    id: ~
    titre: { type: VARCHAR, size: '50', required: true }
    tree_left: { type: INTEGER, size: '11', required: true, nestedSetLeftKey: true }
    tree_right: { type: INTEGER, size: '11', required: true, nestedSetRightKey: true }
    tree_parent: { type: INTEGER, size: '11', required: true }</pre></div></div>

<p>Vous noterez donc l&#8217;ajout du treeMode et la définition des nesetSetLeftKey et nestedSetRightKey, le tree_parent, n&#8217;est là que pour un certain confort à l&#8217;affichage, mais pas indispensable.</p>
<p>Votre schema ainsi terminé (vous pouvez y rajouter d&#8217;autres tables, même pas peur), on construit la base correspondante (en ayant au préalable configuré notre database.yml évidemment:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">php symfony propel:build-all</pre></div></div>

<p>Et là on constate dans notre dossier lib, deux nouvelles classes que vous n&#8217;avez sans doute jamais vu:<br />
<img src="http://www.amicalement-web.net/wp-content/uploads/image-25.png" alt="image-25" title="image-25" width="304" height="218" class="alignnone size-full wp-image-220" /><br />
- BaseCategoriesNestedSet<br />
- BaseCategoriesNestedSetPeer<br />
qui viennent se placer entre entre les classes classiques et les classes &laquo;&nbsp;Base&nbsp;&raquo;</p>
<p>Afin de jouer rapidement, on va ajouter quelques valeurs test dans data/fixtures/fixtures.yml comme suit:</p>

<div class="wp_syntax"><div class="code"><pre class="yaml" style="font-family:monospace;">Categories:
  cat_1:
    titre: root
    tree_left: 1
    tree_right: 10
  cat_2:
    titre: Hi-Tech
    tree_left: 2
    tree_right: 7
  cat_3:
    titre: Developpement
    tree_left: 3
    tree_right: 4
  cat_4:
    titre: Internet
    tree_left: 5
    tree_right: 6
  cat_5:
    titre: Culture
    tree_left: 8
    tree_right: 9</pre></div></div>

<p>que l&#8217;on va charger dès à présent:</p>

<div class="wp_syntax"><div class="code"><pre class="yaml" style="font-family:monospace;">php symfony propel:data-load</pre></div></div>

<p>A noter que la notion de root est ici très importante. En effet, j&#8217;ai choisi délibérément de travailler avec un seul scope (une seule racine) pour la simple et bonne raison que les manipulations entre scope sont très limitées et l&#8217;intérêt et de pouvoir y faire tout et n&#8217;importe quoi. Il nous faut donc un élément parent de tous, que l&#8217;on ne modifiera jamais, que l&#8217;on n&#8217;affichera jamais.</p>
<p>Maintenant, les choses sérieuses commencent. On va commencer par générer un module admin generator:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">php symfony generate:app main
php symfony propel:generate-admin main Categories</pre></div></div>

<p>Et vous devriez arriver via http://monlocal/categories sur quelque chose d&#8217;assez classique:<br />
<a  href="http://www.amicalement-web.net/wp-content/uploads/image-26.png"><img src="http://www.amicalement-web.net/wp-content/uploads/image-26-300x218.png" alt="image-26" title="image-26" width="300" height="218" class="alignnone size-medium wp-image-221" /></a></p>
<p>L&#8217;idée est maintenant d&#8217;inclure un plugin jquery qui va matérialiser notre arbre, propel ne s&#8217;occupant évidemment que de la logique métier.<br />
J&#8217;ai choisi le très bon <a  href="http://code.google.com/p/nestedsortables/wiki/NestedSortableDocumentation" class="extern">NestedSortable</a> qui répond très bien en terme de performance et très flexible à configurer. Vous pouvez donc télécharger <a  href="http://code.google.com/p/nestedsortables/downloads/list" class="extern">la dernière version</a>. Seul bémol, il nécessite <a  href="http://interface.eyecon.ro" class="extern">Interface</a>, un équivalent à jquery UI, que l&#8217;on va donc <a  href="http://interface.eyecon.ro/download" class="extern">télécharger également</a>.<br />
Pour jQuery, on laissera google faire.</p>
<p>On a donc nos js comme ceci:<br />
<img src="http://www.amicalement-web.net/wp-content/uploads/image-281.png" alt="image-281" title="image-281" width="250" height="111" class="alignnone size-full wp-image-222" /></p>
<p>et on les intègre à notre projet via notre view.yml (la notation en ligne étant plus claire à mon goût):</p>

<div class="wp_syntax"><div class="code"><pre class="yaml" style="font-family:monospace;">  javascripts: 
    - http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js
    - interface.js
    - inestedsortable-1.0.1.pack.js</pre></div></div>

<p>On va devoir maintenant modifier un peu quelques partials car le plugin jquery nécessite une imbrication de tag html, ici on utilisera ce qui semble être le plus apte sémantiquement parlant, des couples ul/li.</p>
<p>L&#8217;idée est donc d&#8217;afficher tout l&#8217;arbre quelque soit le nombre d&#8217;élément et de n&#8217;afficher que l&#8217;info qui nous interesse, en l&#8217;occurrence le titre. Première chose, voici la modification sur le generator.yml:</p>

<div class="wp_syntax"><div class="code"><pre class="yaml" style="font-family:monospace;">      list:
        peer_method: retrieveTree
        max_per_page: 99999
        display: [titre]</pre></div></div>

<p>Vous n&#8217;avez maintenant plus qu&#8217;un seul élément affiché dans votre tableau, l&#8217;élément root et c&#8217;est normal. </p>
<p>La suite se passe dans le partial _list.php. Rapide brief pour ceux qui n&#8217;ont jamais modifier un partial de l&#8217;admin generator. On récupère la version qui est dans le dossier <code>cache/[APP]/[ENV]/modules/auto[MODULE]/templates</code> et on la copie dans notre dossier templates de notre module généré.</p>
<p>Une fois cette opération effectuée, rien n&#8217;a du changer, mais maintenant on a la possibilité de modifier le partial, et voici un extrait de ce qu&#8217;il faut modifier dans la balise tbody:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">     &lt;tbody&gt;
        &lt;tr&gt;
            &lt;td class=&quot;container_main_list&quot; colspan=&quot;3&quot;&gt;
              <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$pager</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getResults</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$i</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$item</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">:</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
                <span style="color: #000000; font-weight: bold;">&lt;?php</span> include_partial<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'categories/tree'</span><span style="color: #339933;">,</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'tree'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$item</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'i'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$i</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'helper'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$helper</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
              <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">endforeach</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
            &lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;</pre></div></div>

<p>Puis dans la partie script tout en base (vous pouvez retirer l&#8217;ancienne fonction checkAll, on ne pourra plus s&#8217;en servir:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #339933;">&lt;</span>script type<span style="color: #339933;">=</span><span style="color: #3366CC;">&quot;text/javascript&quot;</span><span style="color: #339933;">&gt;</span>
<span style="color: #009966; font-style: italic;">/* &lt;![CDATA[ */</span>
$<span style="color: #009900;">&#40;</span>document<span style="color: #009900;">&#41;</span>.<span style="color: #660066;">ready</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: #3366CC;">'#main_list'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">NestedSortable</span><span style="color: #009900;">&#40;</span>
    <span style="color: #009900;">&#123;</span>
      accept<span style="color: #339933;">:</span> <span style="color: #3366CC;">'item_list'</span><span style="color: #339933;">,</span>
      opacity<span style="color: #339933;">:</span> <span style="color: #CC0000;">0.6</span><span style="color: #339933;">,</span>
      autoScroll<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">,</span>
      revert<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">,</span>
      nestingPxSpace<span style="color: #339933;">:</span> <span style="color: #3366CC;">'15'</span><span style="color: #339933;">,</span>
      handle<span style="color: #339933;">:</span> <span style="color: #3366CC;">'.sort-handle'</span><span style="color: #339933;">,</span>
      currentNestingClass<span style="color: #339933;">:</span> <span style="color: #3366CC;">'current-nesting'</span><span style="color: #339933;">,</span>
      noNestingClass<span style="color: #339933;">:</span> <span style="color: #3366CC;">'sf_admin_td_actions'</span><span style="color: #339933;">,</span>
      onChange<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>serialized<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	$<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'#hashValue'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">val</span><span style="color: #009900;">&#40;</span>serialized<span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span>.<span style="color: #660066;">hash</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #009900;">&#125;</span> 
    <span style="color: #009900;">&#125;</span>
  <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009966; font-style: italic;">/* ]]&gt; */</span>
<span style="color: #339933;">&lt;/</span>script<span style="color: #339933;">&gt;</span></pre></div></div>

<p>Bon si vous avez suivi, vous vous doutez que si vous actualisez, symfony vous dira gentiment qu&#8217;il manque le partial _tree.php. Et bien créons le! C&#8217;est la base même du tuto, car c&#8217;est un partial récursif, qui va donc s&#8217;auto inclure:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">&lt;ul <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #990000;">empty</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$i</span><span style="color: #009900;">&#41;</span>?<span style="color: #0000ff;">'id=&quot;main_list&quot; '</span><span style="color: #339933;">:</span><span style="color: #0000ff;">''</span><span style="color: #009900;">&#41;</span><span style="color: #000000; font-weight: bold;">?&gt;</span>class=&quot;page-list&quot;&gt;
  <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$tree</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getChildren</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$node</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">:</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
    &lt;li class=&quot;item_list clear-element&quot; id=&quot;ele-<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$node</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getPrimaryKey</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&quot;&gt;
      &lt;div class=&quot;sort-handle&quot;&gt;
        <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$node</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getTitre</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
			&lt;/div&gt;
      <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$node</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">hasChildren</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">:</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
            <span style="color: #000000; font-weight: bold;">&lt;?php</span> include_partial<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'categories/tree'</span><span style="color: #339933;">,</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'tree'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$node</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'helper'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$helper</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
      <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">endif</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
    &lt;/li&gt;
  <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">endforeach</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
&lt;/ul&gt;</pre></div></div>

<p>Et là, un petit coup de F5 et la magie comment à opérer. Vous pouvez maintenant déplacer les éléments de branche en branche tel un hibou&#8230; bref, ca fonctionne!</p>
<p>Un petit coup de css s&#8217;impose pour que ca se rapproche le plus possible des autres modules classiques:</p>

<div class="wp_syntax"><div class="code"><pre class="css" style="font-family:monospace;"><span style="color: #cc00cc;">#sf_admin_container</span> table tr<span style="color: #3333ff;">:hover </span><span style="color: #00AA00;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">background-color</span><span style="color: #00AA00;">:</span> <span style="color: #cc00cc;">#FFF</span><span style="color: #00AA00;">;</span>
<span style="color: #00AA00;">&#125;</span>
&nbsp;
ul<span style="color: #cc00cc;">#menu</span> li<span style="color: #00AA00;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">list-style</span><span style="color: #00AA00;">:</span> <span style="color: #993333;">none</span><span style="color: #00AA00;">;</span>
	<span style="color: #000000; font-weight: bold;">display</span><span style="color: #00AA00;">:</span> <span style="color: #993333;">inline</span><span style="color: #00AA00;">;</span>
	<span style="color: #000000; font-weight: bold;">padding</span><span style="color: #00AA00;">:</span> <span style="color: #cc66cc;">0</span> <span style="color: #933;">10px</span> <span style="color: #cc66cc;">0</span> <span style="color: #cc66cc;">0</span> <span style="color: #00AA00;">;</span>
<span style="color: #00AA00;">&#125;</span>
&nbsp;
<span style="color: #cc00cc;">#admin_content</span> ul <span style="color: #00AA00;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">margin</span><span style="color: #00AA00;">:</span> <span style="color: #cc66cc;">0</span><span style="color: #00AA00;">;</span>
	<span style="color: #000000; font-weight: bold;">list-style-position</span><span style="color: #00AA00;">:</span> <span style="color: #993333;">inside</span><span style="color: #00AA00;">;</span>
<span style="color: #00AA00;">&#125;</span>
&nbsp;
<span style="color: #cc00cc;">#admin_content</span> ul<span style="color: #cc00cc;">#list-container</span> <span style="color: #00AA00;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">margin-left</span><span style="color: #00AA00;">:</span> <span style="color: #933;">1em</span><span style="color: #00AA00;">;</span>
	<span style="color: #000000; font-weight: bold;">background-color</span><span style="color: #00AA00;">:</span> <span style="color: #cc00cc;">#FFF</span> <span style="color: #00AA00;">;</span>
	<span style="color: #000000; font-weight: bold;">padding</span><span style="color: #00AA00;">:</span> <span style="color: #933;">10px</span> <span style="color: #00AA00;">;</span>
<span style="color: #00AA00;">&#125;</span>
&nbsp;
<span style="color: #cc00cc;">#admin_content</span> ul li <span style="color: #00AA00;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">list-style-position</span><span style="color: #00AA00;">:</span> <span style="color: #993333;">inside</span><span style="color: #00AA00;">;</span>
<span style="color: #00AA00;">&#125;</span>
&nbsp;
li img <span style="color: #00AA00;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">vertical-align</span><span style="color: #00AA00;">:</span> text-<span style="color: #000000; font-weight: bold;">bottom</span> <span style="color: #00AA00;">;</span>
<span style="color: #00AA00;">&#125;</span>
&nbsp;
<span style="color: #cc00cc;">#list-container</span> li span <span style="color: #00AA00;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">cursor</span><span style="color: #00AA00;">:</span> <span style="color: #993333;">pointer</span><span style="color: #00AA00;">;</span>
<span style="color: #00AA00;">&#125;</span>
&nbsp;
<span style="color: #cc00cc;">#sortHelper</span> <span style="color: #00AA00;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">background</span><span style="color: #00AA00;">:</span> <span style="color: #cc00cc;">#FFE</span><span style="color: #00AA00;">;</span>
<span style="color: #00AA00;">&#125;</span>
&nbsp;
<span style="color: #cc00cc;">#dragHelper</span> <span style="color: #00AA00;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">background-color</span><span style="color: #00AA00;">:</span> <span style="color: #cc00cc;">#EEE</span><span style="color: #00AA00;">;</span>
<span style="color: #00AA00;">&#125;</span>
&nbsp;
div<span style="color: #6666ff;">.wrap</span> <span style="color: #00AA00;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">border</span><span style="color: #00AA00;">:</span><span style="color: #933;">1px</span> <span style="color: #993333;">solid</span> <span style="color: #cc00cc;">#BBBBBB</span><span style="color: #00AA00;">;</span>
	<span style="color: #000000; font-weight: bold;">padding</span><span style="color: #00AA00;">:</span> <span style="color: #933;">1em</span> <span style="color: #933;">1em</span> <span style="color: #933;">1em</span> <span style="color: #933;">1em</span><span style="color: #00AA00;">;</span>
<span style="color: #00AA00;">&#125;</span>
<span style="color: #cc00cc;">#main_list</span><span style="color: #00AA00;">,</span><span style="color: #cc00cc;">#contenu_list</span> <span style="color: #00AA00;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">width</span><span style="color: #00AA00;">:</span> <span style="color: #933;">700px</span><span style="color: #00AA00;">;</span>
<span style="color: #00AA00;">&#125;</span>
&nbsp;
<span style="color: #cc00cc;">#main_list</span> li <span style="color: #00AA00;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">list-style-type</span><span style="color: #00AA00;">:</span> <span style="color: #993333;">none</span><span style="color: #00AA00;">;</span>
	<span style="color: #000000; font-weight: bold;">list-style-position</span><span style="color: #00AA00;">:</span> <span style="color: #993333;">none</span><span style="color: #00AA00;">;</span>
<span style="color: #00AA00;">&#125;</span>
&nbsp;
<span style="color: #6666ff;">.page-list</span> <span style="color: #00AA00;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">list-style</span><span style="color: #00AA00;">:</span> <span style="color: #993333;">none</span><span style="color: #00AA00;">;</span>
	<span style="color: #000000; font-weight: bold;">margin</span><span style="color: #00AA00;">:</span> <span style="color: #cc66cc;">0</span><span style="color: #00AA00;">;</span>
	<span style="color: #000000; font-weight: bold;">padding</span><span style="color: #00AA00;">:</span> <span style="color: #cc66cc;">0</span><span style="color: #00AA00;">;</span>
	<span style="color: #000000; font-weight: bold;">display</span><span style="color: #00AA00;">:</span> <span style="color: #993333;">block</span><span style="color: #00AA00;">;</span>
<span style="color: #00AA00;">&#125;</span>
&nbsp;
<span style="color: #6666ff;">.clear-element</span> <span style="color: #00AA00;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">clear</span><span style="color: #00AA00;">:</span> <span style="color: #993333;">both</span><span style="color: #00AA00;">;</span>
	<span style="color: #000000; font-weight: bold;">position</span><span style="color: #00AA00;">:</span> <span style="color: #993333;">relative</span><span style="color: #00AA00;">;</span>
<span style="color: #00AA00;">&#125;</span>
&nbsp;
<span style="color: #6666ff;">.sort-handle</span> <span style="color: #00AA00;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">cursor</span><span style="color: #00AA00;">:</span>move<span style="color: #00AA00;">;</span>
	<span style="color: #000000; font-weight: bold;">margin</span><span style="color: #00AA00;">:</span> <span style="color: #933;">0.25em</span> <span style="color: #cc66cc;">0</span> <span style="color: #cc66cc;">0</span> <span style="color: #cc66cc;">0</span><span style="color: #00AA00;">;</span>
	<span style="color: #000000; font-weight: bold;">padding</span><span style="color: #00AA00;">:</span> <span style="color: #933;">2px</span> <span style="color: #cc66cc;">0</span> <span style="color: #933;">2px</span> <span style="color: #933;">18px</span><span style="color: #00AA00;">;</span>
	<span style="color: #000000; font-weight: bold;">background</span><span style="color: #00AA00;">:</span> <span style="color: #cc00cc;">#f3F3F3</span> <span style="color: #000000; font-weight: bold;">left</span> <span style="color: #993333;">center</span> <span style="color: #993333;">url</span><span style="color: #00AA00;">&#40;</span><span style="color: #ff0000; font-style: italic;">../images/toggleexpanddark.png</span><span style="color: #00AA00;">&#41;</span> <span style="color: #993333;">no-repeat</span><span style="color: #00AA00;">;</span>
<span style="color: #00AA00;">&#125;</span>
&nbsp;
div<span style="color: #6666ff;">.item-title</span> <span style="color: #00AA00;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">background-color</span><span style="color: #00AA00;">:</span> <span style="color: #cc00cc;">#DDD</span><span style="color: #00AA00;">;</span>
	<span style="color: #000000; font-weight: bold;">margin</span><span style="color: #00AA00;">:</span> <span style="color: #933;">0.25em</span> <span style="color: #cc66cc;">0</span> <span style="color: #cc66cc;">0</span> <span style="color: #cc66cc;">0</span><span style="color: #00AA00;">;</span>
	<span style="color: #000000; font-weight: bold;">padding</span><span style="color: #00AA00;">:</span> <span style="color: #933;">2px</span> <span style="color: #cc66cc;">0</span> <span style="color: #933;">2px</span> <span style="color: #933;">18px</span><span style="color: #00AA00;">;</span>
<span style="color: #00AA00;">&#125;</span>
&nbsp;
<span style="color: #6666ff;">.list-action</span> <span style="color: #00AA00;">&#123;</span>
	<span style="color: #808080; font-style: italic;">/*background-color: #f3F3F3;*/</span>
	<span style="color: #000000; font-weight: bold;">position</span><span style="color: #00AA00;">:</span> <span style="color: #993333;">absolute</span><span style="color: #00AA00;">;</span>
	<span style="color: #000000; font-weight: bold;">right</span><span style="color: #00AA00;">:</span> <span style="color: #cc66cc;">0</span><span style="color: #00AA00;">;</span> <span style="color: #000000; font-weight: bold;">top</span><span style="color: #00AA00;">:</span><span style="color: #cc66cc;">0</span><span style="color: #00AA00;">;</span>
	<span style="color: #000000; font-weight: bold;">width</span><span style="color: #00AA00;">:</span> <span style="color: #933;">350px</span><span style="color: #00AA00;">;</span>
<span style="color: #00AA00;">&#125;</span></pre></div></div>

<p>Et l&#8217;image qui va bien (récupéré de redotheoffice):<br />
<img src="http://www.amicalement-web.net/wp-content/uploads/toggleexpanddark.png" alt="toggleexpanddark" title="toggleexpanddark" width="16" height="16" class="alignnone size-full wp-image-229" /></p>
<p>Et voilà, la première étape s&#8217;achève ici, on peut s&#8217;amuser à déplacer ces éléments. La suite très prochainement, pour remettre les actions et ajouter une action pour sauvegarder l&#8217;arbre.</p>
<p>A noter que je ne détaille pas forcément toutes les étapes de création d&#8217;un projet symfony, <a  href="http://www.symfony-project.org/jobeet/1_2/Propel/en/" class="extern">Jobeet</a> le fais si bien.</p>
<p>Évidemment, toutes remarques, questions, propositions, meilleurs solutions sont les bienvenues! Je suis aussi là pour apprendre : )</p>
]]></content:encoded>
			<wfw:commentRss>http://www.amicalement-web.net/symfony-gestion-d-un-arbre-en-propel-via-les-nestedset-part-1/2009/05/12/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Symfony: Automatiser la navigation dans votre admin-generator</title>
		<link>http://www.amicalement-web.net/symfony-automatiser-la-navigation-dans-votre-admin-generator/2009/03/19/</link>
		<comments>http://www.amicalement-web.net/symfony-automatiser-la-navigation-dans-votre-admin-generator/2009/03/19/#comments</comments>
		<pubDate>Thu, 19 Mar 2009 12:07:57 +0000</pubDate>
		<dc:creator>Tim</dc:creator>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[admin]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[snippet]]></category>
		<category><![CDATA[Symfony]]></category>

		<guid isPermaLink="false">http://www.amicalement-web.net/?p=174</guid>
		<description><![CDATA[Petite reprise d&#8217;activité du blog après quelques journée assez chargées. Et me voilà vous proposer une pré alpha d&#8217;un petit snippet pour symfony 1.2 qui vise à automatiser la génération d&#8217;un menu pour l&#8217;admin générator qui malheureusement ne propose rien de semblable à l&#8217;heure actuelle. Et combien il devient vite barbant de rajouter les liens [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.amicalement-web.net/wp-content/uploads/accessories-text-editor.png" alt="accessories-text-editor" title="accessories-text-editor" width="48" height="48" class="alignleft size-full wp-image-28" /> Petite reprise d&#8217;activité du blog après quelques journée assez chargées. Et me voilà vous proposer une pré alpha d&#8217;un petit snippet pour symfony 1.2 qui vise à automatiser la génération d&#8217;un menu pour l&#8217;admin générator qui malheureusement ne propose rien de semblable à l&#8217;heure actuelle.<br />
Et combien il devient vite barbant de rajouter les liens de vos nouveaux modules à la main dans votre layout.</p>
<p>Voici donc une solution possible et facile à mettre en place en se basant sur le fichier de routing.<br />
<span id="more-174"></span><br />
En effet, à chaque ajout de module d&#8217;admin via la célèbre:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">php symfony propel:generate-admin backend MonModel</pre></div></div>

<p>Le fichier de routing.yml de l&#8217;application en question est modifié avec quelque chose qui ressemble à ça par défaut:</p>

<div class="wp_syntax"><div class="code"><pre class="yml" style="font-family:monospace;">offres:
  class: sfPropelRouteCollection
  options:
    model:               Offres
    module:              offres
    prefix_path:         offres
    column:              oid
    with_wildcard_routes: true</pre></div></div>

<p>J&#8217;ai donc fait un petit snippet qui parse ce yml:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> myAdminMenu 
<span style="color: #009900;">&#123;</span>
  <span style="color: #000000; font-weight: bold;">public</span> static <span style="color: #000000; font-weight: bold;">function</span> getLinks<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$array</span> <span style="color: #339933;">=</span> sfYaml<span style="color: #339933;">::</span><span style="color: #004000;">load</span><span style="color: #009900;">&#40;</span>sfConfig<span style="color: #339933;">::</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'sf_app_config_dir'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'/routing.yml'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$links</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$array</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$k</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$v</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
      <span style="color: #666666; font-style: italic;">// On n'affiche pas les infos présentes par défaut dans le routing</span>
      <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$k</span> <span style="color: #339933;">!=</span> <span style="color: #0000ff;">'homepage'</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #000088;">$k</span> <span style="color: #339933;">!=</span> <span style="color: #0000ff;">'default'</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #000088;">$k</span> <span style="color: #339933;">!=</span> <span style="color: #0000ff;">'default_index'</span><span style="color: #009900;">&#41;</span>
      <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$links</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$k</span><span style="color: #339933;">;</span>
      <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #990000;">sort</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$links</span><span style="color: #339933;">,</span>SORT_STRING<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// On trie par ordre alphabétique</span>
&nbsp;
    <span style="color: #b1b100;">return</span> <span style="color: #000088;">$links</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Et il ne reste plus qu&#8217;à boucler dessus dans votre layout.php:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">&lt;ul id=&quot;menu&quot;&gt;
  	<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span>myAdminMenu<span style="color: #339933;">::</span><span style="color: #004000;">getLinks</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$link</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">:</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
  		&lt;li&gt;&lt;a href=&quot;<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> url_for<span style="color: #009900;">&#40;</span><span style="color: #000088;">$link</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'/index'</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&quot;&gt;<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #990000;">ucfirst</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$link</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&lt;/a&gt;&lt;/li&gt;
  	<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">endforeach</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
&lt;/ul&gt;</pre></div></div>

<p>Bon j&#8217;imagine bien qu&#8217;il est perfectible au possible surtout si on configure un nom différent du module à la génération du module mais on fera avancer les choses quand le besoin s&#8217;en fera sentir.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.amicalement-web.net/symfony-automatiser-la-navigation-dans-votre-admin-generator/2009/03/19/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
<!-- WP Super Cache is installed but broken. The path to wp-cache-phase1.php in wp-content/advanced-cache.php must be fixed! -->
