<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet title="XSL formatting" type="text/xsl" href="http://mirmodynamics.com/feed/rss2/xslt" ?><rss version="2.0"
  xmlns:dc="http://purl.org/dc/elements/1.1/"
  xmlns:wfw="http://wellformedweb.org/CommentAPI/"
  xmlns:content="http://purl.org/rss/1.0/modules/content/"
  xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
  <title>Mirmo Dynamics - Tag - MVC</title>
  <link>http://mirmodynamics.com/</link>
  <atom:link href="http://mirmodynamics.com/feed/tag/MVC/rss2" rel="self" type="application/rss+xml"/>
  <description>Si tu kiffes pas reunoi, t'écoutes pas et puis c'est tout.</description>
  <language>en</language>
  <pubDate>Sun, 14 Mar 2010 19:59:01 +0100</pubDate>
  <copyright>2003-2009 &amp;copy; Geoffrey Bachelet</copyright>
  <docs>http://blogs.law.harvard.edu/tech/rss</docs>
  <generator>Dotclear</generator>
  
    
  <item>
    <title>Zend Framework: Un plugin simple pour le Front Controller</title>
    <link>http://mirmodynamics.com/post/2006/11/19/Zend-Framework%3A-Un-plugin-simple-pour-le-Front-Controller</link>
    <guid isPermaLink="false">urn:md5:6c829cc8dbd18739b84ef7758d852a70</guid>
    <pubDate>Sun, 19 Nov 2006 21:30:00 +0100</pubDate>
    <dc:creator>Geoffrey</dc:creator>
        <category>Coding</category>
        <category>bootstrap</category><category>howto</category><category>MVC</category><category>organisation</category><category>php</category><category>plugin</category><category>vues</category><category>zend framework</category>    
    <description>&lt;p&gt;L'implémentation du &lt;code&gt;Front Controller&lt;/code&gt; du &lt;a href=&quot;http://framework.zend.com/&quot;&gt;Zend Framework&lt;/a&gt; inclue un système bien pratique de plugins, qui va nous permettre de réaliser plus simplement et proprement &lt;a href=&quot;http://fashion.hosmoz.net/blog/post/2006/08/30/Automatisation-des-vues&quot;&gt;l'automatisation des vues&lt;/a&gt;, initialement embarquée dans une extension de &lt;code&gt;Zend_Controller_Action&lt;/code&gt; (ce qui pose quelques problèmes, nottament au lors de l'utilisation de &lt;code&gt;__forward()&lt;/code&gt; et &lt;code&gt;_redirect()&lt;/code&gt;).&lt;/p&gt;    &lt;p&gt;Techniquement, un plugin est une classe qui implémente l'interface des plugins (&lt;code&gt;Zend_Controller_Plugin_Interface&lt;/code&gt;). Dans la pratique, une classe abstraite est fournie pour simplifier la tache (&lt;code&gt;Zend_Controller_Plugin_Abstract&lt;/code&gt;). Notre premier plugin s'appellera &lt;code&gt;AutoView&lt;/code&gt; (&lt;code&gt;My_Controller_Plugin_AutoView&lt;/code&gt;, stocké dans &lt;code&gt;My/Controller/Plugin/AutoView.php&lt;/code&gt;).&lt;/p&gt;


&lt;p&gt;Un plugin est donc une classe dont les méthodes seront appelées a différents moments de la &lt;em&gt;dispatch loop&lt;/em&gt; du controlleur frontal, comme on peut le voir dans &lt;code&gt;Zend_Controller_Front::dispatch()&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;routeStartup()&lt;/code&gt;, à la mise en route du routeur&lt;/li&gt;
&lt;li&gt;&lt;code&gt;routeShutdown($action)&lt;/code&gt;, à l'arrêt du routeur&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dispatchLoopStartup($action)&lt;/code&gt;, avant la &lt;em&gt;dispatch loop&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;preDispatch($action)&lt;/code&gt;, avant d'executer une action&lt;/li&gt;
&lt;li&gt;&lt;code&gt;postDispatch($action)&lt;/code&gt;, après avoir executé une action&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dispatchLoopShutdown()&lt;/code&gt;, pour finir.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A chaud, on pourrait se dire que &lt;code&gt;postDispatch&lt;/code&gt; est exactement ce dont on n'a besoin, et on se tromperait. Ce qu'il faut savoir, c'est que l'argument &lt;code&gt;$action&lt;/code&gt; passé à &lt;code&gt;postDispatch&lt;/code&gt; contient l'action qui suit celle qui vient d'être executé. Dans la majorité des cas, n'ayant qu'une seule action à executer, &lt;code&gt;$action&lt;/code&gt; sera vide, et on se retrouve l'air un peu con.&lt;/p&gt;


&lt;p&gt;Bon donc, on va user d'un stratagème: notre plugin va stocker les actions qui passent dans &lt;code&gt;preDispatch&lt;/code&gt;, pour s'occuper de la dernière à être passée dans &lt;code&gt;dispatchLoopShutdown&lt;/code&gt;. Dernier détail, notre plugin s'occupera lui même de gérer son instance de &lt;code&gt;Zend_View&lt;/code&gt;. Et sans plus attendre, le code, qui n'a finalement rien de compliqué:&lt;/p&gt;

&lt;pre&gt;
&amp;lt;?php

require_once 'Zend/Controller/Plugin/Abstract.php';

class My_Controller_Plugin_AutoView extends Zend_Controller_Plugin_Abstract {

	private $_lastAction;

	public function __construct() {
		$view = new Zend_View;
		$view-&amp;gt;setScriptPath(APP_ROOT.'/views/');
		Zend::register('view', $view);
	}

	public function preDispatch($action) {
		$this-&amp;gt;_lastAction = clone($action);
		return $action;
	}

	public function dispatchLoopShutdown() {
		if (!is_null($this-&amp;gt;_lastAction)) {
			$viewPath = sprintf('%s/%s.php', $this-&amp;gt;_lastAction-&amp;gt;getControllerName(), $this-&amp;gt;_lastAction-&amp;gt;getActionName());
			echo Zend::registry('view')-&amp;gt;render($viewPath);
		}
	}
}

?&amp;gt;
&lt;/pre&gt;


&lt;p&gt;Bien, notre plugin vaillament codé, il nous faut désormais expliquer au controlleur frontal qu'on aimerai bien qu'il en tienne compte. Cela se passe fort logiquement dans le &lt;em&gt;bootstrap&lt;/em&gt;, via la méthode &lt;code&gt;registerPlugin&lt;/code&gt; du sus-cité controlleur frontal, qui prend en argument une instance d'un objet implémentant &lt;code&gt;Zend_Controller_Plugin_Interface&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;
$controller = Zend_Controller_Front::getInstance();
$controller-&amp;gt;registerPlugin(new My_Controller_Plugin_AutoView);
&lt;/pre&gt;


&lt;p&gt;And viola !&lt;/p&gt;</description>
    
    
    
          <comments>http://mirmodynamics.com/post/2006/11/19/Zend-Framework%3A-Un-plugin-simple-pour-le-Front-Controller#comment-form</comments>
      <wfw:comment>http://mirmodynamics.com/post/2006/11/19/Zend-Framework%3A-Un-plugin-simple-pour-le-Front-Controller#comment-form</wfw:comment>
      <wfw:commentRss>http://mirmodynamics.com/feed/atom/comments/720</wfw:commentRss>
      </item>
    
  <item>
    <title>Howto: Utiliser Zend_Controller_RewriteRouter avec Zend_Config</title>
    <link>http://mirmodynamics.com/post/2006/10/31/Howto%3A-Utiliser-Zend_Controller_RewriteRouter-avec-Zend_Config</link>
    <guid isPermaLink="false">urn:md5:58ec785aef55507ca8784ce7b8d798b3</guid>
    <pubDate>Tue, 31 Oct 2006 20:26:00 +0100</pubDate>
    <dc:creator>Geoffrey</dc:creator>
        <category>Coding</category>
        <category>bootstrap</category><category>configuration</category><category>controlleurs</category><category>doc</category><category>howto</category><category>ini</category><category>MVC</category><category>php</category><category>zend framework</category>    
    <description>&lt;p&gt;Comme je le disais plus bas, le Zend Framework Preview 0.2.0 est dans les bacs ! Cette nouvelle mouture apporte son lot de nouveautés, et nous allons nous pencher sur une des plus interressantes: le &lt;em&gt;RewriteRouter&lt;/em&gt;. Le &lt;em&gt;RewriteRouter&lt;/em&gt; est un routeur pour le composant &lt;acronym&gt;MVC&lt;/acronym&gt; du Zend Framework qui va nous permettre de configurer nos &lt;acronym&gt;URL&lt;/acronym&gt; comme dans Ruby on Rails, c'est à dire (en gros), via un fichier de configuration, et c'est là que &lt;em&gt;Zend_Config&lt;/em&gt; entre en jeu.&lt;/p&gt;    &lt;h3&gt;Mettre en place le routeur&lt;/h3&gt;


&lt;p&gt;C'est bien beau tout ça, mais pour l'utiliser, il faut déjà en informer le controlleur. Pour cela, rien de plus simple, on utilise la méthode &lt;code&gt;addRouter&lt;/code&gt;:&lt;/p&gt;


&lt;pre&gt;$router = new Zend_Controller_RewriteRouter;
$controller = Zend_Controller_Front::getInstance();
$controller-&amp;gt;setRouter($router);&lt;/pre&gt;


&lt;p&gt;Le &lt;em&gt;RewriteRouter&lt;/em&gt; est pré-configuré avec deux routes qui permettent d'assurer la compatibilité descendante avec l'ancien routeur, donc jusque là, tout va bien.&lt;/p&gt;


&lt;h3&gt;Déclarer les routes&lt;/h3&gt;


&lt;p&gt;Nous utiliserons un fichier de configuration dédié aux routes, que nous appellerons sobrement &lt;em&gt;routes.ini&lt;/em&gt;, et que nous placerons dans &lt;code&gt;app/&lt;/code&gt;, à coté de son compagnon &lt;em&gt;config.ini&lt;/em&gt;. Ce fichier de configuration contiendra une unique section &lt;code&gt;[routes]&lt;/code&gt;, qui contiendra à son tour les multiples définitions de routes que nous souhaitons y caser. Une route se compose de 5 éléments principaux:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;L'identifiant de la route. C'est un identifiant interne utilisé par le &lt;code&gt;RewriteRouter&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;l'&lt;acronym&gt;URL&lt;/acronym&gt; de la route, c'est ce qui permet au routeur de reconnaitre la route à utiliser,&lt;/li&gt;
&lt;li&gt;les valeurs par défauts des variables,&lt;/li&gt;
&lt;li&gt;les requirements de la route, qui permettent de déterminer si une route est bien formée ou non.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Sans plus attendre, un petit exemple: la route qui &lt;em&gt;pourrait&lt;/em&gt; permettre d'accéder à un billet dans dotclear 2:&lt;/p&gt;


&lt;pre&gt;post.route = post/:year/:month/:day/:title
post.reqs.year = &amp;quot;\d+&amp;quot;
post.reqs.month = &amp;quot;\d+&amp;quot;
post.reqs.day = &amp;quot;\d+&amp;quot;
post.reqs.title = &amp;quot;[a-zA-Z0-9_:-]&amp;quot;+
post.defaults.controller = post
post.defaults.action = view
post.defaults.title =&lt;/pre&gt;


&lt;p&gt;Elle &lt;em&gt;pourrait&lt;/em&gt; seulement, car en fait, la regexp du &lt;code&gt;title&lt;/code&gt; est trop restrictive (une &lt;acronym&gt;URL&lt;/acronym&gt; peut contenir d'autres caractères que ceux là), et de plus, les &lt;acronym&gt;URL&lt;/acronym&gt; stockées par dotclear 2 en base de données comprennent tout ce qui se trouve après &lt;code&gt;post/&lt;/code&gt; (par exemple le champs &lt;code&gt;post_url&lt;/code&gt; de ce billet contient: &lt;code&gt;2006/10/31/Howto:-Utiliser-Zend_Controller_RewriteRouter-avec-Zend_Config&lt;/code&gt;).&lt;/p&gt;


&lt;p&gt;Cela étant dit, la route que nous venons de décrire s'appliquera aux &lt;acronym&gt;URL&lt;/acronym&gt;s suivantes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;/post/2006/30/10/ZendFramework&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/post/42/2006/56/Foobar&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/post/2006/30/10/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Mais pas à:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;/post/2006/Foobar&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/post/Foobar/2006/30/01&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On note donc d'ores et déjà:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;que la validation des composants d'une route se fait par expression régulière&lt;/li&gt;
&lt;li&gt;qu'on peut ommettre le dernier composant d'une route si il possède une valeur par défaut (récursivement)&lt;/li&gt;
&lt;li&gt;qu'on ne peut pas modifier l'ordre des composants d'une route&lt;/li&gt;
&lt;li&gt;qu'on doit spécifier manuellement le nom du controlleur et de l'action à utiliser&lt;/li&gt;
&lt;li&gt;et c'est déjà pas mal.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Décortiquons maintenant une &lt;acronym&gt;URL&lt;/acronym&gt;: &lt;code&gt;/post/2006/30/10/ZendFramework&lt;/code&gt;. Le routeur va diviser cette &lt;acronym&gt;URL&lt;/acronym&gt; ainsi:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Controller: &lt;code&gt;post&lt;/code&gt; (d'après les &lt;em&gt;defaults&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;Action: &lt;code&gt;view&lt;/code&gt; (d'après les &lt;em&gt;defaults&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;Paramètres: &lt;code&gt;year&lt;/code&gt;: 2006, &lt;code&gt;month&lt;/code&gt;: 30, &lt;code&gt;day&lt;/code&gt;: 10, &lt;code&gt;title&lt;/code&gt;: ZendFramework (d'après l'&lt;acronym&gt;URL&lt;/acronym&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Les paramètres ainsi détectés seront disponibles via la méthode &lt;code&gt;$this-&amp;gt;_getParam($name);&lt;/code&gt; a l'intérieur du controlleur.&lt;/p&gt;


&lt;p&gt;Dernier point de ce chapitre, une déclaration de route peut comporter deux variables spéciales: &lt;code&gt;:controller&lt;/code&gt; et &lt;code&gt;:action&lt;/code&gt;, qui servent respectivement à détecter le controller et l'action à utiliser dans l'url. Par exemple, la route &lt;em&gt;builtin&lt;/em&gt; &lt;code&gt;compat&lt;/code&gt; chargé d'assurer la compatibilité descendante se déclare ainsi:&lt;/p&gt;


&lt;pre&gt;compat.route = :controller/:action
compat.defaults.controller = index
compat.defaults.action = index&lt;/pre&gt;


&lt;h3&gt;Assembler le tout&lt;/h3&gt;


&lt;p&gt;Dernière étape, transférer directement toutes ces déclarations dans le Routeur: n'y allons pas par quatre chemin:&lt;/p&gt;


&lt;pre&gt;$router-&amp;gt;addConfig(new Zend_Config_Ini('/path/to/routes.ini', null), 'routes');&lt;/pre&gt;


&lt;p&gt;C'est aussi simple que ça. Ce qui nous donne, en prenant en compte le morceau de code du début de l'article:&lt;/p&gt;


&lt;pre&gt;$router = new Zend_Controller_RewriteRouter;
$router-&amp;gt;addConfig(new Zend_Config_Ini($routes_path, null), 'routes');
$controller = Zend_Controller_Front::getInstance();
$controller-&amp;gt;setRouter($router);&lt;/pre&gt;


&lt;p&gt;And voilà. Je ne saurais que vous conseiller la lecture du &lt;a href=&quot;http://framework.zend.com/manual/en/zend.controller.rewriterouter.html&quot;&gt;manuel&lt;/a&gt; pour plus d'informations (sachant qu'en fait, &lt;code&gt;addRoute&lt;/code&gt; attend en deuxième argument une instance de &lt;code&gt;Zend_Controller_Router_Route&lt;/code&gt;, mais qui s'instancie avec les paramètres qu'ils passent à &lt;code&gt;addRoute&lt;/code&gt;, petite coquille du manuel :p).&lt;/p&gt;</description>
    
    
    
          <comments>http://mirmodynamics.com/post/2006/10/31/Howto%3A-Utiliser-Zend_Controller_RewriteRouter-avec-Zend_Config#comment-form</comments>
      <wfw:comment>http://mirmodynamics.com/post/2006/10/31/Howto%3A-Utiliser-Zend_Controller_RewriteRouter-avec-Zend_Config#comment-form</wfw:comment>
      <wfw:commentRss>http://mirmodynamics.com/feed/atom/comments/710</wfw:commentRss>
      </item>
    
  <item>
    <title>Automatisation des vues</title>
    <link>http://mirmodynamics.com/post/2006/08/30/Automatisation-des-vues</link>
    <guid isPermaLink="false">urn:md5:1d9d59b981f8ce7f914908cf7957d4da</guid>
    <pubDate>Wed, 30 Aug 2006 13:17:00 +0200</pubDate>
    <dc:creator>Geoffrey</dc:creator>
        <category>Coding</category>
        <category>howto</category><category>MVC</category><category>php</category><category>zend framework</category>    
    <description>    &lt;p&gt;Le rebutement principal que j'ai eu au début avec le Zend Framework était l'impossibilité (a priori) d'automatiser le rendu des vues en fonction du controlleur et de l'action appelés. Mes pérénigrations webesques m'ont finalement fait entrevoir &lt;a href=&quot;http://svn.akrabat.com/svnvi.pl?file=Action.php&amp;amp;repos=AkCom&amp;amp;path=/trunk/library/AkCom/Controller&quot;&gt;la solution&lt;/a&gt;.&lt;/p&gt;


&lt;p&gt;&lt;strong&gt;EDIT&lt;/strong&gt;: mes nouvelles pérégrinations dans les sources du Zend Framework m'ont fait entrevoir &lt;a href=&quot;http://fashion.hosmoz.net/blog/post/2006/11/18/Howto%3A-Un-plugin-simple-pour-le-controller&quot;&gt;une meilleure solution&lt;/a&gt; :-)&lt;/p&gt;


&lt;p&gt;Tout se passe dans le destructeur du controlleur, et nous allons voir ici une version édulcorée de celle disponible dans le lien sus-cité. L'astuce qui sauve, c'est de savoir que l'objet &lt;code&gt;Controller&lt;/code&gt; possède un membre &lt;code&gt;_action&lt;/code&gt;, qui lui même propose (entre autres) deux méthodes bien utiles: &lt;code&gt;getControllerName&lt;/code&gt; et &lt;code&gt;getActionName&lt;/code&gt;. Il suffit donc de récupérer ces informations pour construire dynamiquement le chemin de la vue à utiliser pour un controlleur donné:&lt;/p&gt;


&lt;pre&gt;abstract class My_Controller_Action extends Zend_Controller_Action {
	public function __destruct() {
		$view = Zend::registry('view');
		$controller = $this-&amp;gt;_action-&amp;gt;getControllerName();
		$action = $this-&amp;gt;_action-&amp;gt;getActionName();
		$viewPath = sprintf('%s/%s.php', $controller, $action);
		try {
			echo $view-&amp;gt;render($viewPath);
		} catch (Exception $e) {
			trigger_error('Unable to render view: ' . $e-&amp;gt;getMessage(), E_USER_ERROR);
		}
	}
}&lt;/pre&gt;


&lt;p&gt;&lt;a href=&quot;http://fashion.hosmoz.net/public/sources/577.phps&quot;&gt;Fichier source&lt;/a&gt;&lt;/p&gt;


&lt;p&gt;Ce controlleur requiert que vous ayez instancié, configuré et enregistré &lt;code&gt;Zend_View&lt;/code&gt; au préalable. Il ira, lors de sa destruction, chercher la vue dont le nom correspond à &lt;code&gt;controller/action.php&lt;/code&gt;, c'est à dire:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;pour une URL du type &lt;code&gt;http://example.com/foo/bar/&lt;/code&gt;, &lt;code&gt;foo/bar.php&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;pour &lt;code&gt;http://example.com/&lt;/code&gt;, &lt;code&gt;index/index.php&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;pour &lt;code&gt;http://example.com/foo/&lt;/code&gt;, &lt;code&gt;foo/index.php&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pour une raison obscure, on ne peut pas laisser trainer l'éventuelle exception générée par &lt;code&gt;Zend_View&lt;/code&gt; dans le cas d'une vue inexistante. Cela entre en conflit avec une autre Exception qui traine, j'essayerai de tirer ça au clair :-)&lt;/p&gt;</description>
    
    
    
          <comments>http://mirmodynamics.com/post/2006/08/30/Automatisation-des-vues#comment-form</comments>
      <wfw:comment>http://mirmodynamics.com/post/2006/08/30/Automatisation-des-vues#comment-form</wfw:comment>
      <wfw:commentRss>http://mirmodynamics.com/feed/atom/comments/577</wfw:commentRss>
      </item>
    
</channel>
</rss>