Pomme, poire & electro

Aller au contenu | Aller au menu | Aller à la recherche

jeudi, juin 4 2009

Opera 10 au secours des internautes par satellite

Je viens d'installer Opera 10 beta sur les conseils de Stef, toujours à l'affût... Et je dois dire que c'est le navigateur de la situation.

En plus d'être un bon navigateur, celui-ci propose une nouvelle fonctionnalité : le mode "turbo" qui est censé accélérer le chargement des pages sur les connexions lentes.

Comme certains le savent, je suis connecté à internet par satellite depuis 4 ans maintenant, et si on dispose d'une bande passante de l'ordre des 2Mbps, le ping de 600ms minimum rend le surf lent et désagréable, quand on sait le nombre d'éléments externes chargés sur une simple page web, et que pour chacun d'entre eux, le navigateur envoie une requête au serveur. Le mode turbo d'opera 10 est réellement efficace dans ma situation. Si vous êtes vous aussi sur satellite, je vous conseille de l'essayer, ça ne mange pas de pain. Je ne saurais dire les mécanismes qui sont utilisés par cette technologie. L'un d'entre eux consiste en tout cas à charger les images en format basse qualité, mais ça n'est certainement pas le seul vu le résultat.

EDIT : Un petit coup de little snitch pour voir ce qui se passe. Une fois le mode turbo enclenché, le seul domain requêté est opera10beta-turbo.opera-mini.net. Il est fort probable que leur serveur fasse office de "proxy" et envoie un seul fichier compressé incluant tous les éléments de la page demandée. Reste à voir si leur serveur sera assez musclé pour assurer une qualité dans la durée...

vendredi, avril 3 2009

Calcul de distances routières avec GDirections côté serveur

L'API GoogleMaps avec son GDirections permet d'obtenir l'itinéraire routier d'un point A à un point B, dans les pays supportés.

Malheureusement ce service n'est officiellement proposé qu'en version javascript, donc pas moyen de l'exploiter sur votre serveur.

Ceci dit il est possible de biaiser la chose facilement et assez proprement (relativement à mon sale hack pour leur service de traductions).

Il est en effet possible d'obtenir de l'information au format JSON à partir d'une URL de la forme : http://maps.google.com/maps/nav?q=from:%20paulinet,france%20to:%20toulouse,france&output=js&hl=fr

Il ne reste plus qu'à décoder le résultat avec json_decode() et extraire l'information de distance.

Je n'ai pas encore testé mais ça va venir très bientôt.

mercredi, avril 1 2009

Modifier un log dans un dépôt subversion + trac

