<?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 - surclassage</title>
  <link>http://mirmodynamics.com/</link>
  <atom:link href="http://mirmodynamics.com/feed/tag/surclassage/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>Collections, Object Chaining, et la vérité sur le Père Noël</title>
    <link>http://mirmodynamics.com/post/2006/11/29/Collections-Object-Chaining-et-la-verite-sur-le-Pere-Noel</link>
    <guid isPermaLink="false">urn:md5:e7c45d491281466d693e2b556945606a</guid>
    <pubDate>Wed, 29 Nov 2006 23:09:00 +0100</pubDate>
    <dc:creator>Geoffrey</dc:creator>
        <category>Coding</category>
        <category>clichés</category><category>php</category><category>rigolo</category><category>SPL</category><category>surclassage</category><category>zend framework</category>    
    <description>    &lt;p&gt;Aujourd'hui je vais vous parler de deux concepts que j'aime beaucoup et que j'ai (re)découverts en travaillant sur mon projet personnel de conquête de l'univers: les Collections d'objets et l'Object Chaining.&lt;/p&gt;


&lt;p&gt;Les collections, qui sont peut-être finalement un design pattern connu sous un autre nom, permettent d'executer aisément des méthodes sur plusieurs objets (une collection d'objets quoi). Concrétement, disons qu'on à une classe &lt;code&gt;My_Collection&lt;/code&gt;, qui implémente les interfaces &lt;code&gt;Iterator&lt;/code&gt; (et &lt;code&gt;Countable&lt;/code&gt; tant qu'a faire) de la &lt;acronym&gt;SPL&lt;/acronym&gt;, ainsi que la fonction magique &lt;code&gt;__call&lt;/code&gt; suivante (je vous fait grace du docblock):&lt;/p&gt;

&lt;pre&gt;
class My_Collection implements Iterator, Countable {
	public function __call($method, $args) {
		$calls = 0;
		foreach($this as $item) {
			if (method_exists($item, $method)) {
				call_user_func_array(array($item, $method), $args);
				$calls++;
			}
		}
		if ($calls &amp;gt; 0) {
			return $this;
		} else {
			throw new My_Collection_Exception('Method catched but could not be called: '.$method);
		}
	}
}
&lt;/pre&gt;


&lt;p&gt;Ce &lt;em&gt;dispositif&lt;/em&gt; permet d'utiliser le genre de code suivant (si les objets de la collection le permettent, bien évidemment, et disons qu'ici ce sont des objets représentant des images, supportant les méthodes &lt;code&gt;move&lt;/code&gt; et &lt;code&gt;createThumbnail&lt;/code&gt;):&lt;/p&gt;

&lt;pre&gt;
# $array contient les objets My_Image
$collection = new My_Collection($array);
$collection-&amp;gt;move('/new/path/')-&amp;gt;createThumbnail();
&lt;/pre&gt;


&lt;p&gt;Ce qui, comme vous l'aurez deviné, déplacera les fichiers de la collection vers &lt;code&gt;/new/path&lt;/code&gt;, puis en créera des miniatures.&lt;/p&gt;


&lt;p&gt;Deuxième chose, l'Object Chaining. On vient de le voir en fait, ça consiste à &lt;em&gt;chainer&lt;/em&gt; les appels de méthodes grâce à un subtil &lt;code&gt;return $this;&lt;/code&gt;, qui retourne donc une référence à l'objet courant. Exemple pratique, dans le Zend Framework, en étendant &lt;code&gt;Zend_View&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;
class My_View extends Zend_View {
	public function assign($spec) {
		$args = func_get_args();
		call_user_func_array(array('parent', 'assign'), $args);
		return $this;
	}
}
&lt;/pre&gt;


&lt;p&gt;Ce qui autorise le genre de code suivant (en admettant que vous ayiez une instance de &lt;code&gt;My_View&lt;/code&gt; dans le registre):&lt;/p&gt;

&lt;pre&gt;
Zend::registry('view')
	-&amp;gt;assign('foo', $foo)
	-&amp;gt;assign('foo', $bar)
	-&amp;gt;render('template.php');
&lt;/pre&gt;


