<?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; Tutorials</title>
	<atom:link href="http://www.amicalement-web.net/categorie/tutorial/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>De PHP à Ruby : votre premier index.php en Ruby</title>
		<link>http://www.amicalement-web.net/de-php-a-ruby-votre-premier-index-php-en-ruby/2011/05/23/</link>
		<comments>http://www.amicalement-web.net/de-php-a-ruby-votre-premier-index-php-en-ruby/2011/05/23/#comments</comments>
		<pubDate>Mon, 23 May 2011 13:39:53 +0000</pubDate>
		<dc:creator>Vince</dc:creator>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[http]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[rack]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://www.amicalement-web.net/?p=1795</guid>
		<description><![CDATA[Je suis un développeur PHP depuis environ 10 ans maintenant, et j&#8217;en suis plutôt content à vrai dire. J&#8217;aime écrire des web apps, et ça tombe bien, PHP a été initialement créé pour ça. Bien. Et après ? Je suis curieux. Diantre. Il m&#8217;a donc fallu aller satisfaire ma curiosité. J&#8217;ai essayé Ruby on Rails, [...]]]></description>
			<content:encoded><![CDATA[<p><a  href="http://www.amicalement-web.net/wp-content/uploads/rubys.jpg"><img src="http://www.amicalement-web.net/wp-content/uploads/rubys.jpg" alt="" title="rubys" width="600" height="100" class="alignnone size-full wp-image-1808" /></a><br />
Je suis un développeur PHP depuis environ 10 ans maintenant, et j&#8217;en suis plutôt content à vrai dire. J&#8217;aime écrire des web apps, et ça tombe bien, PHP a été initialement créé pour ça. Bien. Et après ? Je suis curieux. Diantre. Il m&#8217;a donc fallu aller satisfaire ma curiosité. J&#8217;ai essayé Ruby on Rails, mais comme je voulais aussi apprendre le Ruby, ce n&#8217;était pour moi pas la bonne façon de commencer. J&#8217;ai donc voulu écrire ma première web app en Ruby, comme je l&#8217;ai fait il y a 10 ans de cela avec mon premier <em><?php echo 'hello world'; ?></em> dans un <em>index.php</em>. Nous y voici.<br />
<span id="more-1795"></span></p>
<h3>PHP : un langage web</h3>
<p>Comme je l&#8217;ai dit, <strong>PHP est un langage web</strong>. Il propose donc de base un ensemble de choses utiles pour interagir avec un environnement HTTP (entre autres). Vous n&#8217;avez pas pu passer à côté de nos chers amis <em>$_GET</em> et <em>$_POST</em> par exemple (sauf si vous avez appris PHP avec symfony mais bon, pas sur que ce soit le meilleur moyen). Ensuite PHP est un langage de template à lui tout seul. Vous mélangez du PHP au sein d&#8217;un fichier HTML et vous obtenez ce que vous souhaitez, sans effort particulier. Prenons le fichier <em>index.php</em> suivant :</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">&lt;h1&gt;Hello world&lt;/h1&gt;
&lt;p&gt;
  Hello <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$_GET</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'name'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
&lt;/p&gt;</pre></div></div>

<p>Vous utilisez ensuite Apache et mod_php pour l&#8217;afficher (avec MAMP, WAMP, ou ce que vous voulez) en appelant <em>index.php?name=Karamazof</em> et vous êtes les rois du monde. Admettons. Attaquons les choses sérieuses.</p>
<h3>Ruby : un langage tout court</h3>
<p>C&#8217;est là que ça se gâte. Tout d&#8217;abord je tiens à dire que je n&#8217;ai pas beaucoup d&#8217;expérience en Ruby, il y a de ça un mois je n&#8217;en avais encore jamais fait, soyez indulgents ;-). Mais j&#8217;ai tout de suite été confronté à l&#8217;évidence : <strong>Ruby (comme Python d&#8217;ailleurs) n&#8217;est pas un langage web</strong>. Pas qu&#8217;on ne peut pas faire de web avec (ça se saurait), mais il n&#8217;a pas été initialement prévu pour cela. Qu&#8217;est-ce que cela implique ? Vous n&#8217;avez pas de raccourcis/fonctions pour accéder à l&#8217;environnement HTTP comme vous pouvez avoir avec PHP et ses <em>$_GET</em> et <em>$_POST</em>.</p>
<p>Il faut donc en Ruby utiliser une <strong>couche standardisée</strong> (ou presque) entre votre code et le serveur web, couche qui vous donnera la possibilité d&#8217;accéder aux éléments d&#8217;une requête HTTP et de renvoyer une réponse à afficher. En Ruby le &laquo;&nbsp;standard de facto&nbsp;&raquo; est maintenant Rack (rien à voir avec Rake). Rack est une couche d&#8217;abstraction entre le serveur web (peu importe lequel) et votre code. Vous devrez bien sûr adapter votre code pour qu&#8217;il soit compatible Rack et puisse être exécuté sur n&#8217;importe quel serveur web qui propose une interface Rack (à peu prêt tous maintenant). C&#8217;est ce que je vous montre ci-dessous.</p>
<p>À noter que le problème est le même pour Pyhon et que Rack a d&#8217;ailleurs été inspiré de la solution trouvée pour Python qui s&#8217;appelle WSGI.</p>
<h3>Une application Rack</h3>
<p>Une application Rack qu&#8217;est-ce que c&#8217;est ? C&#8217;est une application qui a comme point d&#8217;entrée une méthode <em>call</em> qui prend un tableau en paramètre (souvent nommé <em>env</em>) et qui renvoie un tableau contenant le statut HTTP, les headers HTTP, et le contenu. Vous pouvez aller consulter le <a  href="http://chneukirchen.org/blog/archive/2007/02/introducing-rack.html">post de blog</a> d&#8217;origine ou <a  href="http://en.wikipedia.org/wiki/Rack_%28Web_server_interface%29">l&#8217;article Wikipedia</a>.</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> HelloWorld
  <span style="color:#9966CC; font-weight:bold;">def</span> call<span style="color:#006600; font-weight:bold;">&#40;</span>env<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">200</span>, <span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#996600;">&quot;Content-Type&quot;</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;text/plain&quot;</span><span style="color:#006600; font-weight:bold;">&#125;</span>, <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">&quot;Hello world!&quot;</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#93;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Heureusement vous pouvez inclure des modules rack pour vous faciliter la vie, et notamment pour construire un object Request à partir de cet environnement et un objet Response pour faciliter la création de la réponse à envoyer au navigateur. À noter que vous pouvez très bien utiliser <em>env</em> et retourner un tableau de contenu vous même comme l&#8217;exemple ci dessus, mais c&#8217;est je trouve pas le plus pratique. Voici un exemple de code ci-dessous :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#008000; font-style:italic;">#hello_world.rb</span>
&nbsp;
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'rack/request'</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'rack/response'</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">class</span> HelloWorld
  <span style="color:#9966CC; font-weight:bold;">def</span> call<span style="color:#006600; font-weight:bold;">&#40;</span>env<span style="color:#006600; font-weight:bold;">&#41;</span>
      request = <span style="color:#6666ff; font-weight:bold;">Rack::Request</span>.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span>env<span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
      response = <span style="color:#6666ff; font-weight:bold;">Rack::Response</span>.<span style="color:#9900CC;">new</span>
&nbsp;
      response.<span style="color:#9900CC;">write</span> <span style="color:#996600;">&quot;&lt;h1&gt;Hello world&lt;/h1&gt;&quot;</span>
      response.<span style="color:#9900CC;">write</span> <span style="color:#996600;">&quot;&lt;p&gt;&quot;</span>
      response.<span style="color:#9900CC;">write</span> <span style="color:#996600;">&quot;  Hello &quot;</span> <span style="color:#006600; font-weight:bold;">+</span> request.<span style="color:#9900CC;">GET</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'name'</span><span style="color:#006600; font-weight:bold;">&#93;</span>
      response.<span style="color:#9900CC;">write</span> <span style="color:#996600;">&quot;&lt;/p&gt;&quot;</span>
      response.<span style="color:#9900CC;">finish</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Pour tester votre application vous avez plusieurs choix (dont Apache si vous le souhaitez) mais je vous conseille pour commencer d&#8217;utiliser rackup qui vous permettra d&#8217;avoir un serveur de test assez facilement. Pour ce faire créez un fichier <em>config.ru</em> avec le contenu suivant dedans :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#008000; font-style:italic;">#config.ru</span>
&nbsp;
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'hello_world'</span>
&nbsp;
run HelloWorld.<span style="color:#9900CC;">new</span></pre></div></div>

<p>Rien de bien compliqué ici, on inclut le fichier <em>hello_word.rb</em> précédemment créé et on dit à rackup de lancer notre application. </p>
<p>Installez ensuite les gem nécessaires :</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">sudo</span> gem <span style="color: #c20cb9; font-weight: bold;">install</span> webrick rackup</pre></div></div>

<p>Puis pour lancez le serveur web (webrick par défaut) avec rackup, placez vous dans le répertoire contenant vos fichiers puis exécutez la commande suivante :</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">rackup -I.</pre></div></div>

<p>Vous devriez pouvoir vous rendre sur http://127.0.0.1:9292/?name=Vincent et voir votre première page web en Ruby !</p>
<p>Petite précision, si vous souhaitez modifier votre code et voir les modifications sans relancer le serveur web, utilisez shotgun à la place de rackup (à n&#8217;utiliser qu&#8217;en développement) :</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">sudo</span> gem <span style="color: #c20cb9; font-weight: bold;">install</span> shotgun
shotgun -I.</pre></div></div>

<h3>Conclusion</h3>
<p>Ruby est un langage fort sympathique avec beaucoup de possibilités que PHP ne permet même pas d&#8217;entrevoir. En revanche en ce qui concerne le web on comprend un peu mieux pourquoi PHP est beaucoup plus populaire que Ruby pour faire du web : PHP a été prévu pour, pas Ruby. Mais je ne saurais vous conseiller d&#8217;essayer le Ruby, on y prend vite goût.</p>
<p><small>Crédit photo : http://www.flickr.com/photos/pswansen/41832591/</small></p>
]]></content:encoded>
			<wfw:commentRss>http://www.amicalement-web.net/de-php-a-ruby-votre-premier-index-php-en-ruby/2011/05/23/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Doctrine2 : au revoir ActiveRecord, bonjour DataMapper !</title>
		<link>http://www.amicalement-web.net/doctrine2-au-revoir-activerecord-bonjour-datamapper/2011/01/03/</link>
		<comments>http://www.amicalement-web.net/doctrine2-au-revoir-activerecord-bonjour-datamapper/2011/01/03/#comments</comments>
		<pubDate>Mon, 03 Jan 2011 08:55:29 +0000</pubDate>
		<dc:creator>Vince</dc:creator>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[active record]]></category>
		<category><![CDATA[datamapper]]></category>
		<category><![CDATA[doctrine]]></category>
		<category><![CDATA[orm]]></category>

		<guid isPermaLink="false">http://www.amicalement-web.net/?p=1413</guid>
		<description><![CDATA[Aujourd&#8217;hui nous allons parler d&#8217;un ORM pour PHP que vous connaissez sûrement : Doctrine (si vous ne le connaissez pas je ne peux rien pour vous, ou alors juste vous donner l&#8217;adresse du site). Cela fait maintenant quelques années que Doctrine 1 a vu le jour et a été utilisé dans nombre de projets symfony, [...]]]></description>
			<content:encoded><![CDATA[<p><a  href="http://www.amicalement-web.net/doctrine2-au-revoir-activerecord-bonjour-datamapper/2011/01/03/"><img src="http://www.amicalement-web.net/wp-content/uploads/doctrine1.png" alt="" title="doctrine" width="614" height="100" class="alignnone size-full wp-image-1655" /></a><br />
Aujourd&#8217;hui nous allons parler d&#8217;un <a  href="http://fr.wikipedia.org/wiki/Mapping_objet-relationnel">ORM</a> pour PHP que vous connaissez sûrement : Doctrine (si vous ne le connaissez pas je ne peux rien pour vous, ou alors juste vous donner <a  href="http://www.doctrine-project.org">l&#8217;adresse du site</a>). Cela fait maintenant quelques années que Doctrine 1 a vu le jour et a été utilisé dans nombre de projets symfony, mais il est temps pour lui de prendre sa retraite, et par l&#8217;occasion de dire au revoir (ou presque) au design pattern <a  href="http://www.martinfowler.com/eaaCatalog/activeRecord.html">Active Record</a> qui va avec. D&#8217;ailleurs ça tombe bien, Doctrine 2 vient de sortir sa première version stable !<br />
<span id="more-1413"></span></p>
<h3>Modèle et persistance</h3>
<p>La première chose que l&#8217;on m&#8217;a apprise lorsqu&#8217;on m&#8217;a parlé de MVC, c&#8217;était que le M (pour model) devait contenir la <strong>logique &laquo;&nbsp;métier&nbsp;&raquo;</strong> de notre application. Quand on parle de métier, c&#8217;est bien ce qui est spécifique à l&#8217;application développée. La partie Modèle d&#8217;une calculatrice doit savoir calculer (Lapalisse si tu m&#8217;entends, elle est pour toi celle là), la partie Modèle d&#8217;une gestion de facturation doit savoir gérer les relances, les impayés, les factures &#8230; Bon bah très bien tout ça.</p>
<p>Et là c&#8217;est le drame, vous vous mettez à utiliser symfony et un des deux principaux ORM du monde PHP : <strong>Propel ou Doctrine</strong>. Tout d&#8217;abord vous trouvez ça chouette, vous pouvez faire un <strong>->save() ou un ->delete()</strong> directement sur votre objet, la classe. Mais qu&#8217;est-ce que ça veut dire ça ? Ca veut dire que votre objet connait la façon dont il doit persister. Il est fortement couplé à la façon dont vous voulez l&#8217;enregistrer, dans notre cas dans une base de données.</p>
<p>C&#8217;est assez facile à voir, regardez le graphe d&#8217;héritage de votre objet, pour Doctrine tous les objets de votre modèle héritent de la classe <code>Doctrine_Record</code>. Et si, par le plus grand des hasards, vous voulez réutiliser votre logique métier dans une autre application PHP qui n&#8217;a rien à voir avec celle que vous développez avec symfony/Doctrine ? Vous êtes bons pour de jolis copier/coller.</p>
<h3>DataMapper à la rescousse</h3>
<p>L&#8217;idéal pour réaliser des M qui ne font que du M, c&#8217;est de n&#8217;avoir que des <strong>PPO (Plain PHP Object)</strong>, c&#8217;est à dire des objets PHP standards (qui n&#8217;héritent pas d&#8217;une classe comme <code>Doctrine_Record</code> par exemple). Ces PPO doivent réaliser la logique métier de notre application (le M), et une autre partie de l&#8217;application doit pouvoir prendre ce PPO et le faire persister quelque part (système de fichier, base de données, &#8230;). C&#8217;est là qu&#8217;intervient le design pattern <a  href="http://martinfowler.com/eaaCatalog/dataMapper.html"><strong>DataMapper</strong></a>. Il va permettre de faire le lien entre l&#8217;objet (l&#8217;Entity dans le jargon Doctrine2) et la façon dont il devra persister. Dans Doctrine2, c&#8217;est l&#8217;<a  href="http://www.doctrine-project.org/api/orm/2.0/doctrine/orm/entitymanager.html">Entity Manager</a> qui va réaliser le rôle de DataMapper avec sa méthode flush() qui sauvegarde les changements dans la base de données.</p>
<h3>Unit of Work, le copain du DataMapper</h3>
<p>La méthode ->flush() de l&#8217;EntityManager va permettre d&#8217;enregistrer les changements effectués sur les PPO dans la base de données. Ces changements auront été notifiés au préalable à l&#8217;Entity Manager par la méthode persist(). Cette méthode permet de dire à l&#8217;Entity Manager que l&#8217;on veut faire persister notre PPO passé en paramètre de la méthode. Ça se résume comme ça :</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: #000088;">$user</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> User<span style="color: #339933;">;</span>
<span style="color: #000088;">$user</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setName</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Mr.Right'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$em</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">persist</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$user</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$em</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">flush</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Ici on informe l&#8217;Entity Manager (em), que l&#8217;on voudra faire persister les changements apportés à l&#8217;objet user via la méthode <code>$em->persist($user)</code>. Les changements ne seront effectués dans la base de données qu&#8217;une fois la méthode ->flush() invoquée. Si nous avions fait plusieurs ->persist() différents avant de faire notre ->flush(), rien n&#8217;aurait encore été écrit dans la base. Mais alors, comment Doctrine fait pour garder trace de ces changements jusqu&#8217;au flush ? Il utilise le design pattern <a  href="http://martinfowler.com/eaaCatalog/unitOfWork.html"><strong>Unit of Work</strong></a>. Ce design pattern permet de garder trace de toutes les modifications apportées entre 2 flush(). Il met en place une sorte de <strong>transaction, mais au niveau des objets</strong>. C&#8217;est en partie son utilisation qui permet d&#8217;avoir un beau Data Mapper comme l&#8217;EM.</p>
<h3>Conclusion</h3>
<p>L&#8217;utilisation d&#8217;un DataMapper n&#8217;est pas vraiment nouveau dans le monde de la programmation : <a  href="http://www.hibernate.org/">Hibernate</a> l&#8217;implémente déjà pour Java et <a  href="http://www.sqlalchemy.org/">SQLAlchemy</a> pour Python. En revanche, c&#8217;est une <strong>petite révolution dans le monde PHP</strong>. Si des fois vous préférez garder votre bon vieux <strong>Active Record</strong>, il existe aussi des solution en PHP : vous pouvez utiliser l&#8217;<a  href="http://www.propelorm.org/">ORM Propel</a> qui est toujours activement maintenu par François Zaninotto ou utiliser des implémentations du pattern Active Record réalisées avec Doctrine2 comme <a  href="https://github.com/pablodip/doctrator">Doctractor</a> ou <a  href="http://www.doctrine-project.org/blog/your-own-orm-doctrine2">ActiveEntity</a> codé par l&#8217;équipe de Doctrine2. C&#8217;est deux derniers exemples montrent bien toute la flexibilité et la puissance de cette nouvelle version de Doctrine !</p>
]]></content:encoded>
			<wfw:commentRss>http://www.amicalement-web.net/doctrine2-au-revoir-activerecord-bonjour-datamapper/2011/01/03/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<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, les forms et les forms embarqués</title>
		<link>http://www.amicalement-web.net/symfony-les-forms-et-les-forms-embarques/2010/03/08/</link>
		<comments>http://www.amicalement-web.net/symfony-les-forms-et-les-forms-embarques/2010/03/08/#comments</comments>
		<pubDate>Mon, 08 Mar 2010 10:00:00 +0000</pubDate>
		<dc:creator>Vince</dc:creator>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[conception]]></category>
		<category><![CDATA[embed]]></category>
		<category><![CDATA[form]]></category>
		<category><![CDATA[poo]]></category>
		<category><![CDATA[Symfony]]></category>

		<guid isPermaLink="false">http://www.amicalement-web.net/?p=896</guid>
		<description><![CDATA[Tout d&#8217;abord admirez, dans le titre, cette traduction d&#8217;embedded forms , qui est digne d&#8217;un Nelson (ou d&#8217;un ubermuda) en pleine forme. Maintenant que c&#8217;est fait, nous allons parler ici d&#8217;un des aspects de symfony les plus intéressant, mais aussi d&#8217;un des moins bien documenté. Pas que les forms &#171;&#160;basiques&#160;&#187; ne soient pas documentés, mais [...]]]></description>
			<content:encoded><![CDATA[<p><a  href="http://www.amicalement-web.net/symfony-les-forms-et-les-forms-embarques/2010/03/08/"><img src="http://www.amicalement-web.net/wp-content/uploads/boats.jpg" alt="" title="boats" width="614" height="100" class="alignnone size-full wp-image-1368" /></a> Tout d&#8217;abord admirez, dans le titre, cette traduction d&#8217;<em>embedded forms</em> , qui est digne d&#8217;un Nelson (ou d&#8217;un ubermuda) en pleine forme. </p>
<p>Maintenant que c&#8217;est fait, nous allons parler ici d&#8217;un des aspects de symfony les plus intéressant, mais aussi d&#8217;un des moins bien documenté. Pas que les forms &laquo;&nbsp;basiques&nbsp;&raquo; ne soient pas documentés, mais dès que vous voulez faire autre chose qu&#8217;un form qui représente tel quel (ou presque) un objet de la base de données, ça se complique un peu. </p>
<p>Je vais essayer de vous faire un petit tour d&#8217;horizon de <strong>ce qu&#8217;on peut faire avec les embedded forms</strong>.<br />
<span id="more-896"></span></p>
<h3>Les forms, c&#8217;est de la POO</h3>
<p>Vous allez me dire que tout symfony est de la POO (Programmation Orientée Objet), et vous avez raison. Mais on peut utiliser symfony sans être un expert de la POO (voire sans vraiment savoir ce que c&#8217;est), en suivant Jobeet et en comprenant que executeIndex inclut le template indexSuccess.php en cas de succès. À partir de là, on est le roi du monde. </p>
<p>Enfin, du monde, moins les forms. Car les forms sont &#8211; à mon sens &#8211; la partie de symfony qui est à la fois utilisée par tous les utilisateurs de symfony, et à la fois<strong> très orientée objet </strong>(les factories sont par exemple beaucoup moins utilisées &#8230;). Du coup, ça mérite quelques explications.</p>
<h3>Tout le monde n&#8217;est pas doué en POO</h3>
<p>Certes tout le monde n&#8217;est pas doué en POO, professionnel ou pas d&#8217;ailleurs ;) À l&#8217;inverse de JAVA où les programmeurs n&#8217;ont pas vraiment le choix, la POO est récente dans PHP et certains l&#8217;ont découvert comme un cheveu sur la soupe. </p>
<p>L&#8217;impression que l&#8217;on a quand on essaye de changer le comportement des embed form c&#8217;est : mais <strong>où est-ce que je peux bien faire ce que j&#8217;ai envie de faire</strong>? doBind, doUpdateObject, saveEmbeddedForms, &#8230; les choix sont multiples. </p>
<p>Et pour cause, les forms utilisent énormément l&#8217;héritage, et disposent donc de moultes méthodes que l&#8217;on peut surcharger, sans que ce ne soit vraiment documenté autre part que dans l&#8217;API. Si on ne comprend pas les principes de base de la POO, les forms sont une vraie galère (déjà que quand on les comprend &#8230;). </p>
<p>Petit rappel sur la POO sur <a href="http://hdd34.developpez.com/cours/artpoo/ ">developpez.com</a> : Consultez au moins la partie sur l&#8217;héritage pour ceux qui sont largués.</p>
<h3>Principales étapes de gestion des formulaires</h3>
<p>Il faut quand même que vous ayez quelque chose à l&#8217;esprit, il y a pour moi deux principales étapes quand vous souhaitez traiter un formulaire qui vient d&#8217;être soumis :</p>
<ul>
<li><strong>1 ère étape</strong> : lier les valeurs qui sont récupérées dans la requête à l&#8217;objet Form (c&#8217;est à dire les recopier en s&#8217;assurant qu&#8217;elles sont valides et nettoyées)</li>
<li><strong>2 ème étape</strong> : Une fois les valeurs recopiés dans le $values du formulaire (qui n&#8217;est en fait qu&#8217;un tableau de valeurs nettoyées), réaliser un traitement dessus ou sur l&#8217;objet qui en découlera (nous verrons cela par la suite)</li>
</ul>
<p>
Il est toujours bon de <strong>se demander ce que l&#8217;on veut faire exactement</strong> : agir sur les valeurs qui seront recopiées et validées dans notre form, ou alors agir sur les valeurs nettoyées et recopiées, avant qu&#8217;elles ne soient sauvegardées en base.
</p>
<h4>Première étape</h4>
<p>Lors de la première étape de liaison/validation/recopie des valeurs de la requête dans votre formulaire (votre objet Form), vous pourrez agir sur les données<strong> avant qu&#8217;elles ne soient passées dans les validateurs</strong>, ou alors une fois qu&#8217;elles sont passées dans les validateurs.</p>
<p>Vous pourrez faire votre bourrin : enlever des parties de votre formulaire de la requête en vous basant sur certaines valeurs soumises.<br />
Par exemple enlever tout un formulaire embarqué, si certaines valeurs ne sont pas saisies (c&#8217;est l&#8217;exemple qu&#8217;on trouve pas mal sur le web d&#8217;ailleurs).<br />
Petit souci : les valeurs de la requête n&#8217;auront pas été validées/nettoyées par les validateurs, vous vous exposez donc à quelques soucis (dans le style le gars qui n&#8217;aura rempli que des espaces dans un champ texte, faudra penser à faire vous même le trim avant de vérifier la valeur &#8230;).<br />
<h4>Deuxième étape</h4>
<p>
Lors de la deuxième étape, c&#8217;est ici que vous devrez effectuer<strong> les traitements concernant votre logique métier</strong> à proprement parler. La première étape s&#8217;est occupée de vous donner accès aux valeurs dans votre formulaire (via le tableau $values), maintenant que c&#8217;est fait vous pouvez jouer avec.</p>
<p>
Vous voulez mettre à jour un objet qui dépend de celui que vous allez sauvegarder automatiquement, vous souhaitez insérer votre objet dans un nested set, etc etc &#8230; C&#8217;est dans cette étape que vous ferez ça.
</p>
<p>
Je sépare sciemment le processus en deux étapes, après vous pouvez le voir autrement. Les étapes étant chaînées, vous pouvez les mélanger et faire un peu de business logic à la fin de l&#8217;étape 1 par exemple, mais essayez de rester constant partout dans votre code, où vous ne saurez plus où aller voir quand il y a un souci.
</p>
<h3>Étude de cas</h3>
<p>On va prendre ici un cas tout simple, celui d&#8217;un formulaire auto-généré par doctrine à partir d&#8217;une table de votre modèle. </p>
<p>Appelons notre modèle PetitSuisse. On aura donc une classe nommée <code>PetitSuisseForm.class.php dans lib/form/doctrine/</code></p>
<p>On va vite fait faire le parcours d&#8217;héritage de cette classe :<br />
<strong>PetitSuisseForm => BasePetitSuisseForm => BaseFormDoctrine => sfFormDoctrine => sfFormObject => BaseForm => sfFormSymfony => sfForm (ouf)</strong>
</p>
<p>
Même si quelques unes de ces classes sont vides, on comprend que ça puisse devenir un peu dur de savoir où chercher. Alors oui <strong>l&#8217;abstraction c&#8217;est bon</strong> mangez en, mais ça engendre une complexité de lecture du code non négligeable.</p>
<p>Les classes qui sont &laquo;&nbsp;à vous&nbsp;&raquo; et donc dans lesquelles vous pourrez surcharger des méthodes sont <strong>PetitSuisseForm</strong> et <strong>BaseFormDoctrine</strong>.</p>
<p> La première vous permettra de surcharger une méthode relative au formulaire du modèle PetitSuisse, la deuxième vous permettra de surcharger de manière plus globale (chacun des forms auto-générés par doctrine héritant de BaseFormDoctrine). Je parle ici de symfony 1.3+, vous n&#8217;aurez pas toutes ces classes dans les versions précédentes.</p>
<p>On va maintenant parler <strong>des principales méthodes</strong> que vous aurez (peut être) à surcharger. Il en existe d&#8217;autres, si celles ci ne vous vont pas, lisez le code de symfony ;-)
</p>
<h3>1 ère étape (liaison)</h3>
<h4>doBind(array $values)</h4>
<p>
C&#8217;est la méthode qui va faire appel aux validateurs pour <strong>nettoyer les valeurs</strong> de la requête avant de les placer dans le tableau des valeurs. Ce sont ensuite sur ces valeurs nettoyées que nous travaillerons. Vous pouvez ici toucher aux données brut de pomme <strong>qui sortent directement du formulaire envoyé</strong>, sans traitement préalable.
</p>
<h3>2 ème étape (sauvegarde)</h3>
<h4>doSave($con = null)</h4>
<p>
C&#8217;est cette méthode qui sera appelée (par save() ) lorsque vous demandez la sauvegarde de votre formulaire. Elle se charge de mettre à jour votre objet avec les valeurs du form en appelant updateObject (qui appelera doUpdateObject que nous verrons par la suite).<br />
Si vous souhaitez <strong>changer le processus de sauvegarde</strong>, ajouter par exemple l&#8217;appel d&#8217;une vos méthodes à chaque sauvegarde du formulaire (pourquoi pas garder trace dans un fichier de toutes les sauvegardes de vos formulaires), c&#8217;est ici que vous devez le faire.
</p>
<h4>processValues($values)</h4>
<p>
C&#8217;est ici que vous pouvez<strong> toucher les valeurs qui ont été nettoyées </strong>par les validateurs, avant qu&#8217;elles ne soient passées à la méthode updateObject (que nous verrons par la suite). Je n&#8217;ai pas de traitement particulier en tête, mais l&#8217;idée est là : modifier des valeurs avant qu&#8217;elles ne soient utilisées pour mettre votre objet à jour.
</p>
<h4>doUpdateObject($values)</h4>
<p>
C&#8217;est cette méthode que vous devrez surcharger si vous voulez réaliser <strong>une opération spéciale sur votre objet avant qu&#8217;il ne soit enregistré</strong> dans la base.<br />
Par exemple, si vous voulez insérer cet objet à la fin d&#8217;un NestedSet, vous ferez ça ici. Le $values passé en paramètre est un tableau contenant les valeurs du formulaire, une fois qu&#8217;elles ont été nettoyées/vérifiées par les validateurs.
</p>
<h4>updateObjectEmbeddedForm($values)</h4>
<p>
Je pense qu&#8217;elle veut bien dire ce qu&#8217;elle veut dire. Elle va se charger d&#8217;appeler la fonction updateObject de chaque formulaire embarqué. Vous voulez agir sur le traitement des données par vos forms embarqués ? C&#8217;est par ici !
</p>
<h4>saveEmbeddedForms($con = null, $forms = null)</h4>
<p>
Allez la petite dernière pour la route : elle se charge de la sauvegarde de chacun des objets de vos forms embarqués. Fabien Potencier en donne un exemple de surcharge dans le livre <a  href="http://www.symfony-project.org/more-with-symfony/1_4/en/06-Advanced-Forms#chapter_06_sub_creating_a_custom_validator">&laquo;&nbsp;More with symfony&nbsp;&raquo;</a>
</p>
<h3>Exemple d&#8217;utilisation</h3>
<p>C&#8217;est bien beau de parler, mais un peu de concret ne fait pas de mal. </p>
<p>Vous trouverez un bon exemple pour comprendre le comportement des forms sur le blog de n1k0 dans son article <a  href="http://prendreuncafe.com/blog/post/2009/11/29/Embedding-Relations-in-Forms-with-Symfony-1.3-and-Doctrine">Embedding Relations in Forms with Symfony 1.3 and Doctrine</a>. Certes c&#8217;est en anglais, mais le code est universel ! Si vous avez des bons articles en français je suis preneur aussi. </p>
<p>Il existe maintenant la méthode embedRelation() et le plugin de Daniel Lohse <a  href="http://github.com/annismckenzie/ahDoctrineEasyEmbeddedRelationsPlugin">ahDoctrineEasyEmbeddedRelationsPlugin</a> qui font ça tout seul. Mais c&#8217;est toujours bien de comprendre ce que l&#8217;on fait ;-)</p>
<h3>Conclusion</h3>
<p>Je vous ai fait un petit tour d&#8217;horizon des principales méthodes que vous pouvez surcharger dans votre formulaire. Comme je l&#8217;ai dit plus haut, ce n&#8217;est pas une liste exhaustive, mais vous devriez avoir de quoi vous amuser. </p>
<p>J&#8217;ai juste essayé de voir tout cela d&#8217;une manière un peu plus globale et de ne pas proposer un n-ième exemple de code pour les formulaires embarqués. </p>
<p>Mais avec tout cet attirail, gardez à l&#8217;esprit que votre code d&#8217;action ne doit pas dépasser le classique <code>Bind &gt; Save</code>! Ce qui est au traitement de votre formulaire, reste dans votre formulaire! Enjoy!</p>
<p><small>Crédit photo: http://www.flickr.com/photos/fromeyetopixel/2470999873/</small></p>
]]></content:encoded>
			<wfw:commentRss>http://www.amicalement-web.net/symfony-les-forms-et-les-forms-embarques/2010/03/08/feed/</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
		<item>
		<title>Jouer avec Symfony2 sur github</title>
		<link>http://www.amicalement-web.net/jouer-avec-symfony-2-sur-github/2010/01/06/</link>
		<comments>http://www.amicalement-web.net/jouer-avec-symfony-2-sur-github/2010/01/06/#comments</comments>
		<pubDate>Wed, 06 Jan 2010 07:59:44 +0000</pubDate>
		<dc:creator>Vince</dc:creator>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[Symfony]]></category>

		<guid isPermaLink="false">http://www.amicalement-web.net/?p=1111</guid>
		<description><![CDATA[Comme vous ne l&#8217;avez peut-être pas loupé si vous suiviez le trac symfony ou si vous suivez les bonnes personnes ( ;-) ) sur twitter, Symfony2 utilise maintenant Git comme gestionnaire de version et non plus Svn. Le code source a été déplacé sur github ici. Cela devrait permettre plus de participations externes (ça a [...]]]></description>
			<content:encoded><![CDATA[<p><a  href="http://www.amicalement-web.net/wp-content/uploads/entete_github.png"><img src="http://www.amicalement-web.net/wp-content/uploads/entete_github.png" alt="" title="entete_github" width="614" height="100" class="aligncenter size-full wp-image-1138" /></a></p>
<p>Comme vous ne l&#8217;avez peut-être pas loupé si vous suiviez le trac symfony ou si vous suivez les bonnes personnes ( ;-) ) sur twitter, Symfony2 utilise maintenant Git comme gestionnaire de version et non plus Svn. Le code source a été déplacé sur github <a  href="http://github.com/symfony/symfony">ici</a>. Cela devrait permettre plus de participations externes (ça a déjà commencé avec pborelli, CodingFabian et denderello), vu la facilité pour cloner un repository (le repository c&#8217;est l&#8217;endroit où sont stockées le sources à distance) avec git.<span id="more-1111"></span></p>
<p>Si comme moi, vous connaissez mal ou peu Git, vous pourrez commencer par lire le <a  href="http://learn.github.com/">&laquo;&nbsp;Learn GitHub&nbsp;&raquo;</a> qui pourra vous en apprendre un peu plus. Je vais essayer de vous donner les commandes de base pour récupérer en lecture seule ou en écriture le repository Symfony2<br />
<h3>Récupérer le code source</h3>
<p>
Le premier cas : vous souhaitez juste récupérer le code source pour jouer avec, sans le modifier. Dans ce cas, pas besoin de créer une branche du repository principal, récupérez le juste en lecture seule. Je pars ici du principe que vous êtes sur un *nix et que Git est installé, si vous n&#8217;avez pas installé Git allez le faire de ce pas, si vous êtes sous Windows je ne peux vous aider !
<p>
Rendez-vous sur <a  href="http://github.com/symfony/symfony">l&#8217;url du dépôt GitHub de Symfony2</a> et copiez l&#8217;url Read-Only qui devrait être : git://github.com/symfony/symfony.git
</p>
<p>
Vous pouvez ensuite récupérer les sources en local avec la commande</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">git</span> clone <span style="color: #c20cb9; font-weight: bold;">git</span>:<span style="color: #000000; font-weight: bold;">//</span>github.com<span style="color: #000000; font-weight: bold;">/</span>symfony<span style="color: #000000; font-weight: bold;">/</span>symfony.git</pre></div></div>

<p>Vous aurez un beau répertoire symfony avec les sources.
</p>
<h3>Effectuer des changements</h3>
<p>Si vous voulez effectuer des changements comme un grand sur le code source de symfony, il vous faudra créer une branche. Vous devez être au préalable inscrit sur GitHub. Si vous vous rendez à <a  href="http://github.com/symfony/symfony">l&#8217;url du dépôt GitHub de Symfony2</a> vous devriez avoir quelque chose comme cela en haut : <a  href="http://www.amicalement-web.net/wp-content/uploads/github.png"><img src="http://www.amicalement-web.net/wp-content/uploads/github.png" alt="" title="github" width="300" height="42" class="aligncenter size-full wp-image-1123" /></a></p>
<p>
À la place de &laquo;&nbsp;Your fork&nbsp;&raquo; vous aurez la possibilité de forker. Je ne l&#8217;ai plus car j&#8217;ai déjà forké en fait ;-) Cela vous créera un repository dans votre compte GitHub auquel vous pourrez accéder comme précédemment, mais cette fois-ci en lecture/écriture. Juste l&#8217;url du repository devrait avoir changée, pour moi la commande c&#8217;est :</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">git</span> clone <span style="color: #c20cb9; font-weight: bold;">git</span><span style="color: #000000; font-weight: bold;">@</span>github.com:vjousse<span style="color: #000000; font-weight: bold;">/</span>symfony.git</pre></div></div>

<p>N&#8217;oubliez pas d&#8217;avoir généré et envoyé votre clef publique sur GitHub avant, sinon vous aurez une belle erreur. Voilà, vous pouvez maintenant effectuer vos changements et les répercuter sur le serveur comme expliqué dans le  <a  href="http://learn.github.com/">&laquo;&nbsp;Learn GitHub&nbsp;&raquo;</a>.
</p>
<h3>Symfony2, un exemple de code</h3>
<p>Tout d&#8217;abord il va vous falloir PHP 5.3 d&#8217;installé, si ce n&#8217;est pas le cas n&#8217;allez pas plus loin ! Ensuite il va falloir vous faire aux namespaces PHP et ses \, mais ça ça viendra avec le temps ! Pour finir, allez faire un tour sur git pour recopier un <a  href="http://gist.github.com/296690">petit snippet d&#8217;ubermuda modifié par Fabien Potencier</a>. Je vous le recopie ici :</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">// change this with the actual path you cloned sf2 to</span>
<span style="color: #000088;">$sf2_path</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'~/symfony/src'</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">use</span> Symfony\Foundation\ClassLoader<span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">use</span> Symfony\Components\CLI\Application<span style="color: #339933;">;</span>
&nbsp;
<span style="color: #b1b100;">require_once</span> <span style="color: #000088;">$sf2_path</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'/Symfony/Foundation/ClassLoader.php'</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$loader</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> ClassLoader<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$loader</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">registerNamespace</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Symfony'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$sf2_path</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$loader</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">register</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$app</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Application<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$app</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">run</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>On ne parle pour l&#8217;instant que du composant CLI de Symfony2 qui vient juste d&#8217;être ajouté, on ne manquera pas de vous tenir au courant du reste des évolutions par la suite. À vous de jouer !</p>
]]></content:encoded>
			<wfw:commentRss>http://www.amicalement-web.net/jouer-avec-symfony-2-sur-github/2010/01/06/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Symfony: Move ta Debug Bar</title>
		<link>http://www.amicalement-web.net/symfony-move-ta-debug-bar/2009/12/23/</link>
		<comments>http://www.amicalement-web.net/symfony-move-ta-debug-bar/2009/12/23/#comments</comments>
		<pubDate>Wed, 23 Dec 2009 10:00:36 +0000</pubDate>
		<dc:creator>Tim</dc:creator>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[debug]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[plugin]]></category>
		<category><![CDATA[Symfony]]></category>

		<guid isPermaLink="false">http://www.amicalement-web.net/?p=1049</guid>
		<description><![CDATA[Trivial, mais depuis le temps que ca me démangeait! Et peut-être que je ne suis pas le seul, d&#8217;où ce petit billet. Quand je développe sous Symfony, régulièrement, je dois fermer ma précieuse debug bar pour accéder à un lien en dessous. Du coup je suis obligé de recharger la page pour m&#8217;en servir de [...]]]></description>
			<content:encoded><![CDATA[<p><a  href="http://www.amicalement-web.net/symfony-move-ta-debug-bar/2009/12/23/"><img src="http://www.amicalement-web.net/wp-content/uploads/speed.png" alt="speed" title="speed" width="614" height="100" class="alignnone size-full wp-image-1061" /></a> Trivial, mais depuis le temps que ca me démangeait! Et peut-être que je ne suis pas le seul, d&#8217;où ce petit billet.<br />
Quand je développe sous Symfony, régulièrement, je dois fermer ma précieuse debug bar pour accéder à un lien en dessous. Du coup je suis obligé de recharger la page pour m&#8217;en servir de nouveau et depuis la 1.3, je m&#8217;en passe plus moi de ma debug bar.</p>
<p>J&#8217;ai donc pris 5min de mon temps pour faire rapido presto, un petit coup de jquery pour pouvoir bouger ma debug bar!<br />
<span id="more-1049"></span><br />
Tout simplement, j&#8217;ai juste utilisé un <a  href="http://blog.threedubmedia.com/2008/08/eventspecialdrag.html">script jquery</a> qui permet d&#8217;ajouter un event de type &laquo;&nbsp;drag&nbsp;&raquo; à un élément du DOM. Un petit coup de jquery pour l&#8217;utiliser sur la debug bar:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">jQuery<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;">&quot;#sfWebDebugBar&quot;</span><span style="color: #009900;">&#41;</span>
    .<span style="color: #660066;">bind</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;dragstart&quot;</span><span style="color: #339933;">,</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span> event <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
      $<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">css</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;right&quot;</span><span style="color: #339933;">,</span><span style="color: #3366CC;">&quot;auto&quot;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span>
    .<span style="color: #660066;">bind</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;drag&quot;</span><span style="color: #339933;">,</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span> event <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
      $<span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">css</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span>
        top<span style="color: #339933;">:</span> event.<span style="color: #660066;">offsetY</span><span style="color: #339933;">,</span>
        left<span style="color: #339933;">:</span> event.<span style="color: #660066;">offsetX</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: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Il ne reste plus qu&#8217;à faire un petit filtre pour inclure ces 2 scripts automatiquement à la volée en environnement de dev. J&#8217;ai tout mis dans un petit plugin disponible plus bas mais je vous détaille le code ici pour ceux qui voudraient juste jeter un œil:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> moveWebDebugBarFilter <span style="color: #000000; font-weight: bold;">extends</span> sfFilter
<span style="color: #009900;">&#123;</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> execute<span style="color: #009900;">&#40;</span><span style="color: #000088;">$filterChain</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: #0000ff;">'dev'</span> <span style="color: #339933;">==</span> sfConfig<span style="color: #339933;">::</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'sf_environment'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
      <span style="color: #000088;">$response</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getContext</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getResponse</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
      <span style="color: #000088;">$response</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addJavascript</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/moveDebugBarPlugin/js/jquery.event.drag-1.5.min.js'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'last'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #000088;">$response</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addJavascript</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/moveDebugBarPlugin/js/moveDebugBar.js'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'last'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000088;">$filterChain</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">execute</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>que l&#8217;on rajoute dans notre <code>filters.yml</code></p>

<div class="wp_syntax"><div class="code"><pre class="yml" style="font-family:monospace;">rendering: ~
security:  ~
&nbsp;
# insert your own filters here
moveDebugBar:
  class: moveWebDebugBarFilter
&nbsp;
cache:     ~
execution: ~</pre></div></div>

<p>Il ne reste plus qu&#8217;à télécharger:<br />
<a  href="http://www.amicalement-web.net/symfony-move-ta-debug-bar/2009/12/23/movedebugbarplugin/" rel="attachment wp-att-1050">moveDebugBarPlugin</a><br />
et à lancer un petit:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">php symfony plugin:publish-asset</pre></div></div>

<p>Le plugin est très basique et rudimentaire évidemment, il ne sera pas encore sur le site de Symfony du coup. Mais si vous avez des idées d&#8217;améliorations ou d&#8217;enrichissements hésitez pas, sait-on jamais.</p>
<p>Voilà le rendu en vidéo, a noter que je l&#8217;ai testé avec Symfony 1.2 et 1.3:<br />
<object id='stUE1TSkxIR19eRFVdW1NcU19R' 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=stUE1TSkxIR19eRFVdW1NcU19R'/></object>
<div style='width: 425px; text-align: right;'><a  href="http://www.screentoaster.com/">Capture your screen in seconds</a></div>
<p><small>Crédit photo: http://www.flickr.com/photos/kaidohmaru/453263320/</small></p>
]]></content:encoded>
			<wfw:commentRss>http://www.amicalement-web.net/symfony-move-ta-debug-bar/2009/12/23/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Veille sécuritaire avec flux RSS (part 1)</title>
		<link>http://www.amicalement-web.net/veille-securitaire-avec-flux-rss-part-1/2009/08/28/</link>
		<comments>http://www.amicalement-web.net/veille-securitaire-avec-flux-rss-part-1/2009/08/28/#comments</comments>
		<pubDate>Fri, 28 Aug 2009 07:57:00 +0000</pubDate>
		<dc:creator>Benoit</dc:creator>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[rss]]></category>
		<category><![CDATA[sécurité]]></category>
		<category><![CDATA[veille]]></category>

		<guid isPermaLink="false">http://www.amicalement-web.net/?p=598</guid>
		<description><![CDATA[Il existe sur Internet, de nombreux sites de veille sécuritaire permettant de vous maintenir au courant des dernières vulnérabilités découvertes. Si vous utilisez une application open-source (forum, blog, cms &#8230;), des visites régulières sur ces sites ou abonnement aux flux RSS, vous permettent de maintenir à jour votre application et minimiser les risques de piratages. [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.amicalement-web.net/wp-content/uploads/veille.secu2.png" alt="Veille sécuritaire" width="614" height="100" class="alignnone size-full wp-image-640" /></p>
<p>Il existe sur Internet, de nombreux sites de veille sécuritaire permettant de vous maintenir au courant des dernières vulnérabilités découvertes. Si vous utilisez une application open-source (forum, blog, cms &#8230;), des visites régulières sur ces sites ou abonnement aux flux RSS, vous permettent de maintenir à jour votre application et minimiser les risques de piratages.</p>
<p>Mais, que vous utilisiez une application web open-source (ou non) à jour, cela n&#8217;empêche pas les tentatives d&#8217;attaques, c&#8217;est pourquoi je vous propose ici un petit script python pour effectuer vous même votre veille sécuritaire.</p>
<p>Cet article est la 1ère partie d&#8217;une série de 3 :</p>
<ul>
<li><b>Part 1</b>: Configuration des logs apache, création de la BDD puis présentation et configuration du script de traitement.</li>
<li><b>Part 2</b>: Script de génération du flux RSS avec présentation détaillées des informations dans le flux.</li>
<li><b>Part 3</b>: Amélioration du script avec des expressions régulières plus poussés, rajout d&#8217;options &#8230;</li>
</ul>
<p><span id="more-598"></span>Il est intéressant de noter que la Partie 1 est la plus importante, les 2 autres parties pouvant être réalisées sans attendre la suite de l&#8217;article si vous savez programmer.</p>
<h3>Logs apache, BDD &amp; script de traitement</h3>
<p>
<h4>Configuration des logs apache</h4>
<p>Ce script de veille se base sur les fichiers de logs apache, il faut donc vous assurer dans un premier temps que les directives de logs sont bien renseignées au niveau de votre configuration.<br />
L&#8217;article ne portant pas sur la configuration d&#8217;apache, je ne vais pas m&#8217;étendre dessus, voici donc les lignes nécessaires à la génération des logs.</p>
<p></p>

<div class="wp_syntax"><div class="code"><pre class="apache" style="font-family:monospace;"><span style="color: #00007f;">LogFormat</span> %V %{canonical}p %h %{X-Forwarded-For}i %{PHPSESSID}C %t \<span style="color: #7f007f;">&quot;%r<span style="color: #000099; font-weight: bold;">\&quot;</span> %gt;s %b <span style="color: #000099; font-weight: bold;">\&quot;</span>%{Referer}i<span style="color: #000099; font-weight: bold;">\&quot;</span> <span style="color: #000099; font-weight: bold;">\&quot;</span>%{User-Agent}i<span style="color: #000099; font-weight: bold;">\&quot;</span>
ErrorLog /var/log/apache/my_error_log</span></pre></div></div>

<p>Ceci est un exemple de format de log, vous pouvez le modifier sans problème :</p>
<ul>
<li><b>%V</b>: Nom du serveur</li>
<li><b>%{canonical}p</b>: port</li>
<li><b>%h</b>: IP du visiteur</li>
<li><b>%{X-Forwareded-for}i</b>: IP du proxy</li>
<li><b>%{PHPSESSID}C</b>: ID de session (pratique pour retracer le chemin d&#8217;un pirate potentiel)</li>
<li><b>%t</b>: Date</li>
<li><b>%r</b>: Requête</li>
<li><b>%&gt;s</b>: Status de la requête</li>
<li><b>%b</b>: Taille de la requête</li>
<li><b>%{Referer}i</b>: Referer (lien précédent)</li>
<li><b>%{User-Agent}i</b>: Informations sur le navigateur du visiteur</li>
</ul>
<p>Pour plus d&#8217;infos, je vous invite à consulter <a  href="http://httpd.apache.org/docs/2.0/logs.html">la documentation officielle concernant les directives logs d&#8217;apache</a>.<br />
Une fois votre fichier modifié, n&#8217;oubliez pas de le recharger. Un simple reload doit normalement suffire.</p>
<p></p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">/</span>etc<span style="color: #000000; font-weight: bold;">/</span>init.d<span style="color: #000000; font-weight: bold;">/</span>apache2 reload</pre></div></div>

<h4>Création de la BDD MySQL</h4>
<p>Les informations traitées par le script seront enregistrées en BDD pour pouvoir garder une trace, voici le code SQL pour la création des tables concernées.</p>
<p></p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">--</span>
<span style="color: #808080; font-style: italic;">-- Création de la table des attaques potentielles recensées</span>
<span style="color: #808080; font-style: italic;">--</span>
&nbsp;
<span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">TABLE</span> <span style="color: #ff0000;">`veille_vuln`</span> <span style="color: #66cc66;">&#40;</span>
	<span style="color: #ff0000;">`id_vuln`</span> <span style="color: #993333; font-weight: bold;">BIGINT</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">20</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">UNSIGNED</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span> <span style="color: #993333; font-weight: bold;">AUTO_INCREMENT</span><span style="color: #66cc66;">,</span>
	<span style="color: #ff0000;">`ip`</span> <span style="color: #993333; font-weight: bold;">VARCHAR</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">15</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span>
	<span style="color: #ff0000;">`url`</span> text<span style="color: #66cc66;">,</span>
	<span style="color: #ff0000;">`log`</span> text<span style="color: #66cc66;">,</span>
	<span style="color: #ff0000;">`temps`</span> datetime<span style="color: #66cc66;">,</span>
	<span style="color: #ff0000;">`id_type`</span> tinyint<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">3</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">UNSIGNED</span><span style="color: #66cc66;">,</span>
	<span style="color: #993333; font-weight: bold;">PRIMARY</span> <span style="color: #993333; font-weight: bold;">KEY</span> <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">`id_vuln`</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span>
	<span style="color: #993333; font-weight: bold;">UNIQUE</span> <span style="color: #993333; font-weight: bold;">KEY</span> <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">`ip`</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">`url`</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">150</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">`log`</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">150</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">`temps`</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">`id_type`</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#41;</span> ENGINE<span style="color: #66cc66;">=</span>MyISAM <span style="color: #993333; font-weight: bold;">DEFAULT</span> CHARSET utf8;
&nbsp;
<span style="color: #808080; font-style: italic;">--</span>
<span style="color: #808080; font-style: italic;">-- Création de la table des types d'attaques surveillées</span>
<span style="color: #808080; font-style: italic;">--</span>
&nbsp;
<span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">TABLE</span> <span style="color: #ff0000;">`veille_vuln_type`</span> <span style="color: #66cc66;">&#40;</span>
	<span style="color: #ff0000;">`id_type`</span> tinyint<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">3</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">UNSIGNED</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span> <span style="color: #993333; font-weight: bold;">DEFAULT</span> <span style="color: #ff0000;">'0'</span><span style="color: #66cc66;">,</span>
	<span style="color: #ff0000;">`nom`</span> <span style="color: #993333; font-weight: bold;">VARCHAR</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">45</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span>
	<span style="color: #ff0000;">`link`</span> <span style="color: #993333; font-weight: bold;">VARCHAR</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">250</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span>
	<span style="color: #993333; font-weight: bold;">PRIMARY</span> <span style="color: #993333; font-weight: bold;">KEY</span> <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">`id_type`</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#41;</span> ENGINE<span style="color: #66cc66;">=</span>MyISAM <span style="color: #993333; font-weight: bold;">DEFAULT</span> CHARSET utf8;
&nbsp;
<span style="color: #808080; font-style: italic;">--</span>
<span style="color: #808080; font-style: italic;">-- Insertion des types de vulnérabilités surveillées</span>
<span style="color: #808080; font-style: italic;">--</span>
&nbsp;
<span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #993333; font-weight: bold;">INTO</span> <span style="color: #ff0000;">`veille_vuln_type`</span> <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">`id_type`</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">`nom`</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">`link`</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">VALUES</span> 
<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'1'</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">'XSS'</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">'http://fr.wikipedia.org/wiki/Cross_site_scripting'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span>
<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'2'</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">'Unicode'</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">''</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span>
<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'3'</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">'Include'</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">''</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span>
<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'4'</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">'SQL Injection'</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">'http://fr.wikipedia.org/wiki/Injection_SQL'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span>
<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'5'</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">'Mot sensible'</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">''</span><span style="color: #66cc66;">&#41;</span>;</pre></div></div>

<h4>Script veille-secu</h4>
<p>Une fois les logs apache configurés et la <acronym title="Base De Données">BDD</acronym> créée, nous allons  nous attaquer au script de traitement.<br />
En début de script, appel des différentes librairies nécessaires.</p>
<p></p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#!/usr/bin/python</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Importation des librairies necessaires</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">re</span>, <span style="color: #dc143c;">cgi</span>, <span style="color: #dc143c;">time</span>, MySQLdb, <span style="color: #dc143c;">sys</span>
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">getopt</span> <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">getopt</span>,GetoptError</pre></div></div>

<p>Ensuite, la partie à configurer pour :</p>
<ul>
<li>Effectuer la connexion à la <acronym title="Base De Données">BDD</acronym></li>
<li>Indiquer le fichier <strong>pointer</strong></li>
<li>Gérer vos expressions régulières.</li>
</ul>
<p>Le fichier <strong>pointer</strong> va vous permettre de conserver la dernière ligne de logs traitée par le script afin de ne pas repasser sur tout le fichier et utiliser des ressources mémoires inutilement.<br />
Juste après ces infos, deux bloc d&#8217;expressions régulières qui permettront de traiter la ligne de log pour la découper puis de détecter une éventuelle tentative d&#8217;attaque.</p>
<p></p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#---------------------------------#</span>
<span style="color: #808080; font-style: italic;">#	PARTIE A CONFIGURER</span>
<span style="color: #808080; font-style: italic;">#---------------------------------#</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Declaration des variables generales (chemin absolu)</span>
file_pointer = <span style="color: #483d8b;">'/path/to/your/pointer'</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Declaration des variables de connexion a la BDD MySQL</span>
bdd_host	= <span style="color: #483d8b;">'127.0.0.1'</span>
bdd_user	= <span style="color: #483d8b;">'mon_user'</span>
bdd_pass	= <span style="color: #483d8b;">'mon_pass'</span>
bdd_db		= <span style="color: #483d8b;">'ma_bdd'</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Declaration des regexp de traitement des logs</span>
pattern_ip 	= <span style="color: #dc143c;">re</span>.<span style="color: #008000;">compile</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'[0-9]{1,3}<span style="color: #000099; font-weight: bold;">\.</span>[0-9]{1,3}<span style="color: #000099; font-weight: bold;">\.</span>[0-9]{1,3}<span style="color: #000099; font-weight: bold;">\.</span>[0-9]{1,3}'</span><span style="color: black;">&#41;</span>
pattern_date 	= <span style="color: #dc143c;">re</span>.<span style="color: #008000;">compile</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'[0-9]{2}<span style="color: #000099; font-weight: bold;">\/</span>...<span style="color: #000099; font-weight: bold;">\/</span>[0-9]{4}:[0-9]{2}:[0-9]{2}:[0-9]{2}'</span><span style="color: black;">&#41;</span>
pattern_url 	= <span style="color: #dc143c;">re</span>.<span style="color: #008000;">compile</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'(GET|POST|PUT|DELETE|HEAD|PROPFIND|LOCK|OPTIONS)<span style="color: #000099; font-weight: bold;">\ </span>[^ ]*<span style="color: #000099; font-weight: bold;">\ </span>'</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Declaration des regexp de detection d'attaques potentielles</span>
p_faille_xss 	=  <span style="color: #dc143c;">re</span>.<span style="color: #008000;">compile</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'((<span style="color: #000099; font-weight: bold;">\%</span>3C)|&lt;)[^<span style="color: #000099; font-weight: bold;">\n</span>]+((<span style="color: #000099; font-weight: bold;">\%</span>3E)|&gt;)'</span>, <span style="color: #dc143c;">re</span>.<span style="color: black;">IGNORECASE</span><span style="color: black;">&#41;</span>
p_faille_unicode = <span style="color: #dc143c;">re</span>.<span style="color: #008000;">compile</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'<span style="color: #000099; font-weight: bold;">\.</span>exe|<span style="color: #000099; font-weight: bold;">\/</span>syntaxe<span style="color: #000099; font-weight: bold;">\/</span>winnt<span style="color: #000099; font-weight: bold;">\/</span>system32<span style="color: #000099; font-weight: bold;">\/</span>'</span>, <span style="color: #dc143c;">re</span>.<span style="color: black;">IGNORECASE</span><span style="color: black;">&#41;</span>
p_faille_inc 	= <span style="color: #dc143c;">re</span>.<span style="color: #008000;">compile</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'(http|ftp):<span style="color: #000099; font-weight: bold;">\/</span><span style="color: #000099; font-weight: bold;">\/</span>|<span style="color: #000099; font-weight: bold;">\/</span>etc<span style="color: #000099; font-weight: bold;">\/</span>(passwd|shadow)|<span style="color: #000099; font-weight: bold;">\/</span>(sbin|bin)<span style="color: #000099; font-weight: bold;">\/</span>|<span style="color: #000099; font-weight: bold;">\.</span><span style="color: #000099; font-weight: bold;">\.</span><span style="color: #000099; font-weight: bold;">\/</span>'</span>, <span style="color: #dc143c;">re</span>.<span style="color: black;">IGNORECASE</span><span style="color: black;">&#41;</span>
p_faille_sql 	= <span style="color: #dc143c;">re</span>.<span style="color: #008000;">compile</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'(<span style="color: #000099; font-weight: bold;">\ </span>|%20)(union|or)(<span style="color: #000099; font-weight: bold;">\ </span>|%20)'</span>, <span style="color: #dc143c;">re</span>.<span style="color: black;">IGNORECASE</span><span style="color: black;">&#41;</span>
p_faille_word 	= <span style="color: #dc143c;">re</span>.<span style="color: #008000;">compile</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'(root|htaccess|passwd|<span style="color: #000099; font-weight: bold;">\.</span>log|<span style="color: #000099; font-weight: bold;">\.</span>conf)'</span>, <span style="color: #dc143c;">re</span>.<span style="color: black;">IGNORECASE</span><span style="color: black;">&#41;</span></pre></div></div>

<p>La suite du fichier concerne le traitement des options et des arguments qu&#8217;il est possible de passer au script, ici une seule option <em>&laquo;&nbsp;&#8211;help&nbsp;&raquo;</em> et un seul argument <em>&laquo;&nbsp;le fichier&nbsp;&raquo;</em>. Nous verrons dans la partie 3 des cas beaucoup plus poussés pour faire de ce script un mini <acronym title="Intrusion Detection System">IDS</acronym> et limiter au maximum les faux-positifs.</p>
<p></p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#-----------------------------------------------------#</span>
<span style="color: #808080; font-style: italic;">#	NE PAS MODIFIER CETTE PARTIE</span>
<span style="color: #808080; font-style: italic;">#-----------------------------------------------------#</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Declaration des options et arguments</span>
optionmap = <span style="color: black;">&#91;</span>
	<span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;-h&quot;</span>, <span style="color: #483d8b;">&quot;--help&quot;</span>, <span style="color: #483d8b;">&quot;Affiche l'aide&quot;</span><span style="color: black;">&#93;</span>,
	<span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;-f&quot;</span>, <span style="color: #483d8b;">&quot;--logfile&quot;</span>, <span style="color: #483d8b;">&quot;Specifie le fichier de log a traiter (chemin absolu)&quot;</span><span style="color: black;">&#93;</span>,
<span style="color: black;">&#93;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Traitement des options et arguments</span>
args = <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
params = <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
<span style="color: #ff7700;font-weight:bold;">try</span>:
	args, params = <span style="color: #dc143c;">getopt</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">sys</span>.<span style="color: black;">argv</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span>:<span style="color: black;">&#93;</span>, <span style="color: #483d8b;">&quot;&quot;</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span>o<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span> <span style="color: #ff7700;font-weight:bold;">for</span> o <span style="color: #ff7700;font-weight:bold;">in</span> optionmap<span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>, \
		<span style="color: black;">&#91;</span>x<span style="color: black;">&#91;</span><span style="color: #ff4500;">2</span>:<span style="color: black;">&#93;</span> <span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">reduce</span><span style="color: black;">&#40;</span><span style="color: #ff7700;font-weight:bold;">lambda</span> x,y: x+y, <span style="color: black;">&#91;</span>z<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span>:-<span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span> <span style="color: #ff7700;font-weight:bold;">for</span> z <span style="color: #ff7700;font-weight:bold;">in</span> optionmap<span style="color: black;">&#93;</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
	args = <span style="color: black;">&#91;</span>a <span style="color: #ff7700;font-weight:bold;">for</span> a,b <span style="color: #ff7700;font-weight:bold;">in</span> args<span style="color: black;">&#93;</span>
&nbsp;
	log = <span style="color: #ff4500;">0</span>
	mode = <span style="color: #008000;">None</span>
&nbsp;
	<span style="color: #ff7700;font-weight:bold;">for</span> option <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;--help&quot;</span>, <span style="color: #483d8b;">&quot;-h&quot;</span><span style="color: black;">&#93;</span>:
		<span style="color: #ff7700;font-weight:bold;">if</span> option <span style="color: #ff7700;font-weight:bold;">in</span> args:
			args.<span style="color: black;">remove</span><span style="color: black;">&#40;</span>option<span style="color: black;">&#41;</span>
			mode = <span style="color: #483d8b;">&quot;help&quot;</span>
&nbsp;
	<span style="color: #ff7700;font-weight:bold;">for</span> option <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;--logfile&quot;</span>, <span style="color: #483d8b;">&quot;-f&quot;</span><span style="color: black;">&#93;</span>:
		<span style="color: #ff7700;font-weight:bold;">if</span> option <span style="color: #ff7700;font-weight:bold;">in</span> args:
			args.<span style="color: black;">remove</span><span style="color: black;">&#40;</span>option<span style="color: black;">&#41;</span>
			log = params.<span style="color: black;">pop</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Traitement des errreurs</span>
<span style="color: #ff7700;font-weight:bold;">except</span> GetoptError, e:
	<span style="color: #dc143c;">sys</span>.<span style="color: black;">stderr</span>.<span style="color: black;">write</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;option invalide: &quot;</span><span style="color: black;">&#41;</span>
	<span style="color: #dc143c;">sys</span>.<span style="color: black;">stderr</span>.<span style="color: black;">write</span><span style="color: black;">&#40;</span><span style="color: #008000;">str</span><span style="color: black;">&#40;</span>e<span style="color: black;">&#41;</span>+<span style="color: #483d8b;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: black;">&#41;</span>
	mode = <span style="color: #483d8b;">&quot;help&quot;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Affichage de l'aide si le mode &quot;help&quot; est defini ou si le fichier de log est equivalent a 0</span>
<span style="color: #ff7700;font-weight:bold;">if</span> mode == <span style="color: #483d8b;">&quot;help&quot;</span> <span style="color: #ff7700;font-weight:bold;">or</span> log == <span style="color: #ff4500;">0</span>:
	<span style="color: #dc143c;">sys</span>.<span style="color: black;">stderr</span>.<span style="color: black;">write</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Syntax: veille-secu <span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: black;">&#41;</span>
	<span style="color: #ff7700;font-weight:bold;">for</span> m <span style="color: #ff7700;font-weight:bold;">in</span> optionmap:
		<span style="color: #dc143c;">sys</span>.<span style="color: black;">stderr</span>.<span style="color: black;">write</span><span style="color: black;">&#40;</span>m<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span> + <span style="color: #483d8b;">&quot;<span style="color: #000099; font-weight: bold;">\t</span>&quot;</span> + m<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span> + <span style="color: #483d8b;">&quot;   <span style="color: #000099; font-weight: bold;">\t</span>: &quot;</span> + m<span style="color: black;">&#91;</span>-<span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span> + <span style="color: #483d8b;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: black;">&#41;</span>
		<span style="color: #ff7700;font-weight:bold;">for</span> o <span style="color: #ff7700;font-weight:bold;">in</span> m<span style="color: black;">&#91;</span><span style="color: #ff4500;">2</span>:-<span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span>:
			<span style="color: #dc143c;">sys</span>.<span style="color: black;">stderr</span>.<span style="color: black;">write</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;<span style="color: #000099; font-weight: bold;">\t</span>&quot;</span> + o + <span style="color: #483d8b;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: black;">&#41;</span>
	<span style="color: #dc143c;">sys</span>.<span style="color: black;">exit</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Connexion à la <acronym title="Base De Données">BDD</acronym> avec les informations renseignées en début de fichier.</p>
<p></p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># Connexion a la BDD</span>
cnx = MySQLdb.<span style="color: black;">connect</span><span style="color: black;">&#40;</span>
	host	= bdd_host,
	<span style="color: #dc143c;">user</span>	= bdd_user,
	passwd	= bdd_pass,
	db		= bdd_db
<span style="color: black;">&#41;</span>
c = cnx.<span style="color: black;">cursor</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Comme expliqué précédemment, nous allons ici vérifier l&#8217;existence et la valeur du <strong>pointer</strong> pour ne pas reprendre le fichier complet puis ouvrir le fichier de log au niveau du <strong>pointer</strong>.<br />
Nous verrons en fin d&#8217;article la possibilité de remettre ce pointer à 0 si vous avez un logrotate activé sur votre serveur.</p>
<p></p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># Vérification du pointer pour ne pas reprendre le fichier a 0</span>
pointer = <span style="color: #ff4500;">0</span>
verif = <span style="color: #008000;">open</span><span style="color: black;">&#40;</span>file_pointer,<span style="color: #483d8b;">'r'</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">for</span> num <span style="color: #ff7700;font-weight:bold;">in</span> verif.<span style="color: black;">xreadlines</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
	pointer = <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>num<span style="color: black;">&#41;</span>
verif.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Ouverture du fichier de log et vérification du pointer</span>
logapache = <span style="color: #008000;">open</span><span style="color: black;">&#40;</span>log,<span style="color: #483d8b;">'r'</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">if</span> pointer <span style="color: #66cc66;">&amp;</span>gt<span style="color: #66cc66;">;</span> <span style="color: #ff4500;">0</span>:
	logapache.<span style="color: black;">seek</span><span style="color: black;">&#40;</span>pointer, <span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Traitement du fichier ligne par ligne. A chaque ligne de log, le script va analyser l&#8217;url et déterminer, en fonction des regexp définies plus haut, si la requête est une tentative d&#8217;attaque ou non.<br />
Dans cet exemple du script, les regexp de détection sont assez basiques, dans la partie 3 nous élaborerons des techniques plus poussées.</p>
<p>Si une attaque potentielle est détectée, alors elle sera enregistrée en <acronym title="Base De Données">BDD</acronym> pour générer par la suite le flux RSS ou tout simplement consulter les différents enregistrements à partir d&#8217;une interface web comme nous le verrons dans la partie 2 de l&#8217;article.</p>
<p></p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># Traitement du fichier ligne par ligne</span>
k=<span style="color: #ff4500;">1</span>
<span style="color: #ff7700;font-weight:bold;">for</span> line <span style="color: #ff7700;font-weight:bold;">in</span> logapache.<span style="color: black;">xreadlines</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
	<span style="color: #808080; font-style: italic;"># Initialisation des Variables</span>
	data_ip 		= <span style="color: #483d8b;">'NULL'</span>
	data_date		= <span style="color: #483d8b;">'NULL'</span>
	data_url		= <span style="color: #483d8b;">'NULL'</span>
	<span style="color: #808080; font-style: italic;"># IP</span>
	field_ip = pattern_ip.<span style="color: black;">search</span><span style="color: black;">&#40;</span>line<span style="color: black;">&#41;</span>
	<span style="color: #ff7700;font-weight:bold;">if</span> field_ip:
		data_ip = field_ip.<span style="color: black;">group</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
	<span style="color: #808080; font-style: italic;"># DATE</span>
	field_date = pattern_date.<span style="color: black;">search</span><span style="color: black;">&#40;</span>line<span style="color: black;">&#41;</span>
	<span style="color: #ff7700;font-weight:bold;">if</span> field_date:
		tmp_date = <span style="color: #dc143c;">time</span>.<span style="color: black;">strptime</span><span style="color: black;">&#40;</span>field_date.<span style="color: black;">group</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>, <span style="color: #483d8b;">&quot;%d/%b/%Y:%H:%M:%S&quot;</span><span style="color: black;">&#41;</span>
		data_date = <span style="color: #dc143c;">time</span>.<span style="color: black;">strftime</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;%Y-%m-%d %H:%M:%S&quot;</span>, tmp_date<span style="color: black;">&#41;</span>
	<span style="color: #808080; font-style: italic;"># URL</span>
	field_url = pattern_url.<span style="color: black;">search</span><span style="color: black;">&#40;</span>line<span style="color: black;">&#41;</span>
	<span style="color: #ff7700;font-weight:bold;">if</span> field_url:
		data_method,data_url = <span style="color: black;">&#40;</span>field_url.<span style="color: black;">group</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">strip</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">split</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> + <span style="color: black;">&#91;</span><span style="color: #483d8b;">'0'</span>,<span style="color: #483d8b;">'0'</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span><span style="color: black;">&#91;</span>:<span style="color: #ff4500;">2</span><span style="color: black;">&#93;</span>
		<span style="color: #808080; font-style: italic;"># ATTAQUES POTENTIELLES</span>
		field_faille_xss 		= p_faille_xss.<span style="color: black;">search</span><span style="color: black;">&#40;</span>data_url<span style="color: black;">&#41;</span>
		field_faille_unicode 	= p_faille_unicode.<span style="color: black;">search</span><span style="color: black;">&#40;</span>data_url<span style="color: black;">&#41;</span>
		field_faille_inc 		= p_faille_inc.<span style="color: black;">search</span><span style="color: black;">&#40;</span>data_url<span style="color: black;">&#41;</span>
		field_faille_sql 		= p_faille_sql.<span style="color: black;">search</span><span style="color: black;">&#40;</span>data_url<span style="color: black;">&#41;</span>
		field_faille_word 		= p_faille_word.<span style="color: black;">search</span><span style="color: black;">&#40;</span>data_url<span style="color: black;">&#41;</span>
		<span style="color: #ff7700;font-weight:bold;">if</span> field_faille_xss <span style="color: #ff7700;font-weight:bold;">or</span> field_faille_unicode <span style="color: #ff7700;font-weight:bold;">or</span> field_faille_inc <span style="color: #ff7700;font-weight:bold;">or</span> field_faille_sql <span style="color: #ff7700;font-weight:bold;">or</span> field_faille_word:
			<span style="color: #ff7700;font-weight:bold;">if</span> field_faille_xss:
				faille_type = <span style="color: #483d8b;">'1'</span>
			<span style="color: #ff7700;font-weight:bold;">elif</span> field_faille_unicode:
				faille_type = <span style="color: #483d8b;">'2'</span>
			<span style="color: #ff7700;font-weight:bold;">elif</span> field_faille_inc:
				faille_type = <span style="color: #483d8b;">'3'</span>
			<span style="color: #ff7700;font-weight:bold;">elif</span> field_faille_sql:
				faille_type = <span style="color: #483d8b;">'4'</span>
			<span style="color: #ff7700;font-weight:bold;">elif</span> field_faille_word:
				faille_type = <span style="color: #483d8b;">'5'</span>
			c.<span style="color: black;">execute</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;INSERT IGNORE veille_vuln (ip, url, log, temps, id_type) VALUES (%s, %s, %s, %s, %s)&quot;</span>, <span style="color: black;">&#40;</span>data_ip, data_url, line, data_date, faille_type<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
			k = k + <span style="color: #ff4500;">1</span></pre></div></div>

<p>Une fois le fichier traité, nous allons successivement :</p>
<ul>
<li>Fermer la connexion MySQL</li>
<li>Récupérer la position du pointer</li>
<li>Fermer le fichier de log</li>
</ul>
<p></p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># Fermeture de la connexion MySQL</span>
cnx.<span style="color: black;">commit</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
c.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Recuperation position actuelle du pointer puis fermeture du fichier</span>
eof = logapache.<span style="color: black;">tell</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
logapache.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Sauvegarde du pointer en cours</span>
new_verif = <span style="color: #008000;">open</span><span style="color: black;">&#40;</span>file_pointer,<span style="color: #483d8b;">'w'</span><span style="color: black;">&#41;</span>
new_verif.<span style="color: black;">write</span><span style="color: black;">&#40;</span><span style="color: #008000;">str</span><span style="color: black;">&#40;</span>eof<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
new_verif.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Si vous n&#8217;avez qu&#8217;un seul fichier de log que vous videz de temps en temps, il suffit de mettre en tâche cron le script <strong>veille-secu</strong>, mais si vous utilisez un logrotate, il faudra rajouter une étape.</p>
<p>Ci-dessous, on fait tourner le script toutes les 5min.</p>
<p></p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">*/</span><span style="color: #000000;">5</span>	<span style="color: #000000; font-weight: bold;">*</span>	<span style="color: #000000; font-weight: bold;">*</span>	<span style="color: #000000; font-weight: bold;">*</span>	<span style="color: #000000; font-weight: bold;">*</span>	<span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>sbin<span style="color: #000000; font-weight: bold;">/</span>veille-secu <span style="color: #660033;">-f</span> <span style="color: #000000; font-weight: bold;">/</span>path<span style="color: #000000; font-weight: bold;">/</span>to<span style="color: #000000; font-weight: bold;">/</span>your<span style="color: #000000; font-weight: bold;">/</span>apache_log</pre></div></div>

<p>Dans le cas d&#8217;une utilisation de logrotate, dans votre fichier de conf, on va ajouter au niveau de <strong>postrotate</strong> une commande permettant de remettre le <strong>pointer</strong> à 0 à chaque rotation de log.</p>
<p></p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">postrotate
	<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #660033;">-f</span> <span style="color: #000000; font-weight: bold;">/</span>var<span style="color: #000000; font-weight: bold;">/</span>run<span style="color: #000000; font-weight: bold;">/</span>apache2.pid <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span>
		<span style="color: #000000; font-weight: bold;">/</span>etc<span style="color: #000000; font-weight: bold;">/</span>init.d<span style="color: #000000; font-weight: bold;">/</span>apache2 restart <span style="color: #000000; font-weight: bold;">&amp;</span>gt; <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>null
		<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #000000;">0</span> <span style="color: #000000; font-weight: bold;">&amp;</span>gt; <span style="color: #000000; font-weight: bold;">/</span>path<span style="color: #000000; font-weight: bold;">/</span>to<span style="color: #000000; font-weight: bold;">/</span>your<span style="color: #000000; font-weight: bold;">/</span>pointer
	<span style="color: #000000; font-weight: bold;">fi</span>
endscript</pre></div></div>

<p>Voilà, j&#8217;espère que ce premier article vous plaira sinon Tim risque de pas être content et il ne voudra plus venir me voir ^^</p>
]]></content:encoded>
			<wfw:commentRss>http://www.amicalement-web.net/veille-securitaire-avec-flux-rss-part-1/2009/08/28/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Doctrine et son Behavior Geographical</title>
		<link>http://www.amicalement-web.net/doctrine-et-son-behavior-geographical/2009/08/05/</link>
		<comments>http://www.amicalement-web.net/doctrine-et-son-behavior-geographical/2009/08/05/#comments</comments>
		<pubDate>Wed, 05 Aug 2009 12:00:18 +0000</pubDate>
		<dc:creator>Tim</dc:creator>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[behavior]]></category>
		<category><![CDATA[doctrine]]></category>
		<category><![CDATA[Symfony]]></category>

		<guid isPermaLink="false">http://www.amicalement-web.net/?p=485</guid>
		<description><![CDATA[Retour un peu à la technique, mais n&#8217;oubliez pas, il vous reste seulement jusqu&#8217;à demain pour gagner une BD. En ce qui nous concerne, avec les annonces faites lors de la dernière Symfony Conference Live, il faut bien commencer à se lancer dans Doctrine. Et c&#8217;est l&#8217;occasion de découvrir petit à petit cet ORM qui [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.amicalement-web.net/wp-content/uploads/edit-cut.png" alt="edit-cut" title="edit-cut" width="48" height="48" class="alignleft size-full wp-image-34" /> Retour un peu à la technique, mais n&#8217;oubliez pas, il vous reste seulement <a  href="/6-mois-deja-bilan-passe-objectifs-futurs-et-des-cadeaux/2009/07/31/">jusqu&#8217;à demain pour gagner une BD</a>.</p>
<p>En ce qui nous concerne, avec les annonces faites lors de la dernière Symfony Conference Live, il faut bien commencer à se lancer dans Doctrine. Et c&#8217;est l&#8217;occasion de découvrir petit à petit cet ORM qui change beaucoup de Propel, pas toujours en bien à mon goût, mais il y a quand même des choses très bien pensées.<br />
En parcourant la <a  class="extern" href="http://www.doctrine-project.org/documentation">doc</a>, je suis donc tombé sur un behavior que j&#8217;ai trouvé fort intéressant: <a  class="extern" href="http://www.doctrine-project.org/documentation/manual/1_1/en/behaviors#core-behaviors:geographical">Geographical</a>.</p>
<p>Je me suis donc laissé tenté par un test de celui-ci!<br />
<span id="more-485"></span><br />
Le principe est simple, il rajoute 2 champs à notre table, latitude et longitude, qui outre le fait de donner les coordonnées GPS de notre adresse, pouvant ainsi alimenter une googlemap, permet également de faire des calculs de distance (à vol d&#8217;oiseau évidemment).<br />
Et d&#8217;ailleurs apparemment, c&#8217;est sa seule fonction, car le remplissage des champs est à notre charge. Mais ça reste une fonctionnalité intéressante.</p>
<p>On se lance donc dans une application à un projet, symfony bien évidemment, avec une table classique d&#8217;adresse avec le behavior de déclaré.<br />
Voici notre schema.yml</p>

<div class="wp_syntax"><div class="code"><pre class="yaml" style="font-family:monospace;">adresses:
  actAs: [ Geographical]
  tableName: adresses
  columns:
    aid: { type: integer(4), primary: true,  autoincrement: true }
    adresse1: { type: string(255), notnull: true }
    adresse2: { type: string(255) }
    cp: { type: string(5), notnull: true }
    ville: { type: string(100), notnull: true }</pre></div></div>

<p>Ce qui donne en base une fois notre table créé:</p>
<pre>+------------+--------------+------+-----+---------+----------------+
| Field      | Type         | Null | Key | Default | Extra          |
+------------+--------------+------+-----+---------+----------------+
| aid        | int(11)      | NO   | PRI | NULL    | auto_increment |
| adresse1   | varchar(255) | NO   |     | NULL    |                |
| adresse2   | varchar(255) | YES  |     | NULL    |                |
| cp         | varchar(5)   | NO   |     | NULL    |                |
| ville      | varchar(100) | NO   |     | NULL    |                |
| latitude   | double       | YES  |     | NULL    |                |
| longitude  | double       | YES  |     | NULL    |                |
+------------+--------------+------+-----+---------+----------------+</pre>
<p>Maintenant que les bases sont posées, on va créer une petite classe rapide qui va nous permettre d&#8217;alimenter les champs latitude et longitude de notre table. Pour cela on va se servir de l&#8217;inévitable googlemap. Il vous faudra pour cela une clé pour utiliser leur API.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> Geoloc
<span style="color: #009900;">&#123;</span>
  <span style="color: #000000; font-weight: bold;">protected</span> 
    <span style="color: #000088;">$adr</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">,</span>
    <span style="color: #000088;">$key</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">,</span>
    <span style="color: #000088;">$url</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">,</span>
    <span style="color: #000088;">$context</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">,</span>
    <span style="color: #000088;">$format</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">,</span>
    <span style="color: #000088;">$x</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">,</span>
    <span style="color: #000088;">$y</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</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> execute<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;">// On utilise un stream_context pour avoir la main sur certaines options plus facilement, comme le timeout de notre connexion</span>
    <span style="color: #000088;">$context</span> <span style="color: #339933;">=</span> <span style="color: #990000;">stream_context_create</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
      <span style="color: #0000ff;">'http'</span> <span style="color: #339933;">=&gt;</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;">'GET'</span><span style="color: #339933;">,</span>
        <span style="color: #0000ff;">'header'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">&quot;Content-type: application/x-www-form-urlencoded<span style="color: #000099; font-weight: bold;">\r</span><span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span>
        <span style="color: #0000ff;">'timeout'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #cc66cc;">5</span><span style="color: #339933;">,</span>
      <span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
    <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// Google n'autorise que les requêtes en GET, on construit donc notre liste de paramètre prêt à emploi</span>
    <span style="color: #000088;">$param</span> <span style="color: #339933;">=</span> <span style="color: #990000;">http_build_query</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
          <span style="color: #0000ff;">'q'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">adr</span><span style="color: #339933;">,</span>
          <span style="color: #0000ff;">'output'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">format</span><span style="color: #339933;">,</span>
          <span style="color: #0000ff;">'oe'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'utf8'</span><span style="color: #339933;">,</span>
          <span style="color: #0000ff;">'sensor'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'false'</span><span style="color: #339933;">,</span>
          <span style="color: #0000ff;">'key'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">key</span>
    <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000088;">$content</span> <span style="color: #339933;">=</span> <span style="color: #990000;">file_get_contents</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">url</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'?'</span><span style="color: #339933;">.</span><span style="color: #000088;">$param</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">,</span> <span style="color: #000088;">$context</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: #000088;">$content</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
      <span style="color: #666666; font-style: italic;">// Le traitement est prévu ici pour du csv</span>
      <span style="color: #000088;">$retour</span> <span style="color: #339933;">=</span> <span style="color: #990000;">explode</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">','</span><span style="color: #339933;">,</span><span style="color: #000088;">$content</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
      <span style="color: #666666; font-style: italic;">// Si le retour est bon, on récupère les coordonnées</span>
      <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$retour</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">==</span> <span style="color: #0000ff;">'200'</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;">x</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$retour</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">2</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">y</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$retour</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">3</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #b1b100;">return</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">x</span><span style="color: #339933;">,</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">y</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">false</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> getX<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;">x</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> getY<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;">y</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Voilà, il suffit de placer cette classe dans un dossier Lib de Symfony, où on bon vous semble. Maintenant on va créer dans notre fichier adresses.class.php 2 méthodes:<br />
- la première qui lancera la mise à jour des champs via google<br />
- la deuxième qui automatisera cette mise à jour, lors d&#8217;une nouvelle insertion et seulement dans ce cas. (et non pas à chaque mise à jour)</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> updateCoordonnees<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$completeAdr</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;;</span>adresse1<span style="color: #339933;">.</span><span style="color: #0000ff;">' '</span><span style="color: #339933;">.</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;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">adresse2</span><span style="color: #009900;">&#41;</span>?<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">adresse2</span><span style="color: #339933;">.</span><span style="color: #0000ff;">' '</span><span style="color: #339933;">.:</span><span style="color: #0000ff;">''</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;">cp</span><span style="color: #339933;">.</span><span style="color: #0000ff;">' '</span><span style="color: #339933;">.</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">ville</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// Ajout adresse2 seulement si non vide</span>
    <span style="color: #000088;">$geoloc</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Geoloc<span style="color: #009900;">&#40;</span><span style="color: #000088;">$completeAdr</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'maCleGoogleMap'</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: #000088;">$data</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$geoloc</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">execute</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: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">latitude</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$data</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
      <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">longitude</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$data</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009933; font-style: italic;">/**
 *  Méthode appelé avant l'insertion d'un nouvel élément. Elle est à surcharger au besoin.
 */</span>
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> preInsert<span style="color: #009900;">&#40;</span><span style="color: #000088;">$event</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;">updateCoordonnees</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Et voilà, avec un fichier de fixtures.yml du genre:</p>

<div class="wp_syntax"><div class="code"><pre class="yaml" style="font-family:monospace;">adresses:
  adresse_1:
    adresse1: 165 avenue du prado
    cp: 13008
    ville: Marseille
  adresse_2:
    adresse1: 7 rue de verdun
    cp: 13005
    ville: Marseille
  adresse_3:
    adresse1: 57 Bd Romain Rolland 
    cp: 13010
    ville: Marseille
  adresse_4:
    adresse1: Route de Gemenos 
    cp: 13400
    ville: Aubagne</pre></div></div>

<p>En le chargeant via symfony, on obtient en base:</p>
<pre>
select * from adresses ;
+-----+----------------------+----------+-------+-----------+------------+-----------+
| aid | adresse1             | address2 | cp    | ville     | latitude   | longitude |
+-----+----------------------+----------+-------+-----------+------------+-----------+
|   1 | 165 avenue du prado  | NULL   | 13008 | Marseille | 43.2783515 | 5.3883703 |
|   2 | 7 rue de verdun      | NULL     | 13005 | Marseille |  43.296542 | 5.3958405 |
|   3 | 57 Bd Romain Rolland | NULL     | 13010 | Marseille | 43.2774579 | 5.4202946 |
|   4 | Route de Gemenos     | NULL     | 13400 | Aubagne  | 43.2975544 | 5.5888222 |
+-----+----------------------+----------+-------+-----------+------------+-----------+
</pre>
<p>Un petit bout de code dans une action, rapidement pour tester:</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> executeTest<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;">$adr1</span> <span style="color: #339933;">=</span> Doctrine<span style="color: #339933;">::</span><span style="color: #004000;">getTable</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'adresses'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">find</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$adr2</span> <span style="color: #339933;">=</span> Doctrine<span style="color: #339933;">::</span><span style="color: #004000;">getTable</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'adresses'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">find</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">2</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">echo</span> <span style="color: #990000;">number_format</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$adr1</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getDistance</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$adr2</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><span style="color: #cc66cc;">2</span><span style="color: #339933;">,</span><span style="color: #0000ff;">','</span><span style="color: #339933;">,</span><span style="color: #0000ff;">''</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'Km'</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// Par défaut, retourne en miles, il faut mettre le 2e paramètre à true pour avoir le résultat en km</span>
&nbsp;
    <span style="color: #b1b100;">return</span> sfView<span style="color: #339933;">::</span><span style="color: #004000;">NONE</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Et on obtient la distance en km entre nos 2 premières adresses. (Ici la distance entre chez moi et mon boulot :p)<br />
Comme l&#8217;indique la doc, on peut aller plus loin, en récupérant pour une adresse donnée, les N adresses les plus proches, ce qui peut donner lieu à des fonctionnalités très intéressantes:</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> executeTest2<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;">$adr1</span> <span style="color: #339933;">=</span> Doctrine<span style="color: #339933;">::</span><span style="color: #004000;">getTable</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'adresses'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">find</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$q</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$adr1</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getDistanceQuery</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$result</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$q</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">orderby</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'miles asc'</span><span style="color: #009900;">&#41;</span> <span style="color: #666666; font-style: italic;">// On les trie par distance</span>
              <span style="color: #339933;">-&gt;</span><span style="color: #004000;">addWhere</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$q</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getRootAlias</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span> <span style="color: #0000ff;">'.aid != ?'</span><span style="color: #339933;">,</span><span style="color: #000088;">$adr1</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">aid</span><span style="color: #009900;">&#41;</span> <span style="color: #666666; font-style: italic;">// On exclut l'adresse de référence</span>
              <span style="color: #339933;">-&gt;</span><span style="color: #004000;">execute</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;">$result</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$res</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
       <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$res</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">cp</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">&quot; - &quot;</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$res</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">kilometers</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">&quot;&lt;br/&gt;&quot;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> sfView<span style="color: #339933;">::</span><span style="color: #004000;">NONE</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span></pre></div></div>

<p>A noter que le code du behavior est très simple en fait, il ajoute juste une formule mathématique pour ces calculs de distance. Mais c&#8217;est ce genre de petites fonctionnalités qui me font apprécier la découverte de Doctrine!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.amicalement-web.net/doctrine-et-son-behavior-geographical/2009/08/05/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>How to: Créer un plugin fckeditor</title>
		<link>http://www.amicalement-web.net/how-to-creer-un-plugin-fckeditor/2009/07/23/</link>
		<comments>http://www.amicalement-web.net/how-to-creer-un-plugin-fckeditor/2009/07/23/#comments</comments>
		<pubDate>Thu, 23 Jul 2009 12:00:22 +0000</pubDate>
		<dc:creator>Tim</dc:creator>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[AJAX]]></category>
		<category><![CDATA[fckeditor]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[plugin]]></category>

		<guid isPermaLink="false">http://www.amicalement-web.net/?p=458</guid>
		<description><![CDATA[Dans le monde du développement web, il y a un domaine où je n&#8217;ai pas encore trouvé une recette miracle: La publication de contenu avec un éditeur WYSIWYG. En même temps, la problématique est costaud, faire éditer du HTML à des gens qui ont déjà du mal avec Word, sans qu&#8217;ils sachent qu&#8217;ils éditent du [...]]]></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" /> Dans le monde du développement web, il y a un domaine où je n&#8217;ai pas encore trouvé une recette miracle: La publication de contenu avec un éditeur <acronym title="What You See Is What You Get">WYSIWYG</acronym>. En même temps, la problématique est costaud, faire éditer du HTML à des gens qui ont déjà du mal avec Word, sans qu&#8217;ils sachent qu&#8217;ils éditent du HTML.</p>
<p>Après avoir définitivement abandonné <a  href="http://tinymce.moxiecode.com/" class="extern">TinyMCE</a>, car trop usine à gaz et n&#8217;en faisant qu&#8217;à sa tête, j&#8217;ai essayé <a  href="http://nicedit.com/" class="extern">nicedit</a> comme je vous l&#8217;avais signalé dans <a  href="/developpement-web-les-bons-plans-de-la-semaine-3/2009/06/19/">un bon plan de la semaine</a>. Malheureusement, il reste un peu juste pour certains besoins.<br />
Sur les conseils de <a  href="http://blog.samuel-trocme.fr/12-07-2009/fckeditor-peut-etre-le-meilleur-rte.html" class="extern">Sam</a>, je me suis donc relancé dans une vieille connaissance, <a  href="http://www.fckeditor.net/" class="extern">FCKEditor</a>, un des plus vieux <acronym title="Rich Text Editor">RTE</acronym> avec TinyMCE.<br />
<span id="more-458"></span><br />
S&#8217;il est a noté de nets progrès, il fait encore un peu usine à gaz (mais moins que TinyMCE quand même) et je le trouve particulièrement moche, mais c&#8217;est un détail qui peut se modifier, donc on va le mettre de côté pour l&#8217;instant ;)</p>
<p>Un des impératifs par contre, c&#8217;est la personnalisation et donc la création de plugin permettant de rajouter des boutons avec des fonctionnalités que l&#8217;on aura déterminer nous même. Et vu les difficultés que j&#8217;ai pu rencontrer pour créer mon premier, je me suis dis que ca valait bien quelques explications. Dans un souci de clarté, je ne détaillerai pas l&#8217;installation de fck, je vous invite à faire un tour sur leur site pour ça.</p>
<p>Première chose quand on veut créer un plugin fck, créer son arborescence, dans <code>editor/plugins</code>. Ici, on va créer un plugin qui nous permettra de rajouter un bouton à notre toolbar qui lancera une fenêtre nous permettant de faire un peu ce qu&#8217;on veut, en l&#8217;occurrence dans notre cas, afficher une liste des pages de notre gestionnaire de contenus symfony afin de pouvoir insérer des liens internes entre elle.  </p>
<p>Dans notre nouveau dossier, vous créez donc un fichier plugin.js avec à l&#8217;intérieur:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #006600; font-style: italic;">// Ici je crée une action FCK qui s'appelle Internlink, et qui chargera le fichier test.html (qui sera au même niveau que ce fichier) lors de son appel</span>
FCKCommands.<span style="color: #660066;">RegisterCommand</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'Internlink'</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">new</span> FCKDialogCommand<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'Internlink'</span><span style="color: #339933;">,</span><span style="color: #3366CC;">'Ajout lien interne'</span><span style="color: #339933;">,</span>FCKConfig.<span style="color: #660066;">PluginsPath</span><span style="color: #339933;">+</span><span style="color: #3366CC;">'internlink/test.html'</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">300</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">300</span> <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #006600; font-style: italic;">// Ici je crée un bouton pour la toolbar auquel j'associe l'action précédemment définie</span>
FCKToolbarItems.<span style="color: #660066;">RegisterItem</span><span style="color: #009900;">&#40;</span> <span style="color: #3366CC;">'Internlink'</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">new</span> FCKToolbarButton<span style="color: #009900;">&#40;</span> <span style="color: #3366CC;">'Internlink'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'Lien interne'</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">null</span><span style="color: #339933;">,</span> FCK_TOOLBARITEM_ICONTEXT<span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">1</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span> <span style="color: #339933;">;</span></pre></div></div>

<p>Ensuite on enchaine avec le template de notre popup qu&#8217;on a appelé test.html plus haut (on le met bien où on veut mais j&#8217;ai définis au-dessus de le mettre au même niveau):</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #00bbdd;">&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD HTML 4.01 Transitional//EN&quot; &quot;http://www.w3.org/TR/html4/loose.dtd&quot;&gt;</span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;html<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;head<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;meta</span> <span style="color: #000066;">http-equiv</span>=<span style="color: #ff0000;">&quot;Content-Type&quot;</span> <span style="color: #000066;">content</span>=<span style="color: #ff0000;">&quot;text/html; charset=UTF-8&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;script</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;text/javascript&quot;</span> <span style="color: #000066;">src</span>=<span style="color: #ff0000;">&quot;http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span><span style="color: #000000; font-weight: bold;">&lt;/script<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;script</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;text/javascript&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
    // Cette partie est nécessaire pour pouvoir utiliser les fonctions de fck à l'intérieur de notre popup 
    var oEditor = window.parent.InnerDialogLoaded();
    var FCKConfig = oEditor.FCKConfig;
    var dialog = window.parent;
    document.write('<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;script</span> <span style="color: #000066;">src</span>=<span style="color: #ff0000;">&quot;' + FCKConfig.BasePath + 'dialog/common/fck_dialog_common.js&quot;</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;text/javascript&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span>&lt;\/script<span style="color: #000000; font-weight: bold;">&gt;</span></span>');
    dialog.SetOkButton(true); // Par défaut, seul le bouton annuler est affiché, on rajoute le bouton ok	
&nbsp;
    // Maintenant on fait bien ce qu'on veux, ici j'ai décidé de récupérer en AJAX, une liste en JSON de toutes mes pages et d'alimenter ma selectbox avec
    jQuery(document).ready(function(){
      $.getJSON(&quot;/content/selectJson&quot;,{}, function(j){
        var options = '';
        for (var i = 0; i <span style="color: #009900;">&lt; j.length; i++<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span></span>
<span style="color: #009900;">          options += <span style="color: #ff0000;">'&lt;option value=&quot;'</span> + j<span style="color: #66cc66;">&#91;</span>i<span style="color: #66cc66;">&#93;</span>.optionValue + <span style="color: #ff0000;">'&quot;&gt;</span></span>' + j[i].optionDisplay + '<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/option<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>';
        }
        $(&quot;select#intern-link&quot;).html(options);
      })
    });
&nbsp;
    // Puis on surdéfinit une fonction Ok qui est appelé par fck quand on appuye sur le bouton ... ok
    function Ok()
    {
      // Maintenant on utilise fck pour rajouter du contenu à notre RTE. Ici je rajoute simplement les valeurs de mes 2 champs définis dans mon HTML ci-dessous
      oEditor.FCK.InsertHtml( '<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;a</span> <span style="color: #000066;">href</span>=<span style="color: #ff0000;">&quot;'+ jQuery('#intern-link').val() +'&quot;</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;extern&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>'+ jQuery('#intern-label').val() +'<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/a<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>' );
      return true; // Il faut renvoyer true pour fermer la popup
    }
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/script<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/head<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;body<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> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;add-intern-link&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;label</span> <span style="color: #000066;">for</span>=<span style="color: #ff0000;">&quot;intern-link&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>Lien interne<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;select</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;intern-link&quot;</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;intern-link&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
			<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/select<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;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> <span style="color: #000066;">for</span>=<span style="color: #ff0000;">&quot;intern-label&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>Label<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;">type</span>=<span style="color: #ff0000;">&quot;text&quot;</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;intern-label&quot;</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;intern-label&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;/div<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/body<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/html<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>

<p>Il ne reste plus qu&#8217;à charger notre plugin dans notre conf:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">FCKConfig.<span style="color: #660066;">Plugins</span>.<span style="color: #660066;">Add</span><span style="color: #009900;">&#40;</span> <span style="color: #3366CC;">'internlink'</span> <span style="color: #009900;">&#41;</span> <span style="color: #339933;">;</span></pre></div></div>

<p>et ajouter le bouton à notre toolbar comme par exemple:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">FCKConfig.<span style="color: #660066;">ToolbarSets</span><span style="color: #009900;">&#91;</span><span style="color: #3366CC;">&quot;nice&quot;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#91;</span><span style="color: #3366CC;">'Internlink'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span></pre></div></div>

<p> et on obtient:<br />
<a  href="http://www.amicalement-web.net/wp-content/uploads/Image-67.png"><img src="http://www.amicalement-web.net/wp-content/uploads/Image-67-300x37.png" alt="Image 67" title="Image 67" width="300" height="37" class="alignnone size-medium wp-image-461" /></a></p>
<p><a  href="http://www.amicalement-web.net/wp-content/uploads/Image-68.png"><img src="http://www.amicalement-web.net/wp-content/uploads/Image-68.png" alt="Image 68" title="Image 68" width="287" height="298" class="alignnone size-full wp-image-460" /></a></p>
<p>On a maintenant accès à toutes nos pages, et un clic sur ok, nous rajoutera un lien dans notre contenu avec le label renseigné. </p>
<p>Il ne reste plus qu&#8217;à adapter à vos besoins ces petits bouts de codes!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.amicalement-web.net/how-to-creer-un-plugin-fckeditor/2009/07/23/feed/</wfw:commentRss>
		<slash:comments>4</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>
	</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! -->