Pour mémoire, je me le note ici (ça peut servir à d'autres aussi) : En cas d'erreur dans le log d'un commit, on peut le modifier en activant le hook pre-revprop-change. Pour ce faire il faut suivre les instructions trouvées sur un blog quelconque (c'est pas parce que j'ai pas envie de citer la source, c'est que c'est le vrai nom du blog !).

Pour mon cas, je ne sais pas s'il s'agit d'une spécificité de mon bash de svn (1.5.1) ou de la distrib (je suis sur une Debian 5) une petite variante a été nécessaire : D'abord renommer pre-revprop-change.tmpl en pre-revprop-change (et non pre-revprop-change.sh)

Ensuite si le dépôt est relié à un Trac il faut resynchroniser manuellement la base de Trac (il faut être loggué en root ou au moins en tant qu'apache) :

trac-admin /path/to/trac/project resync

Et voilà.

lundi, mars 30 2009

Mais qu'arrive-t-il à Aral Balkan ???

Beaucoup d'entre vous doivent le connaitre pour son exploration des confins d'actionscript et sa participation aux outils open-source basés sur la technologie SWF, son opiniatreté à faire tourner Google App Engine ou ses nombreuses conférences ou formations autour des mêmes thèmes. Aujourd'hui, une société manifestement sans vergogne, après lui avoir subtilisé son contenu, son identité, tout ça pour renflouer une base de contenu qui prétend vouloir remplacer une bonne partie de la presse papier et même de wikipedia... Le traine dans la boue de façon mesquine (en turc sur un site anglophone), allant même jusqu'à la traiter d'assassin !

Voilà, Je suis petit bloggueur donc moins avisé surement que les blogueurs quotidiens qui le sont moins - en théorie - que les journalistes. Seulement la lecture de ses trois billets, sachant que je suis son blog depuis au moins deux ans, ne peut que me faire prendre parti directement. Je ne vois pas pourquoi Aral irait s'amuser à faire du lobbying d'une façon aussi vulgaire après tant d'écriture qui reflète aussi bien ses compétences que ses qualités humaines.

EDIT : les commentaires sur ses billets ne font que confirmer les pratiques douteuses de la société en question, puisqu'Aral semble être loin d'être la seule victime.



Donc affaire à suivre de très très près, et si vous avez un compte Digg allez faire buzzer la chose cette histoire sent vraiment pas bon...

mardi, février 10 2009

Besoin d'aide/collaboration

Y'a-t'y des gens qui font du développement web sur toulouse, et qui seraient intéressés pour deux choses :

  • d'une part participer à la maintenance d'un projet commercial (et donc rémunéré)
  • et d'autre part me donner un coup de main sur un framework à licencier en open source et sur lequel le projet tourne. Le framework fait largement appel à plusieurs briques pear (DB_DataObject_Formbuilder_Frontend et dépendances)... Dans l'idée de rendre ce travail public et communautaire par la suite ?

Faites signe si ça vous intéresse d'en savoir plus...

jeudi, novembre 27 2008

Vive la république, vive la France

Is it only me, or did you also notice that writing blog posts in english instead of french dramatically reduces the probability of trolling ?

lundi, mars 19 2007

MACOS 10.4.9 a cassé votre ordinateur ? pas de panique !

Quelle honte ! Vous êtes en train de vous échiner à chercher une solution sur le web depuis le pc de votre coloc, qui lui jubile face à toute ces années où vous avez fait le beau à chaque fois qu'il faisait une réinstall de windows XP. Votre mac est bloqué, ce qui s'appelle bloqué. Impossible de booter depuis cette satanée mise à jour 10.4.9, pas même en mode single user, pas même depuis un lecteur externe, la cata quoi !

ça faisait un moment qu'apple n'en avait pas fait une aussi belle. Mais rappelez-vous la 10.3.1 qui détruisait les disques firewire et leur contenu, la mise à jour itunes qui faisait disparaitre la bibliothèque !

J'étais jusqu'à maintenant passé entre les gouttes, mais cette fois-ci je me suis fait bien peur, j'en ai même travaillé le dimanche (dire à mes clients le lundi "désolé mon ordi est en rade", ces clients à qui je clame furieusement qu'il faut du mac pour travailler, aurait fait beaucoup de mal à mon ego).

Mais voilà, victoire, aujourd'hui la bête se porte comme un charme, et voici comment faire :

  • Rendez-vous avec votre machine chez le voisin du premier qui, oh bonheur, possède un macintel.
  • Téléchargez sur le site d'apple la mise à jour 10.4.9 combo sur le macintel du voisin
  • Branchez-y votre machine en mode target (T au démarrage) et installez la mise à jour combo.
  • Ejectez, redémarrez, souriez

Enfin je ne saurais que trop vous recommander d'installer et utiliser régulièrement applejack qui permet de nettoyer les caches, les disques et réparer les autorisations en mode singluser (pomme-S au démarrage). C'est notamment un outil à utiliser avant et après chaque mise à jour Apple.

lundi, janvier 8 2007

DB_DataObject / MDB2 et la casse dans le nom des champs

J'ai été confronté à un problème qui je crois n'est pas documenté dans la doc de DB_DataObject. En effet je me suis retrouvé avec une base de données MySQL dans laquelle les noms des champs étaient en camelCase. En faisant tourner DB_DataObject sur DB, celà ne pose aucun problème.

Il n'en est pas de même pour MDB2. En effet ce dernier pour des soucis de portabilité n'utilise que des champs en minuscule. Sans en modifier la configuration le remplissage de l'objet DB_DataObject ne se fait donc pas pour les champs contenant des majuscules. Heureusement DB_DataObject permet de modifier de façon globale la configuration de MDB2, grâce à la méthode PEAR::getStaticProperty, comme ceci :

// Configuration de DB_DataObject. Attention a bien recuperer une reference et pas une copie du tableau renvoye par 
// PEAR::getStaticProperty
 
$options = & PEAR :: getStaticProperty('DB_DataObject', 'options');
$options = array ('database' => 'mysql://'.$cfg['db']['user'].':'.$cfg['db']['password'].'@'.$cfg['db']['host'].'/'.$cfg['db']['db'], 
'generator_no_ini'=>true,
'schema_location' => APP_ROOT.'helpers/includes/DOclasses/', 
'class_location' => APP_ROOT.'helpers/includes/DOclasses/', 
'require_prefix' => 'DataObjects/', 
'class_prefix' => 'DataObjects_', 
'db_driver'=>'MDB2'
);
// Configuration de MDB2. Cette facon de configurer MDB2 est propre à DB_DataObject 
require_once ("MDB2.php");// Pour initialiser les constantes MDB2_PORTABILITY_*
$db_options = & PEAR::getStaticProperty('MDB2','options');
$db_options['portability']=MDB2_PORTABILITY_ALL ^ MDB2_PORTABILITY_FIX_CASE;// Tout sauf passage en minuscule pour
                                                                                        // les noms des champs

Voilà, si vous rencontrez d'autres problèmes vous pouvez jeter un oeil aux différentes constantes concernant la portabilité dans /repertoire/pear/MDB2.php

lundi, décembre 11 2006

rendre DB_DataObject / MDB2 traversable

Voici une extension de DB_DataObject qui implémente l'interface Iterator.

Très pratique pour utiliser avec des moteurs de templates, qui possèdent quasiment tous leur "foreach".

<?php
 
class DB_DataObject_Iterator extends DB_DataObject implements Iterator {
    public function current() {
        return $this;
    }
    public function key() {
        global $_DB_DATAOBJECT;
        $result = &$_DB_DATAOBJECT['RESULTS'][$this->_DB_resultid];
        return $result->rowCount();
    }
    public function next() {
        $this->fetch();
    }
    public function rewind() {
        global $_DB_DATAOBJECT;
        $result = &$_DB_DATAOBJECT['RESULTS'][$this->_DB_resultid];
        if(!$result) return false;
        $result->seek();
        return $this->fetch();
    }
    public function valid() {
        global $_DB_DATAOBJECT;
        if (empty($_DB_DATAOBJECT['RESULTS'][$this->_DB_resultid]) || 
            !is_object($result = &$_DB_DATAOBJECT['RESULTS'][$this->_DB_resultid])) 
        {
            return false;
        }
        return true;
    }
}

Ne fonctionne qu'avec MDB2 (doit pouvoir être adapté à DB) et bien sûr nécessite PHP5, l'interface Iterator faisant partie des SPL.

vendredi, novembre 24 2006

traduction automatique, pas d'API, tant pis !

Je suis parti en quête d'une API publique pour proposer des champs multilingue avec traduction auto dans les backoffice que je développe. Après plusieurs messages sur plusieurs forums, il semble ne pas en exister. C'est assez étonnant car quand on voit les services que propose google notamment pour la carto on pourrait se dire que ce ne serait pas la mer à boire pour eux de proposer ça.

Je me suis donc fait un "extracteur de traductions" qui va chercher les infos dans le HTML. En espérant que les sites qui proposent ce service ne fermeront pas leur porte à ce genre de script, je vous en fais tout de même part. Si vous vous sentez le coeur de l'améliorer, faites-m'en part j'en serais ravi, et aussi si vous écrivez des drivers (pour le moment google et altavista) aussi.

Désolé pour la documentation absente mais cet extracteur est somme toute assez basique.

Dépendances : PEAR::HTTP_Request et prototype.js

A télécharger ici

dimanche, octobre 8 2006

xdebug, macosX.4 et MAMP 1.3.1

Vous avez monté une application web que vous utilisez régulièrement, et vous souhaitez rechercher un moyen de l'optimiser, ou vous avez besoin d'un outil de profiling dans le cadre de votre développement PHP ? Vous êtes sur mac osX, vous utilisez MAMP (1.3.1). Moi aussi !!

Je me suis donc décidé à voir ce que donne xdebug qui semble être l'outil incontournable pour accomplir cette tâche. J'ai rencontré quelques obstacles pour arriver à mes fins, qui justifient je pense l'écriture de ce billet.

Installer xdebug

Il n'existe pas de version précompilée de Xdebug pour mac, qui plus est la compilation dépend de la version du moteur Zend utilisé dans votre environnement. Donc, une compilation est nécessaire. Le problème avec MAMP, c'est que les librairies C en sont absentes, ce qui rend toute compilation de module PHP impossible.

Il faut donc, dans un premier temps, récupérer une distribution de php avec le même moteur Zend que la version de MAMP incluant les librairies (à savoir 20050922). Tout ça uniquement pour compiler le module...

Le package d'entropy étant passé en php 5.2, je me suis rabattu sur une autre solution (plus simple, voir note de bas de page)

Pour ce faire j'ai opté pour le package php de Marc Liyanage (ceux qui sont sur osX depuis le début doivent connaitre car il a été le premier à proposer des packages d'installation apache/php/mysql pour osX, qui soient à la portée d'un développeur web de base comme moi).

Le package php 5.1.6 se trouve ici. Récupérez-le, installez-le (c'est un .pkg). Toute l'installation est placée dans le dossier /usr/local/php5/. La version PHP de MAMP est 5.1.4, mais le moteur Zend est le même,c'est ce qui compte.

Cette fois on a les librairies C (dans le dossier include).

Allons nous placer dans une fenêtre terminal.

A savoir, le module php de marc liyanage a effectué une installation des binaires en root/wheel. Alors ceux de MAMP vous appartiennent. Il va donc falloir compiler le module en tant que root.

Pour ce faire, et comme je suis un partisan du moindre effort (il faut déjà en faire assez) nous allons utiliser le gestionnaire de packages PECL (celui du package PHP de Marc Liyanage, pas celui de MAMP !). comme ceci :

macbookpro:~/ moi$ sudo /usr/local/php5/bin/pecl install xdebug

après quelques dizaines de secondes, le téléchargement des source et la compilation sont effectués. le nouveau module a été copié dans /usr/local/php5/lib/php/extensions/no-debug-non-zts-20050922 . Il va falloir, d'une part basculer les droits pour coller avec ceux de MAMP, puis déplacer le module dans le dossier des extensions Zend de MAMP :

sudo chown moi /usr/local/php5/lib/php/extensions/no-debug-non-zts-20050922/xdebug.so
sudo chgrp admin /usr/local/php5/lib/php/extensions/no-debug-non-zts-20050922/xdebug.so
cp /usr/local/php5/lib/php/extensions/no-debug-non-zts-20050922/xdebug.so /Applications/MAMP/bin/php5/lib/php/extensions/no-debug-non-zts-20050922/xdebug.so

Ne reste plus qu'à ajouter une ligne à notre php.ini :

echo zend_extension=/Applications/MAMP/bin/php5/lib/php/extensions/no-debug-non-zts-20050922/xdebug.so >> /Applications/MAMP/conf/php5/php.ini

Et redémarrer les serveurs depuis l'interface MAMP. Il ne vous reste plus qu'à vérifier que le module est bien chargé, en allant consulter le phpinfo(); (si vous lisez cet article, vous savez faire, non ?...)

Premières utilisations

On peut déjà utiliser Xdebug directement dans notre code PHP. Le module xdebug.so ajoute quelques fonctions PHP (consultez la liste complète dans la documentation de xdebug). Premier exemple de base, remplacer le gestionnaire d'erreurs de PHP par celui de Xdebug :

<?php
xdebug_enable();
fonction_a_la_con_qu_existe_pas();
?>

Allez voir ce que ça donne :

Wowo que c 'est bô !!! L'intérêt semble limité pour un simple appel de fonction, mais la pile de traçage devient vite très intéressante lorsque l'on se retrouve à gérer des erreurs dans une imbrication multiple d'objets.

Je vous invite, à partir de ce point, à explorer les différentes fonctions xdebug, dans la doc correspondant (voir lien plus haut). Attention la version 1.3 et la version 2 (celle qu'on a installé) fonctionnent tout à fait différemment.

En tout cas, le top avec xdebug, c'est d'utiliser une interface graphique pour profiler son application. Comme souvent sur mac, on est à la traine et il faut jouer des coudes pour trouver ce dont on a besoin. Heureusement que cet OS est le plus agréable du monde, ça fait oublier ces petits désagréments ;). Heureusement il y a Fink grâce auquel nous allons pouvoir installer Kcachegrind....

Installation de Kcachegrind

bas débit s'abstenir !

Pour installer Kcachegrind sur mac osX, il faut également récupérer un paquet de paquets liés à l'environnement graphique KDE. La solution la plus simple pour ne pas s'empêtrer dans les dépendances, est de laisser faire Fink. Il saura installer tout ce dont on aura besoin pour faire tourner la bête. Mais avant d'installer Fink, assure-vous d'avoir installé :

  • Les Developer Tools (Fink a besoin de gcc entre autres)
  • X11 (KDE tourne sur un moteur de ce type)

Ensuite, récupérez l'installeur de fink ici. L'installation se fait classiquement par un .pkg. L'installeur crée un répertoire sw en racine de votre disque système, tout ce que fink installera, ce sera dans ce dossier. Si vous êtes habitué à apt-get, pear, pecl ou dselect, sachez que fink est un gestionnaire de packages au fonctionnement similaire à ceux-ci, mais il est spécialisé dans le port d'application unix sur mac. Dans le même genre il existe Darwinports. Je n'ai pas testé, mais je pense que si les packages KDE sont dispo sur darwinports on doit arriver au même résultat.

Passons au rapatriement de kacachegrind et toute la cohorte de packages (140 pour moi) nécessaires à son bon fonctionnement. Je n'ai pas compté mais on doit pas être loin du gigaoctet, donc faites chauffer les modems ! D'abord, il faut configurer, et tant qu'à faire, mettre à jour Fink. Kcachegrind n'étant disponible qu'en statut beta, il faut indiquer dans la config que l'on souhaite pouvoir utiliser des packages en beta.

Retour dans le terminal :

vi /sw/etc/fink.conf

Et effectuez la modification suivante :

# Avant
Trees: local/main stable/main stable/crypto
# Après
Trees: local/main stable/main stable/crypto unstable/crypto unstable/main

voilà maintenant mise à jour de Fink et réindexation des packages :

fink selfupdate; fink index; fink scanpackages

Allez boire un café.... ... ... voilà, la journée doit être pas loin de se terminer pour lancer ce qui suit, téléchargement et compilation qui vont prendre... du temps :

sudo fink install kcachegrind

Répondez tout de même aux quelques questions (laissez les valeurs par défaut par exemple, ça suffit) pour que l'opération démarre. .... .... Le lendemain matin... Je vous souhaite de tout coeur qu'aucune erreur n'apparaisse dans votre terminal, en principe tout a bien du se passer, kcachegrind est prêt à être lancé. Il se trouve dans /sw/bin/kcachegrind.

Pour qu'il fonctionne correctement, il doit être lancé depuis X11, par le terminal. Vous pouvez ajouter le chemin de l'exécutable au menu Applications, c'est fait pour ça.

Vous devez obtenir quelque chose comme ça :

Vous savez quoi : on y est presque ! Ne reste plus qu'à configurer xdebug (on retourne dans le php.ini s'il vous plait)

xdebug.profiler_enable="1"
xdebug.profiler_output_dir="/Applications/MAMP/tmp/xdebug/"

Les valeur "xdebug.trace_output_dir" et "xdebug.profiler_output_dir" sont modifiables par l'emplacement où vous souhaiter enregistrer les fichiers de profiling.

Relancez le serveur apache

Lancez une page web PHP de votre serveur local, un fichier de profiling est créé à l'endroit que vous souhaitez. Il ne vous reste plus qu'à ouvrir ce fichier (extension .out) dans kcachegrind. Excellent ! Ci-dessous un profil d'un des sites que j'ai monté. Le retour visuel est immédiat et sans appel : mon système d'internationalisation, utilisant PEAR::XML_Serializer, a sérieusement besoin d'un système de cache :

Amusez-vous bien, n'hésitez pas à émettre remarques ou suggestions sur ce billet.


Voici la liste des articles écrits ça et là, qui m'ont aidé à monter cet environnement.

EDIT : si vous êtes sur php 5.2 un brave ch'ti gars de chez Komodo propose les binaires pour Linux/macosX/Win32 par ici :

PHP 5.2 / xdebug builds

EDIT2 : souhaitant installer PHPunit 3, qui demande xDebug version 2, je me suis retrouvé coincé (après un changement de machine) car le package d'entropy est passé en php 5.2, et toujours pas MAMP (ben ouais j'ai pas upgradé). Donc là, le seul moeyn reste l'extension compilée de komodo. Elle est récupérable directement dans l'application elle-même.