&lt;p&gt;Et là c'est fort, parceque ça rejoint fortement &lt;a href=&quot;http://fashion.hosmoz.net/blog/post/2006/01/28/489-considerations-nocturne-sur-php&quot;&gt;quelque chose dont je parlais en janvier dernier&lt;/a&gt; (le truc qui parle de &lt;code&gt;with&lt;/code&gt;), et donc j'en déduis une chose formidable: &lt;strong&gt;Le père noël existe&lt;/strong&gt;, et il m'a entendu. Merci Santa Copain.&lt;/p&gt;</description>
    
    
    
          <comments>http://mirmodynamics.com/post/2006/11/29/Collections-Object-Chaining-et-la-verite-sur-le-Pere-Noel#comment-form</comments>
      <wfw:comment>http://mirmodynamics.com/post/2006/11/29/Collections-Object-Chaining-et-la-verite-sur-le-Pere-Noel#comment-form</wfw:comment>
      <wfw:commentRss>http://mirmodynamics.com/feed/atom/comments/728</wfw:commentRss>
      </item>
    
  <item>
    <title>Bootstrap CLI</title>
    <link>http://mirmodynamics.com/post/2006/10/13/Bootstrap-CLI</link>
    <guid isPermaLink="false">urn:md5:1e9ff0bf3342af30f0bcc1b219d7f60a</guid>
    <pubDate>Fri, 13 Oct 2006 18:31:00 +0200</pubDate>
    <dc:creator>Geoffrey</dc:creator>
        <category>Coding</category>
        <category>arborescence</category><category>bootstrap</category><category>CLI</category><category>howto</category><category>librairie</category><category>organisation</category><category>surclassage</category><category>zend framework</category>    
    <description>&lt;p&gt;Nous avons parcouru dernièrement la création du bootstrap &lt;acronym&gt;HTTP&lt;/acronym&gt; qui sert de socle à une application utilisant le Zend Framework. Le même principe peut s'appliquer aux scripts &lt;acronym&gt;CLI&lt;/acronym&gt;, mais comme les besoins sont fondamentalements différents, l'implémentation sera elle aussi complètement différente. Nous viserons les objectifs suivants:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Ne pas être obligé d'executer le bootstrap en ligne de commande&lt;/li&gt;
&lt;li&gt;Simplifier au maximum l'écriture ultérieure des scripts &lt;acronym&gt;CLI&lt;/acronym&gt;&lt;/li&gt;
&lt;li&gt;Définir un jeu d'options de ligne de commande obligatoire&lt;/li&gt;
&lt;li&gt;Mettre en place un environnement d'execution&lt;/li&gt;
&lt;/ol&gt;    &lt;p&gt;La tentation serait de créer un système qui obligerait ce genre de commandes:&lt;/p&gt;


&lt;pre&gt;$ php batch/bootstrap.php monscript&lt;/pre&gt;


&lt;p&gt;Pour executer, par exemple, le script &lt;code&gt;batch/monscript.php&lt;/code&gt;. Cela simplifierait grandement les choses, mais c'est moche, et puis on peut faire autrement, donc on ne va pas se priver ! Nous utiliserons a cette fin la fonction magique &lt;code&gt;register_shutdown_function&lt;/code&gt;, qui s'occupera d'appeler une fonction qui executera les scripts &lt;em&gt;ad hoc&lt;/em&gt;.&lt;/p&gt;


&lt;p&gt;Avant d'aller plus loin, l'arborescence de fichiers que nous allons utiliser:&lt;/p&gt;


&lt;pre&gt;batch/
	monscript.php
	runtime.php
library/
	Zend.php
	My/
		Batch.php&lt;/pre&gt;


&lt;p&gt;&lt;code&gt;runtime.php&lt;/code&gt; sera le fichier à inclure dans chaque script, tandis que &lt;code&gt;My/Batch.php&lt;/code&gt; contiendra la classe d'abstraction &lt;code&gt;My_Batch&lt;/code&gt;, qui définira les comportements par défaut de nos scripts.&lt;/p&gt;


&lt;p&gt;Voici donc la première partie de notre bootstrap, &lt;code&gt;batch/runtime.php&lt;/code&gt;:&lt;/p&gt;


&lt;pre&gt;ini_set('include_path', get_include_path().PATH_SEPARATOR.realpath(dirname(__FILE__).'/../library/'));

require_once 'Zend.php';
require_once 'My/Batch.php';

register_shutdown_function(array('My_Batch', 'runAll'));&lt;/pre&gt;


&lt;p&gt;Bien sur, cette méthode nous oblige à définir un format à respecter pour les fonctions à executer par la suite, nous partirons donc sur les bases suivantes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Chaque batch doit être constitué d'une classe dont le nom commence par &lt;code&gt;My_Batch_&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Chaque batch doit posséder une méthode executable &lt;code&gt;run&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ce qui nous donne donc:&lt;/p&gt;


