Alors ça c'est du lourd : Symfony propulse del.icio.us preview.
Il parait que Symfony rame, sauf chez Yahoo!. Poltergheist ? 
Développement PHP, actionScript2, Ruby, XHTML, CSS, javascript, etc.
mardi 2 octobre 2007
Par NiKo le mardi 2 octobre 2007, 23:41
Alors ça c'est du lourd : Symfony propulse del.icio.us preview.
Il parait que Symfony rame, sauf chez Yahoo!. Poltergheist ? 
mercredi 5 septembre 2007
Par NiKo le mercredi 5 septembre 2007, 17:47
QOTD :
À trop procrastiner, on s'y casse le nez.
Bon, je suis en train de sortir des cartons tout ce que je n'ai pas encore releasé. Voici une première fournée, sous la forme de deux plugins pour le framework Symfony :
Ces plugins sont releasés sous licence MIT. Enjoy.
Bon, c'est pas fini, d'autres choses vont suivre très prochainement.
dimanche 19 août 2007
Par NiKo le dimanche 19 août 2007, 13:04
Pour les besoins du boulot, j'ai du me mettre à Flex, le framework d'Adobe orienté RIA en Flash.
Je pensais que mon passé de flasheur m'aiderait à monter rapidement en compétence sur cette techno, ben non : c'est tout à fait autre chose que ce que je connaissais de l'IDE traditionnel, dont je m'étais arrêté à la version 8. Avec Flex on a affaire à un framework complet de génération d'interfaces riches basées sur l'emploi de composants décrits et paramétrés en XML et de la dernière mouture du langage ActionScript en version 3. Quelques exemples d'applications réalisées avec Flex sont disponibles, et pour certaines, ça en jette carrément.
La description des interfaces s'opère au moyen du langage MXML[1], basé sur XML un peu comme ce que proposent XUL ou XAML ou même XHTML (qui reste une implémentation particulière et standardisée d'XML). Deux types principaux de composants sont disponibles : les conteneurs (boîtes, panneaux, fenêtres, etc.) et les éléments de contrôle (champs texte, listes, datagrids, tree, etc.)
Le nombre de conteneurs et de contrôles est impressionnant, on se prend à rêver de la même richesse en HTML [2]. La plupart des composants sont visibles sur l'explorateur de composants Flex, sur le site d'Adobe. Et le meilleur reste sans doute à venir quand on voit le catalogue de composants supplémentaires open source comme ceux du projet FlexLib...
Le format généré après compilation d'un ensemble de fichiers MXML constituant une application Flex est le SWF, le format natif d'Adobe Flash, lisible par tout bon Flash Player 9 qui se respecte, implanté sur plus de 80% du parc machines desktop mondial d'après les dernières statistiques disponibles sur le site d'Adobe.
Voila un exemple de code MXML décrivant l'interface d'une application simpliste :
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <mx:Panel title="Dire bonjour" x="10" y="10" layout="absolute" width="303"> <mx:TextInput id="firstname" x="10" y="10"/> <mx:Button label="Dire bonjour" click="result.text='Bonjour, '+firstname.text" x="178" y="10"/> <mx:Label id="result" x="10" y="40" width="265"/> </mx:Panel> </mx:Application>
Le code est assez parlant, mais voici quelques éléments significatifs :
mx, ce qui nous permettra d'utiliser les composants natifs de FlexPanel contenant trois contrôles :
InputText, champs de saisie textuelleButton, un bouton d'actionLabel, un champs de texte potentiellement dynamiqueid qui doit être unique si renseigné ; il permet de référencer facilement un élément de l'arbre DOMDans l'exemple précédent, on voit que les styles sont appliqués sous forme d'attributs XML. C'est une solution pratique à court terme mais qui peut rapidement s'avérer problématique à maintenir dès que votre application grossit. Aussi, pour séparer la couche de présentation de la description des contenus, tout comme en HTML, Flex permet l'utilisation de feuilles de styles CSS embarquées ou externalisées. Beaucoup de propriétés CSS ont du être créées ou adaptées aux spécificités du balisage MXML et des composants proposés, mais le résultat est une grande souplesse d'utilisation et une large palette de mise en forme disponible. Pour preuve, un petit tour du côté de l'explorateur de styles Flex s'impose.
ActionScript 3 est l'évolution logique des précédentes versions, étendant le périmètre fonctionnel et accentuant son caractère professionnel, notamment dans l'implémentation objet, les types natifs et l'organisation en packages des différents objets de programmation.
Une des grandes forces de Flex à mes yeux est la simplicité avec laquelle on peut créer ses propres composants en héritant de composants basiques préexistants et de les manipuler via son propre espace de noms. Par exemple, la création d'un composant dérivé d'un formulaire présentant un champs de login/mot de passe donne à peu près ceci :
<?xml version="1.0" encoding="utf-8"?> <mx:Form xmlns:mx="http://www.adobe.com/2006/mxml" width="280" height="105"> <mx:FormItem label="Login"> <mx:TextInput id="username"/> </mx:FormItem> <mx:FormItem label="Mot de passe"> <mx:TextInput id="password" displayAsPassword="true"/> </mx:FormItem> <mx:FormItem> <mx:Button label="Connexion"/> </mx:FormItem> </mx:Form>
Si on nomme notre fichier de composant LoginForm.mxml et qu'on le stocke dans le répertoire ./components de notre projet Flex, on va pouvoir l'utiliser de la façon suivante dans une application :
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:niko="components.*" layout="absolute"> <mx:Panel title="Connexion"> <niko:LoginForm id="loginform"/> </mx:Panel> </mx:Application>
On a déclaré un nouvel espace de noms, ici niko (mais on aurait pu mettre ce qu'on veut) pointant vers les fichiers sous le répertoire components du projet. Simple, non ? En tout cas, cela devient un jeu d'enfant de produire des composants réutilisables.
Flex propose trois modes d'accès aux données distantes, par le biais de trois composants :
HTTPService, comme son nom l'indique, permet d'effectuer des requêtes HTTP sur une url et d'en récupérer la réponse. Un objet bien pratique quand on veut s'interfacer avec une architecture REST, par exemple.WebService permet de s'interfacer avec un webservice au format WSDL via SOAP. Quand on dispose de tels service, c'est un plaisir de se baser dessus depuis Flex puisqu'on a qu'à réferencer les méthodes à utiliser et les déclencher depuis leur référence.RemoteObject, implémentation du protocole RPC dans Flex, pendant Flash/ActionScript du RMI en Java. Comme je fais peu de Java, j'ai tendance à plutôt utiliser AMFPHP[3] pour publier mes services en utilisant PHP. Un très bon tuto de mise en oeuvre du couple AMFPHP/Flex se chargera d'illustrer le concept plus efficacement que je ne le fais ici.Adobe propose un IDE dédié à la réalisation d'applications Flex, FlexBuilder. Cet outil, basé sur le célebrissime Eclipse, permet de disposer d'un environnement complet de développement comprenant entre autres un éditeur de code (MXML en mode source/wysiwyg, ActionScript, CSS, etc.), un débogueur avancé à la Java, un gestionnaire de projets, la compilation automatique et surtout un accès à l'immense catalogue des plugins Eclipse. D'ailleurs, FlexBuilder est également disponible sous la forme d'un plugin à installer sur une instance d'Eclipse existante : de quoi travailler sur vos projets Flex/PHP de façon centralisée, par exemple.
Inconvénient majeur de cet outil, il est payant. Et coûte relativement cher, puisque proposé aux alentours de 500€. Néanmoins, le SDK de Flex étant gratuit, vous pouvez tout à fait vous passer de FlexBuilder et compiler vos applications à la main. Une bonne nouvelle ne venant jamais seule, Adobe a décidé de publier la prochaine mouture du framework sous licence libre [4], aussi nous devrions voir fleurir des alternatives à FlexBuilder et assister à un taux d'adoption plus conséquent de la technologie.
Au vu de l'étendue fonctionnelle de Flex et des différents formats de fichiers mis en oeuvre ainsi que de leurs interactions potentielles, il est clair que maintenir la moindre petite application peut vite relever du cauchemar les développements avançant. Pour faire face à cette problématique, Adobe propose un surframework du nom de Cairngorm mettant en oeuvre les bonnes pratiques d'architecture logicielle en implémentant le motif de conception MVC bien connu des utilisateurs de frameworks de développement rapide orientés web.
Même si le projet semble extrêmement intéressant, je n'ai pas encore pour l'heure pu jouer avec.
Pour l'heure et après avoir pas mal galéré tâtonné avec l'outil au début, je dois reconnaître maintenant et avec un peu de recul que c'est assez efficace. C'est relativement déstabilisant pour quelqu'un qui comme moi avait l'habitude de l'IDE Flash Authoring classique, mais au final FlexBuilder semble beaucoup plus sérieux pour tout ce qui concerne la programmation et l'organisation des fichiers (Eclipse oblige.) Même le templating y gagne à mon sens, mais par contre impossible de faire de la création graphique avancée directement dans FlexBuilder, l'outil n'est clairement pas l'ami des infographistes de vocation.
Pour enfoncer le clou, j'ai pu comparer l'utilisation de Flex et de XUL, ayant enchaîné deux projets coup sur coup les mettant en oeuvre. L'excellente documentation de Flex et la richesse des outils gravitant autour de la techno font que pour l'heure Flex me semble l'un des meilleurs choix pour développer une RIA, si l'on écarte le couple HTML/Ajax qui garde une toujours une place de choix dans mon arsenal webdeuzéroesque 
[1] Je ne sais pas à quoi correspond la lettre M de l'acronyme, Macromedia sans doute.
[2] En attendant HTML5, les antiflash pourront aller zieuter du côté d'extjs ou de YUI.
[3] Attention à bien utiliser la dernière version 1.9 beta compatible avec Flex2
[4] Sous licence MPL plus précisément.
vendredi 13 juillet 2007
Par NiKo le vendredi 13 juillet 2007, 11:32
[Via la liste technique de Clever Age]
Ceux qui suivent le développement de PHP6 en scrutant le dépôt CVS ont exulté : la future mouture du langage se voit dotée d'une fonctionnalité très attendue des développeurs : la gestion des espaces de noms (namespaces en anglais.) L'implémentation retenue est celle proposée par Dmitry Stogov.
Mais alors qu'il est encore difficile d'imposer PHP 5 à l'ensemble des hébergeurs et développeurs, combien de temps allons-nous devoir attendre pour déployer des outils utilisant ces alléchantes fonctionnalités de PHP 6 ?
samedi 7 juillet 2007
Par NiKo le samedi 7 juillet 2007, 20:26
Je relaie ici cette chouette initiative d'un groupement de projets open source pour inciter à l'adoption et au déploiement de php5 en lieu et place de l'antique et moins performant php4 : Go PHP 5 !
Php4 nous a rendu de fiers services, mais il est plus que temps de reconnaître que cette version est maintenant largement dépassée et que le maintien de son utilisation ne sert pas l'essor du langage sur des projets de grande envergure... d'autant que la fin du support officiel de php4 est annoncée pour cette année.
Le pire c'est que php6 et ses alléchantes petites révolutions vont arriver l'année prochaine, je sens qu'on est pas sorti de l'auberge :/
Edit : La mort de php4 officiellement annoncée sur php.net. Le vendredi 13 lui a porté malchance ^^
mardi 22 mai 2007
Par NiKo le mardi 22 mai 2007, 11:14
Mon camarade de Nespresso Xavier Lacot nous gratifie d'un plugin pour Symfony répondant au doux nom de sfPropelActAsTaggableBehaviorPlugin et permettant de taguer n'importe quel objet Propel très facilement, mais aussi de gérer les requêtes multi-tags et la récupération d'objets de types multiples.
Ce plugin sera notamment utilisé dans un projet qui touchera prochainement de très près ce blog, si les conditions normales de températures et de pression le permettent, comme d'hab.
Du très bon boulot, Xavier !
dimanche 29 avril 2007
Par NiKo le dimanche 29 avril 2007, 15:15
Dans un précédent billet, nous avons vu comment créer un weblog basique avec l'admin-generator de Symfony. Nous allons reprendre là où nous en étions et ajouter la liste des commentaires à notre back-office de gestion des billets grâce à un simple appel de composant, qui n'est autre qu'un template partiel associé à un contrôleur dédié.
Si ce n'est déjà fait, on crée notre module de gestion des commentaires
# symfony propel-init-admin back comments Comment
Bien. On va maintenant créer un composant postcomments qui affichera la liste des commentaires associés à un objet Post, en créant un nouveau fichier apps/back/modules/posts/actions/components.class.php et en y insérent le contenu ci-dessous :
<?php class postsComponents extends sfComponents { /** * List comments for a given Post * */ public function executePostcomments() { $post_id = $this->getRequestParameter('id'); if (!is_null($post_id)) { $c = new Criteria(); $c->add(CommentPeer::POST_ID, $post_id); $c->addDescendingOrderByColumn(CommentPeer::CREATED_AT); $this->comments = CommentPeer::doSelect($c); } } }
On crée maintenant le template partiel associé au contrôleur, dans le fichier apps/back/modules/posts/templates/_postcomments.php :
<?php if (isset($comments)): ?> <?php if (count($comments) > 0): ?> <?php use_helper('Comment', 'Text') ?> <dl> <?php foreach ($comments as $comment): ?> <dt> <?php echo sprintf('Posté le <strong>%s</strong> par <strong>%s</strong> :', format_date($comment->getCreatedAt(), 'd/MM/yyyy à H:m'), format_comment_author($comment->getAuthor(), $comment->getSite())) ?> </dt> <dd> <?php echo simple_format_text($comment->getContent()) ?> </dd> <dd> [<?php echo link_to('Éditer', 'comments/edit?id='.$comment->getId()) ?>] [<?php echo link_to('Supprimer', 'comments/delete?id='.$comment->getId(), 'confirm=Êtes-vous sûr ?') ?>] </dd> <?php endforeach; ?> </dl> <?php else: ?> <p>No comment yet.</p> <?php endif; ?> <?php endif; ?>
La fonction format_comment_author est un helper maison, que nous définissons dans un nouveau fichier lib/helper/CommentHelper.php :
<?php /** * Returns a formatted html string for author including website link if any * * @param string $name * @param string $site * @param boolean $nofollow * @return string */ function format_comment_author($name, $site=null, $nofollow=true) { if (!is_null($site) && preg_match('/^http/i', $site)) { return sprintf('<a href="%s"%s>%s</a>', $site, $nofollow === true ? ' rel="nofollow"' : '', $name); } else { return $name; } }
Ceci fait, modifions le fichier de configuration du back-office d'administration des billets créé précemment et situé dans le fichier apps/back/modules/posts/config/generator.yml, afin d'appeller notre nouveau composant postcomments pour la vue d'édition d'un billet :
[...]
# Customisation du formulaire d'ajout/édition
edit:
[...]
# Affichage d'une sélection de champs
display: [author_id, title, excerpt, body, post_sections, ~postcomments]
Vous noterez le caractère ~ précedant le nom du composant : encore une convention Symfony qui nous simplifie la vie 
Vous avez tous déjà entendu parler des failles XSS ? Pour nous en prémunir partiellement, nous allons activer l'échappement automatique des contenus passés à une vue, en ajoutant ces directives dans le fichier apps/back/config/settings.yml :
all:
.settings:
escaping_strategy: both
escaping_method: ESC_ENTITIES
Ainsi, dans notre cas toutes les chaînes seront échappées en entités HTML pour plus de sécurité. Pour plus d'information, rendez-vous dans la section dédiée de la documentation officielle.
Au final, voici ce que ça donne quand on édite un billet :
Notre liste de billets, pour l'instant, ne nous informe pas pour chacun le nombre de commentaires associés. On va y remédier simplement en créant un getter ad-hoc dans notre objet de donnée Post et en appellant le champs virtuel associé. Dans le fichier lib/model/Post.php, on rajoute la méthode suivante :
public function getCommentsNumber() { return $this->countComments(); }
Et dans le fichier apps/back/modules/posts/config/generator.yml, on affiche le champs virtuel comments_number dans la vue en liste :
[...]
# Customisation des colones de la vue en liste
list:
display: [=title, excerpt, Author, comments_number, created_at, updated_at]
Voici ce que ça donne :
Voila, notre application prend forme doucement. On pourrait passez des heures à ajouter des détails par-ci par-là, mais je vous laisse le faire en compagnie de la documentation 
samedi 28 avril 2007
Par NiKo le samedi 28 avril 2007, 16:26
Lors du dernier petit-déjeuner Clever Age que j'ai animé sur les frameworks PHP, j'ai effectué une démonstration des fonctionnalités de génération de back-office existantes dans Symfony : la plupart des gens présents - pour la plupart découvrant la notion même de framework - ont été très impressionnés par la facilité déconcertante avec laquelle il était possible de développer une application complète en très peu de temps et d'étapes techniques grâce au générateur d'admin...
Personnellement, je suis tellement habitué à travailler avec de tels outils désormais que j'oublie parfois comme la vie est plus difficile sans eux... Je vais donc faire une démonstration afin que chacun puisse se faire son idée, sur sa propre machine 
Pour faire très original, on va créer une petite application sommaire de gestion de weblog, doté des fonctionnalités suivantes :
L'avantage est que la plupart des frameworks web proposent ce type de tutoriaux, donc ainsi vous pourrez plus aisément comparer 
Je vous renvoie à la documentation officielle ou à ce tutoriel pour installer Symfony sur votre machine et configurer un vhost apache pour votre nouveau projet. On partira sur la version 1.0.2, soit la dernière version stable disponible à l'heure où sont écrites ces quelques lignes.
Imaginons que votre projet soit créé dans /var/www :
$ sudo -s # cd /var/www # mkdir sftest && cd sftest # symfony init-project sftest
Note: Si la page web par défaut du projet n'affiche pas d'images, il se peut que votre vhost ne trouve pas les éléments médias génériques de Symfony ; dans ce cas, un lien symbolique comme ci-dessous devrait régler le problème :
# ln -s /usr/share/php/data/symfony/web/sf web/sf
Note : Vous pourriez tout autant utiliser un alias apache dans votre vhost.
Créons maintenant nos deux applications front et back qui recevront le front-office et la console d'administration de notre projet :
# symfony init-app front # symfony init-app back
On crée une base de données dédiée au projet :
# mysql -uroot -p > CREATE DATABASE sftest CHARACTER SET utf8 COLLATE utf8_general_ci; > GRANT ALL ON sftest.* TO sftest@localhost IDENTIFIED BY '1234567' > FLUSH PRIVILEGES; > \q
D'abord, on renseigne notre DSN MySQL dans le fichier config/databases.yml :
all:
propel:
class: sfPropelDatabase
param:
dsn: mysql://sftest:1234567@localhost/sftest
On fait la même chose pour Propel, dans le fichier config/propel.ini :
propel.database.url = mysql://sftest:1234567@localhost/sftest
On crée le schéma de base notre de données, dans le fichier config/schema.yml :
propel:
blog_authors:
_attributes: { phpName: Author }
id:
name: varchar(255)
email: varchar(255)
blog_posts:
_attributes: { phpName: Post }
id:
title: varchar(255)
excerpt: longvarchar
body: longvarchar
author_id:
created_at:
updated_at:
blog_comments:
_attributes: { phpName: Comment }
id:
post_id:
author: varchar(255)
email: varchar(255)
site: varchar(255)
content: longvarchar
created_at:
blog_sections:
_attributes: { phpName: Section }
id:
name: varchar(255)
blog_posts_sections:
_attributes: { phpName: PostSection }
id:
post_id:
section_id:
Il y a beaucoup de magie dans la syntaxe de ce fichier. Retenez juste que les champs id, *_id et *_at sont nommés en vertus de conventions Symfony pour gérer automatiquement clés primaires, clés étrangères et les champs de type DATETIME.
De même et parce qu'on est des gens sérieux (mais surtout parceque c'est pratique), on crée d'emblée un jeu de données de test (ou fixtures), dans un nouveau fichier data/fixtures/data.yml :
Author:
NiKo:
name: NiKo
email: tepafou@fai.com
Post:
FirstPost:
title: Mon premier post !
excerpt: Un premier billet prometteur...
body: >
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Integer
consectetuer congue diam. Sed eu enim. Cras fringilla, erat et pretium
tincidunt, elit nibh imperdiet lectus, vel viverra erat velit in
metus. Ut ipsum ante, ornare luctus, hendrerit in, ultricies id, est.
author_id: NiKo
SecondPost:
title: Mon deuxième billet
excerpt: Un deuxième billet tout aussi savoureux.
body: >
Suspendisse potenti. Mauris id risus. Cras urna. Etiam vel enim nec
dui ultrices condimentum. Curabitur bibendum ultrices quam. Nulla
sodales risus eget nunc.
author_id: NiKo
Section:
Humeurs:
name: Humeurs
Geek:
name: Geek
Ubuntu:
name: Ubuntu
PostSection:
# First post categories
FirstPost_Humeurs:
post_id: FirstPost
section_id: Humeurs
FirstPost_Geek:
post_id: FirstPost
section_id: Geek
# Second post categories
SecondPost_Geek:
post_id: SecondPost
section_id: Geek
SecondPost_Geek:
post_id: SecondPost
section_id: Ubuntu
Comment:
Comment1:
post_id: FirstPost
author: Jean-Paul
email: "jp@fai.com"
site: "http://blog.jeanpaul.com"
content: Bravo, belle intervention.
Comment2:
post_id: SecondPost
author: Jean-Luc
email: "jl@fai.com"
site: "http://blog.jeanluc.org"
content: Exactement, vous avez raison.
Ceci fait, on va lancer la génération du fichier SQL et des classes représentant notre modèle, créer les tables physiquement dans notre base et insérer notre jeu de données de test :
# symfony propel-build-all-load back
Vous noterez qu'un seule ligne de commande est à appeller, ce qui simplifie grandement les phases de prototypage.
Note : En cas de modification profonde du modèle de données, il est vivement conseillé de vider le cache symfony :
# symfony cc
__toString() aux objets de donnéesAfin d'avoir facilement un descripteur texte pour notre objet Author, nous allons implémenter une méthode __toString() dans sa classe associée située dans le fichier lib/model/Author.php :
class Author extends BaseAuthor { public function __toString() { return $this->getName(); } }
Cette méthode retournera le contenu du champs name de l'enregistrement de la table blog_authors correspondant pour identifier l'objet PHP sous la forme d'une chaîne de caractère descriptive. Vous pouvez aussi adapter ce principe pour les objets Post et Section, par exemple.
Maintenant, on va générer une interface d'administration de nos objets Post, accessible par un contrôleur /posts depuis notre application back :
# symfony propel-init-admin back posts Post
L'interface d'administration est maintenant accessible via /back_dev.php/posts derrière la racine de l'url de votre instance projet Symfony 
C'est un peu sec par défaut et les sections associées aux billets du blog ne sont pas gérées, il nous faut donc adapter le fichier de configuration du générateur d'admin de Symfony pour ce module, situé dans le fichier apps/back/modules/posts/config/generator.yml :
generator:
class: sfPropelAdminGenerator
param:
model_class: Post
theme: default
# Customisation des colones de la vue en liste, lien d'édition sur le titre
list:
display: [=title, excerpt, Author, created_at, updated_at]
# Customisation du formulaire d'ajout/édition
edit:
# Champs personnalisés
fields:
# Création d'un champs d'administration des sections associées
post_sections: { type: admin_check_list, params: through_class=PostSection }
# Spécification des champs de formulaire à afficher
display: [author_id, title, excerpt, body, post_sections]
Un raffraîchissement des interfaces en mode développement (en appellant le contrôleur back_dev.php dans l'url) affichera nos interfaces modifiées en conséquences. Si vous utilisez le contrôleur de production (/back.php), n'oubliez pas de vider le cache symfony pour visualiser vos modifications :
# symfony cc
On reproduira exactement la même opération pour nos autres objets à administrer (Author, Comment et Section):
# symfony propel-init-admin back authors Author # symfony propel-init-admin back sections Section # symfony propel-init-admin back comments Comment
Voila, une vingtaine de minutes nous auront suffit pour générer une application en ligne relativement complète. Il restera à gérer notamment :
Amusez-vous bien 
« billets précédents - page 3 de 7 - billets suivants »