mardi, octobre 3 2006

Enhancing/Extending PEAR::DB_DataObject_FormBuilder

For the ones that use DB_DataObject_FormBuilder, it's clear that this extension easily becomes one of the "must-have" in any project that need form and database. It may have some disadvantages, for example concerning the display of a select with linked values. In Symfony and Propel, and in other Frameworsk certainly, the many ones I don't know, you can implement the __toString() method, which since php5 (AFAIK) is the default method called when you try to echo and object. It's much more flexible than $fb_linkDisplayFields which show the field values separated with a coma. This can be fastly frustrating.

You can think I'm a dumb sometimes, but I took much time for me to figure out how to extend FormBuilder. Finally I found. In fact many things in OOP, (me) seem (to me) inaccessible from the first place, because the solution is sooo simple that you can turn around without seeing it. So, here it is :

require_once 'DB/DataObject/FormBuilder.php';
 
class myFB extends DB_DataObject_FormBuilder
{
  
  function DB_DataObject_FormBuilder(&$do, $options = false)
  {
    DB_DataObject_FormBuilder::DB_DataObject_FormBuilder(&$do, $options = false);
  }
  
  function &create(&$do, $options = false, $driver = 'QuickForm', $mainClass = 'myFB')
  {
 
    $fb = DB_DataObject_FormBuilder::create($do,$options,$driver,$mainClass);
 
    if(PEAR::isError($fb)) {
      die ($fb->getMessage());
    }
    return $fb;
  }
  