&lt;pre&gt;abstract class My_Batch {
	static public function runAll() {
		$classes = get_declared_classes();
		foreach($classes as $className) {
			if (preg_match('/^My_Batch_(.+)$/', $className, $matches) &amp;amp;&amp;amp; method_exists($className, 'run')) {
				try {
					$batch = new $className;
					$batch-&amp;gt;run();
				} catch (Exception $e) {
					die(sprintf(&amp;quot;%s: %s\n&amp;quot;, $matches[1], $e-&amp;gt;getMessage()));
				}
			}
		}
	}
	
	abstract public function run();
}&lt;/pre&gt;


&lt;p&gt;On en profite pour catcher toute Exception indésirable pour la transformer en un &lt;code&gt;die&lt;/code&gt;, bien plus lisible dans un terminal qu'une backtrace :-)&lt;/p&gt;


&lt;p&gt;Maintenant que nous avons résolu les points 1 et 2, attaquons nous à la suite. Le problème principal que j'ai rencontré lors de l'établissement d'un environnement d'execution, c'est que la gestion de la configuration repose en grande partie sur la valeur de &lt;code&gt;$_SERVER['HTTP_HOST']&lt;/code&gt;, qui n'est bien évidemment pas disponible en &lt;acronym&gt;CLI&lt;/acronym&gt; :-) Il me faut donc forcer le passage en argument du nom de la configuration à utiliser. C'est très simple à faire, grace a la méthode que nous avons employé: il suffit de vérifier la présence de cet argument dans le constructeur de &lt;code&gt;My_Batch&lt;/code&gt; :-)&lt;/p&gt;


&lt;pre&gt;public function __construct() {
	foreach($GLOBALS['argv'] as $i =&amp;gt; $arg) {
		switch ($arg) {
			case '--configname':
			case '-c':
				$this-&amp;gt;_args['configname'] = $GLOBALS['argv'][$i+1];
			break;
		}
	}
	if (!isset($this-&amp;gt;_args['configname'])) {
		throw new Exception('-c or --configname is mandatory');
	}
}&lt;/pre&gt;


&lt;p&gt;Voilà, le gros du travail est fait. Pour le reste, c'est la routine, mise en place d'un environnement avec &lt;code&gt;Zend_Config&lt;/code&gt; et &lt;code&gt;Zend_Db&lt;/code&gt;, a la suite dans le constructeur:&lt;/p&gt;


&lt;pre&gt;	$this-&amp;gt;_config = new Zend_Config(
		Zend_Config_Ini::load(
			dirname(__FILE__).'/../../app/config.ini',
			$this-&amp;gt;_args['configname']
		)
	);
	
	$this-&amp;gt;_db = Zend_Db::factory(
		$this-&amp;gt;_config-&amp;gt;db-&amp;gt;adapter,
		$this-&amp;gt;_config-&amp;gt;db-&amp;gt;config-&amp;gt;asArray()
	);
	
	Zend_Db_Table::setDefaultAdapter($this-&amp;gt;_db);&lt;/pre&gt;


&lt;p&gt;Enfin, voila un exemple de script utilisant ce bootstrap:&lt;/p&gt;


&lt;pre&gt;require_once 'path/to/runtime.php';

class My_Batch_MonScript extends My_Batch {
	public function run() {
		// le code ici
	}
}&lt;/pre&gt;


&lt;p&gt;And voila !&lt;/p&gt;</description>
    
    
    
          <comments>http://mirmodynamics.com/post/2006/10/13/Bootstrap-CLI#comment-form</comments>
      <wfw:comment>http://mirmodynamics.com/post/2006/10/13/Bootstrap-CLI#comment-form</wfw:comment>
      <wfw:commentRss>http://mirmodynamics.com/feed/atom/comments/666</wfw:commentRss>
      </item>
    
  <item>
    <title>Aller plus loin avec Zend_Db_Table</title>
    <link>http://mirmodynamics.com/post/2006/09/07/Aller-plus-loin-avec-Zend_Db_Table</link>
    <guid isPermaLink="false">urn:md5:5e84c6163b25cc97ff6364ba37cdf72a</guid>
    <pubDate>Thu, 07 Sep 2006 23:25:00 +0200</pubDate>
    <dc:creator>Geoffrey</dc:creator>
        <category>Coding</category>
        <category>base de données</category><category>surclassage</category><category>zend framework</category>    
    <description>&lt;p&gt;Nous avons vu précédemment les &lt;a href=&quot;http://fashion.hosmoz.net/post/2006/08/30/Acces-a-la-base-de-donnees%3A-Zend_Db&quot;&gt;bases de l'utilisation du composant Zend_Db&lt;/a&gt;, qui nous permet de manipuler les tables via les actions de base &lt;acronym title=&quot;Create Read Update Delete&quot;&gt;CRUD&lt;/acronym&gt;. Malheureusement, dans la plupart des cas, les outils fournis ne suffisent pas, et le besoin de pouvoir gérer les tables de données d'une manière plus fine et surtout plus spécifique se fait sentir. C'est là qu'entre en jeu le surclassage.&lt;/p&gt;    &lt;p&gt;En effet, comme nous l'avons vu la dernière fois, utiliser &lt;code&gt;Zend_Db_Table&lt;/code&gt; se résumé, pour débuter, à un simple surclassage:&lt;/p&gt;