  function getDataObjectString(&$do, $displayFields = false, $linkDisplayLevel = null, $level = 1) {
    if($this->isCallableAndExists(array($do,'__toString'))) {
      return $do->__toString();
    } else {
      return parent::getDataObjectString($do, $displayFields, $linkDisplayLevel, $level);
    }
  }
}

Voilà, I just had to overload the create method, to have an extensible FormBuilder. Here I just add the ability tu use __toString() on the linked object, if it's implemented.

Obviously to make a new form, you have to use MyFB::create($dataobj); instead of DB_DataObject_FormBuilder::create($dataobj);

jeudi, septembre 21 2006

Suppression récursive en ligne de commande

J'ai pris la sale habitude de travailler sur certains projets que j'héberge pendant la période de développement, direct sur le serveur (local), en AFP. Je ne sais pas si c'est textmate ou l'AFP ou les deux, en tout cas cette méthode de travail de barbare (plutôt que de faire des commit sur mon SVN, ce qui serait tout de même plus sérieux) a foutu le bordel (enregistrement des deux fourchettes de fichier en deux fichiers, dont un commençant par '._').

Donc au bout de quelques temps je me dis "Tiens, je vais tout de même faire un petit commit, et on va essayer de repartir ans le droit chemin". Oui mais voilà, svn status me sort une liste grande comme le bras (et c'est peu dire) avec tous ces nouveaux fichiers. Le bordel quoi ! Heureusement mon pote Pascal qui assure bien en ligne de commande m'aiguille sur une méthode pour supprimer d'un coup d'un seul tous ces fichiers '._' de mon arborescence. Voilà ce que ça dit :

find ./ -name "._*" | xargs rm -R -v

Sympat non ?

EDIT : dans la série des petites bricoles qui facilitent la vie, Pascal m'a fait passer une page bourrée de scripts monolignes en perl, c'est assez puissant - Ecrire un programme d'une ligne en Perl

jeudi, juin 1 2006

Supprimer un projet dans un dépôt subversion

Je me suis monté un serveur subversion (avec apache) sur lequel je dépose mes projets. Celà permet notamment de travailler avec deux machines, une portable et une sédentaire, sans risque de s'auto-téléscoper.

Il m'est arrivé de déposer des projets, sans avoir trop regardé ce qu'il y avait dedans, et en fait il y avait plein de merdier... Dans ces coups de temps-là, lorsqu'il s'agit de l'import de départ, il serait préférable de supprimer le projet et de l'importer à nouveau. Le doc de subversion ne parle pas de ce genre de fonctionnalité, mais finalement, on peut le faire avec la commande delete :

svn delete -m "suppression du projet mon_projet" http://serveur/svn/mon_projet

J'espère que ça sera d'une utilité à certains. Evidemment on peut toujours récupérer l'ancien projet en récupérant la révision précédente. Donc ce n'est pas une suppression sécurisée.

mercredi, mai 31 2006

Les costauds de St-Agil

Finalement, je ne me suis pas reposé d'Auzits. Le grand week-end nous tendant les bras, nous sommes partis en famille à St-Agil, quelque part entre Tours et Chartres, dans le Perche. le mât

le mât

Ambiance champêtre au possible, une fois encore. Cette fois-ci c'était pour vivre le festival cirque et fanfare du cheptel aleïkoum, une troupe d'acrobates/musiciens résidant dans le village. Le moins qu'on puisse dire c'est que ces deux disciplines vont bien ensemble, et leur collent à la peau. les poilus Remarquables d'énergie, les Poilus, la fanfare locale née de l'engouement amené par ces nouveaux arrivants, tout en fun et trompette.

A conseiller pour l'année prochaine !

jeudi, février 2 2006

Une banque photo haute résolution

Voilà encore un lien intéressant que Franto, le surfer / collectionneur fou, vient de dénicher.

http://www.morguefile.com/

Je n'ai pas tout lu, mais d'après les quelques infos que j'ai lu, il s'agit d'un dépôt de photos "ratées" (ben dis donc heureusement qu'ils voient pas mes photos réussies ceux-là) que les agences ou photographes mettent à disposition. Libre de droit donc apparemment (faut lire un peu plus la licence mais ça a l'air ça), et très haute résolution. Ouh làlà que de réserve de ma part mazette !

mardi, janvier 24 2006

Smarty and DB_DataObject, yet more integration

Ok, let's try some english now, at least for topics related to pear. (well not too hard, only 3 lines of literatture and many others of code) ;)

I've written a tiny plugin for using a DB_DataObject inside a Smart template. It's a block plugin that implements the DB_DataObject::fetch() method and behaves as the foreach block, except that it does not handle the foreachelse equivalent yet. More to come ....

<?php
function block_dataObject($params,$string,&$smarty,&$repeat){
	if(!key_exists('from',$params)){
		$smarty->trigger_error('No from attribute declared for dataobject tag');
	}
	$do=&$params['from'];
	if(!is_subclass_of($do,'DB_DataObject')){
		$smarty->trigger_error('Object of type '.get_class($do).' passed to dataobject tag is not a dataObject');
	}
	$repeat=$do->fetch();
	return $string;
}
?>

You must register this plugin in smarty as a block :

<?php
	$aSmarty->register_block("dataObject","block_dataObject");
?>

And use it like this :

<?php
require_once 'DB_DataObject.php';
 
$users=& DB_DataObject::factory('users');
$users->find();
$aSmarty->assign_by_ref('userlist',$users);
?>

In the template file :

<dl>
{dataObject from=$userlist}
    <dt>{$userlist->name}</dt>
    <dd>{$userlist->phone}</dd>
    <dd>{$userlist->email}</dd>
{/dataObject}
</dl>

samedi, janvier 14 2006

Haut débit à la maison !!!!!!

Pour les gens de la ville ça n'a l'air de rien, mais pour moi, reclu dans ma campagne profonde, c'est une révolution !

En effet voilà une semaine que j'ai pris une connexion internet par satellite chez sat2way. En plus d'être fort sympathique cette société utilise un parc informatique entièrement composé de mac ce qui ne gâche rien.

Fini les "t'es déconnecté ?" ou "t'as écouté les messages ?". Fini les hotline en différé, Fini les heures à rappeler tout ceux qui ne peuvent pas me joindre.
Et le débit ! Aaaaah le débit !

mardi, décembre 6 2005

froz3n TV

Mon pote Mr Freeze version haut en couleurs !

froz3n TV

vendredi, décembre 2 2005

Smartyfying PEAR

cet article est disponible en français ici

EDIT : The new Structures_DataGrid release is available (0.7.1) and bring many enhancements to renderers and datasources. I have not tried it yet ('cause of I'm into symfony for the moment) but before trying the Structures_DataGrid_Renderer_Array solution I advise you to test it

Her I am ! I've just started my fourth project using pear and smarty. In the beginning it was quite painfull, as it's the first time I'm trying not to reinvent the wheel, but now I can feel the benefits (looking forward to strarting the next project!).
The PEAR_DB PEAR_DB_DataObject, PEAR_DB_DataObject_FormBuilder PEAR_HTML_QuickForm_Controller et PEAR_Structures_DataGrid quintet really offers a powerful framework that can handle a big part of most database driven projects, in a simple and elegant way, once you know how to set it up.

The thing that seemed the most tricky to me was finding documentation to make all this beautiful engine to work with smarty. That's why I want to give you come advice now, or at least let you know about my work in this way.
I'm not an OOP geek, so don't hope to find some best preactises in this post, some things could certainly be improved. Anyway, don't hesitate to leave a comment, I am ready for the rudest ones (but spam obviously).

From the 5 packages I'm talking about, 3 of them have as a goal to make HTML renderable objects (well, Structures_DataGRid can do more, but that's not the purpose of this post) : PEAR_DB_DataObject_FormBuilder, PEAR_HTML_QuickForm_Controller and PEAR_Structures_DataGrid.

Smartyfying PEAR_DB_DataObject_FormBuilder

This package is a sort of "bridge" between DB_DataObject and HTML_QuickForm. More precisely, from a DB_DataObject instance, he can generate an HTML_QuickForm object. This one will go thru smarty then. You will find all the useful information about all the various options for DB_DataObject_FormBuilder in its documentation. Once you have set up the DB_DataObject including more options for form generating with DBDOFB, this is how the form is created :

<?php
require_once 'DB/DataObject.php';
require_once 'DB/DataObject/FormBuilder.php';
 
$dbdo=& DB_DataObject::factory('mytable');
$form=& DB_DataObject_formBuilder::create($dbdo); // here is the instance of HTML_QuickForm
?>


From here, I won't talk too much, because you can easily find some examples to render HTML_QuickForm's to smarty , this one uses a dynamic rendering method with this template, this one uses a static rendering method with this template. The first one is really interesting, because you can use it for any HTML_QuickForm object, while the other one has to be linked with each form element. But if you need a special layout for a special form, this is the one.
Another interesting link, a slideshow presenting HTML_QuickForm and smarty by David Mintz where a third method is proposed (not recommended, says the authir himself).

smartyfynig PEAR_HTML_QuickForm_Controller

HTML_QuickForm_Controller being a package the works with HTML_QuickFrom, we're back to smartyfying HTML_QuickForm. I invite you to read HTML_QuickForm_Controller documentation to understand where and how you handle form rendering in this package. We're doing it in an HTML_QuickForm_Action_Display subclass instance. For example :