&lt;pre&gt;class Members extends Zend_Db_Table {

}&lt;/pre&gt;


&lt;p&gt;Cette méthode laisse le champs libre à la création de méthodes spécifiques à chaque table. Nous pouvons par exemple vouloir remplir des champs automatiquement à chaque insertion ou mise à jour, par exemple des champs &lt;code&gt;created_on&lt;/code&gt; et/ou &lt;code&gt;updated_on&lt;/code&gt;:&lt;/p&gt;


&lt;pre&gt;class Members extends Zend_Db_Table {
	public function insert(&amp;amp;$data) {
		if (!isset($data['created_on'])) {
			$data['created_on'] = date('Y-m-d H:i:s');
		}
		return parent::insert($data);
	}

	public function update(&amp;amp;$data, $where) {
		if (!isset($data['updated_on'])) {
			$data['updated_on'] = date('Y-m-d H:i:s');
		}
		return parent::update($data, $where);
	}
}&lt;/pre&gt;


&lt;p&gt;&lt;em&gt;Note&lt;/em&gt;: Dans cet exemple, vous pouvez constater que la variable &lt;code&gt;$data&lt;/code&gt; de la méthode &lt;code&gt;update&lt;/code&gt; est passée par référence. C'est tout simplement pour respecter la définition originelle des méthodes, ce qui est requis pour passer le niveau d'erreur &lt;code&gt;E_STRICT&lt;/code&gt;.&lt;/p&gt;


&lt;p&gt;Nous pouvons également redéfinir le comportement d'une action:&lt;/p&gt;


&lt;pre&gt;class Members extends Zend_Db_Table {
	public function delete($where) {
 		$data = array(
 			'status' =&amp;gt; 0,
 		);
		return $this-&amp;gt;update($data, $where);
	}
}&lt;/pre&gt;


&lt;p&gt;Il est aussi possible de définir nos propres méthodes de recherche ou d'écriture:&lt;/p&gt;


&lt;pre&gt;class Members extends Zend_Db_Table {
	public function findByMail($mail) {
		$where = $this-&amp;gt;_quoteInto('mail = ?', $mail);
		return $this-&amp;gt;fetchRow($where);
	}
	
	public function getByZipcode($zipcode) {
		$where = $this-&amp;gt;_quoteInto('zipcode = ?', $zipcode);
		return $this-&amp;gt;fetchAll($where);
	}
	
	function updateById(&amp;amp;$data, $id) {
		$where = $this-&amp;gt;_quoteInto('id = ?', $id);
		return $this-&amp;gt;update($data, $where);
	}
	
	private function _quoteInto($mask, $value) {
		return $this-&amp;gt;getAdapter()-&amp;gt;quoteInto($mask, $value);
	}
}&lt;/pre&gt;


&lt;p&gt;On notera ici la création également d'une méthode privée qui n'est qu'un raccourci pour protéger les clauses &lt;code&gt;WHERE&lt;/code&gt; contre les injections &lt;acronym&gt;SQL&lt;/acronym&gt;.&lt;/p&gt;</description>
    
    
    
          <comments>http://mirmodynamics.com/post/2006/09/07/Aller-plus-loin-avec-Zend_Db_Table#comment-form</comments>
      <wfw:comment>http://mirmodynamics.com/post/2006/09/07/Aller-plus-loin-avec-Zend_Db_Table#comment-form</wfw:comment>
      <wfw:commentRss>http://mirmodynamics.com/feed/atom/comments/595</wfw:commentRss>
      </item>
    
</channel>
</rss>