class ActionDisplay extends HTML_QuickForm_Action_Display
{
    function _renderForm(&$page) 
    {
    	
   	$renderer =& new HTML_QuickForm_Renderer_Array(true, true);
	$page->accept($renderer);		
       global $smarty;
       $smarty->assign("form",$renderer->toArray());
 
    }
}

smartyfying Structures_DataGrid

Like HTML_QuickForm, while it's not only devoted to HTML, Structures_dataGrid uses renderers.
Before going further, I suggest you go read Olivier Guilyardi's tutorial. He is one of the maintainers of this package.
As Structures_DataGrid is currently being rewritten from the ground (as I heard), what follows might be obsolete when the next release of SDG is out. Meanwhile it offers a way to use Datagrid and Smarty, to show paginated record set in a snap .
If you checked at the Structures_Datagrid source tree, you will see a Smarty renderer. But IMHO, it has the big disadvantage not to handle column formatters. So I started from Structures_DataGrid_Renderer_HTMLTable to make a Structures_DataGrid_Renderer_Array. You can download it here.

This class allows to generate an array including the dataset of course, but also some other useful information for a rendering engine like smarty. Although it may work with dynamic rendering (similar to what's done with QuickForm) I've only used it with static templating. So you can easily have your blog articles in multiple pages, handled by just one object
This is a use example.
As I use smarty for all the Datagrids in my project, I subclass it to handle smarty rendering by default :

<?php
class MyDg extends Structures_DataGrid {
 	function myDg($limit = null, $page = null,$renderer = DATAGRID_RENDER_TABLE){
              parent::Dg($limit,$page,$renderer);
		$this->setRenderer("Array","classes/");// We declare the renderer (recorded as Array.php, in a classes folder that's in my include_path)
 		$this->addColumn(new Structures_DataGrid_Column('detailLink', 'detailLink', null, '', null, 'detailLink()'));
		$this->addColumn(new Structures_DataGrid_Column('photo', 'idphoto', null, '', null, 'mainphoto()'));
		$this->addColumn(new Structures_DataGrid_Column('ref', 'ref', 'ref'));
		$this->addColumn(new Structures_DataGrid_Column('Title', 'title', 'title'));
		$this->addColumn(new Structures_DataGrid_Column('description', 'description', null));
 	}
 }
?>

So when creating a MyDg instance, we use the 'toArray()' method to send the data to smarty :

<?php
$do=& DB_DataObject::factory("mytable");
$sd = & new MyDg(10);
$sd->bind($do);
 
$smarty->assign("tabletoberenderered",$sd->renderer->toArray());
?>

Next, let's create a template file that will loop over the resulting array :

{* smarty *}
<p>Sort by : {$tableau.headers.ref}</p>
{foreach item=sec key=i from=$tableau.Data}
<dl>
<dt>{$sec.title}</dt>
<dd>{html_image file=$sec.idphoto alt=$sec.description}</dd>
<dd>{$sec.description|truncate|30}</dd>
<dd>{$sec.detailLink}</dd>
</dl>
<hr />
{/foreach}

Okay let's not talk abnout semantics here. If you want smarter HTML code just check simplebits discussions about semantics.

Another thing : If you're fedup having to create all your columns just for one on which you want to apply a formatter, the solution is here : Improvements to Stuctures_Datagrid

Conclusion

I won't go further this time, as you notice the SDG array renderer will export the page as plain HTML. If you want more control over this part of the datagrid, I suggest you search in the PEAR mailing-list archive, there was a thread about this, someone presenting a class that would be a nice complement to mine... Sorry about loosing the link. Whenever you have any suggestion don't hesitate to leave a comment I will be happy to answer you.

- page 1 de 2