» Publishers, Monetize your RSS feeds with FeedShow: More infos (Show/Hide Ads)
J’ai pas franchement l’habitude de publier ce genre de billets, mais pourriez-vous prendre quelques secondes pour voter pour ma galerie au concours Fnac Photo[1] ?
Il y a un Nikon D700 à gagner, le genre de bestiaux qui m’a toujours fait saliver 
Edit : Bon comme on me l’a fait judicieusement remarquer en commentaire, le concours est censé mettre en avant des photos "rigolotes". C’est pas trop le cas des trois clichés que j’ai envoyé, mais bon, l’humour c’est super subjectif non ? (I do want this d700)
Notes
[1] Si et seulement si vous lui trouvez quelque qualité, bien entendu.
Ce billet intitulé Yes I can a été rédigé par Nicolas Perriault et publié sur le blog Prendre un Café sous licence Creative Commons BY-NC-SA.
Mon Dieu, les billets techniques refleuriraient-ils au printemps ? Si vous désirez récupérer des informations géographiques à partir de l’adresse IP (ou du hostname) d’un utilisateur, vous pouvez utiliser les fonctions fournies par l’extension PECL GeoIP.
Voici la procédure d’installation sur une Ubuntu 8.04:
$ sudo -s # apt-get install build-essential php5-dev php5-cli libgeoip-dev libgeoip1 php-pear # pecl install geoip
Si toiut s’est bien passé :
# echo "extension=geoip.so" >> /etc/php5/cli/php.ini
Si vous utilisez Apache comme serveur :
# echo "extension=geoip.so" >> /etc/php5/apache2/php.ini
Il faut également installer la base GeoIPCity de Maxmind :
# wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz # gunzip GeoLiteCity.dat.gz # mv GeoLiteCity.dat /usr/share/GeoIP/GeoIPCity.dat
Vous pouvez maintenant tester l’extension avec une ligne du genre[1] :
$ echo "<?php var_dump(geoip_record_by_name('209.202.168.**'));"|php
Ça donne ici :
array(11) { ["continent_code"]=>
string(2) "NA"
["country_code"]=>
string(2) "US"
["country_code3"]=>
string(3) "USA"
["country_name"]=>
string(13) "United States"
["region"]=>
string(2) "NC"
["city"]=>
string(4) "Cary"
["postal_code"]=>
string(5) "27511"
["latitude"]=>
float(35.7********)
["longitude"]=>
float(-78.7*******)
["dma_code"]=>
int(560)
["area_code"]=>
int(919)
}
Enjoy.
Notes
[1] J’ai volontairement masqué certaines informations pour d’évidentes raisons de confidentialité.
Ce billet intitulé Utiliser les fonctions GeoIP de PHP sous Ubuntu a été rédigé par Nicolas Perriault et publié sur le blog Prendre un Café sous licence Creative Commons BY-NC-SA.
Redmine est un gestionnaire de projet technique exploitant Ruby on Rails et très inspiré de Trac, mais qui le dépasse fonctionnellement sur plusieurs points, notamment avec une gestion multiprojets qui fait cruellement défaut à son inspirateur. Voyons comment installer et déployer la dernière version de la branche stable (0.8) sur une Ubuntu Hardy Heron LTS[1].

Toutes les opérations décrites ci-dessous se font en root, mais libre à vous d’utiliser sudo à chaque fois, ou une fois pour toutes en lançant la commande sudo -s.
En préambule, on installe les quelques paquets qui nous seront nécessaires[2] :
# apt-get install build-essential ruby ruby1.8-dev rake libopenssl-ruby \ libmysql-ruby apache2-threaded-dev subversion git
Maintenant, on récupère les sources de Redmine[3], qu’on va installer dans /opt :
# svn co http://redmine.rubyforge.org/svn/branches/0.8-stable /opt/redmine-0.8 # ln -s /opt/redmine-0.8 /opt/redmine
On va ajouter les sources de la version 2.1.2 de rails[4] dans le répertoire vendor de l’application, afin de cloisonner autant que possible l’environnement qu’elle exploite :
# cd /opt/redmine # wget -O rails.tar.gz http://github.com/rails/rails/tarball/v2.1.2 # tar xvzf rails.tar.gz && rm rails.tar.gz # mv railsXXX vendor/rails
Créez maintenant une base de données (MySQL ou autre) dédiée à Redmine. Une bonne pratique est de créer également un utilisateur MySQL aux droits restreints à sa seule exploitation.
Ensuite, éditez le fichier config/database.yml afin de modifier les paramètres de connexion à la base de données précédemment créée.
On installe maintenant une version récente de rubygems, ce qui nous permettra d’installer passenger, une sorte de mod_rails permettant de déployer facilement des applications rails sur un serveur Apache :
# wget http://rubyforge.org/frs/download.php/56228/rubygems-1.3.3.tar.gz # tar xvzf rubygems-1.3.3.tar.gz && rm rubygems-1.3.3.tar.gz # ruby setup.rb # rm -r rubygems-1.3.3
Vous pouvez maintenant lancer la tâche de création des tables :
# rake db:migrate RAILS_ENV="production"
Et remplir la base avec quelques données par défaut :
# rake redmine:load_default_data RAILS_ENV="production"
On installe donc passenger, qui au passage vous posera quelques questions très simples :
# gem install passenger
On installe le module apache pour prendre en charge passenger :
# passenger-install-apache2-module
Pour mapper un domaine - par exemple mon.domaine.tld - vers votre instance Redmine, il faut d’abord créer un VirtualHost apache dédié, par exemple dans le fichier /etc/apache2/sites-available/redmine :
<VirtualHost *> SetEnv RAILS_ENV production ServerName mon.domaine.tld DocumentRoot /opt/redmine/public </VirtualHost>
Vous noterez que la racine publique du vhost pointe vers le dossier public de l’instance Redmine précédemment installée. N’oubliez pas non plus de déclarer le domaine dans votre fichier /etc/hosts :
127.0.0.1 mon.domaine.tld
On active maintenant le vhost et on relance Apache :
# a2ensite redmine # /etc/init.d/apache2 restart
Une dernière petite chose, vous devez autoriser Apache à lire et écrire dans certains répertoires de l’instance Redmine, comme suit :
# cd /opt/redmine # chown -R www-data:www-data files log tmp # chmod -R ug+rw files log tmp # chmod -R o-rw files log tmp
Voila, vous devriez avoir une instance totalement fonctionnelle de Redmine, accessible par le domaine que vous avez configuré.
En cadeau Bonux, le support de GMail et TLS pour l’envoi d’emails
Si vous désirez configurer l’envoi des emails en utilisant un (ou votre) compte GMail[5], voici la procédure :
Installez tout d’abord le support de TLS pour ActiveMailer :
# cd /opt/redmine # ruby script/plugin install git://github.com/collectiveidea/action_mailer_optional_tls.git
Puis éditez le fichier config/email.yml :
production:
delivery_method: :smtp
smtp_settings:
tls: true
address: "smtp.gmail.com"
port: '587'
domain: "smtp.gmail.com"
authentication: :plain
user_name: "votreadresse@gmail.com"
password: "votremotdepasse"
Relancez Apache pour que la modification soit effective.
Edit : Prise en compte de certaines remarques faites en commentaires.
Notes
[1] C’est la version qui propulse mon serveur.
[2] Ce sont les paquets qui m’ont été nécessaires, sur ma machine ; n’hésitez pas à remonter d’éventuels manques en commentaires.
[3] On installe ici la dernière branche stable disponible à l’heure où sont écrites ces lignes, la 0.8.
[4] Oui, il y a plus récent, mais Redmine 0.8 est conçu pour tourner avec cette version : autant limiter les risques d’incompatibilités.
[5] L’intérêt principal à mes yeux reste l’archivage de tous les éléments envoyés.
Ce billet intitulé Installer Redmine sous Ubuntu a été rédigé par Nicolas Perriault et publié sur le blog Prendre un Café sous licence Creative Commons BY-NC-SA.
Trop silencieux, ce blog, ces derniers temps ? Qu’à cela ne tienne, une bonne connerie des familles un Mars®, et ça repart.
Si vous possédez un groupe de musiques approximatives et vous ne savez pas comment le prénommer, et encore moins où puiser l’inspiration pour produire le packaging de votre premier futur album à succès, qu’à cela ne tienne ; Henry Michel - en plus de connaître les mêmes affres que ma personne suite à un brutal sevrage tabagique et m’avoir provoqué quelques barres de rires récemment - a la solution : le Wikipedia Names Your Band™.
La recette est ma foi fort simple :
- Rendez-vous sur Wikipedia et choisissez un article au hasard : le titre de la page sélectionnée aléatoirement sera le nom de votre groupe - non, ne me remerciez pas ;
- Retenez les quatre ou cinq derniers mots de la dernière citation affichée sur Random Quotes ; vous venez de successfullement choisir le nom de votre album, avec une réelle inventivité : bravo ;
- Rendez-vous maintenant sur la page des photos les plus intéressantes de FlickR[1] et sauvegardez l’image de grande taille correspondant à la troisième image de la page, afin d’obtenir l’illustration de la pochette.
Vous avez maintenant tous les ingrédients pour créer votre pochette de disque. Chez moi ça donne ça :

N’hésitez pas à proposer vos créations originales en commentaires, qu’on fasse ensemble un peu sauter la soupape (qui en a bien besoin me concernant).
Ce billet intitulé Non, je ne suis pas mort (†) a été rédigé par Nicolas Perriault et publié sur le blog Prendre un Café sous licence Creative Commons BY-NC-SA.
Comme certains l’ont sans doute constaté récemment, ce blog est très silencieux ces derniers temps. En effet, outre un travail qui m’accapre au quotidien, je me suis pris d’affection pour la photographie. Je me suis payé un reflex, un Canon 450D[1], dont je suis très satisfait pour le moment.
Un peu auparavant, J’avais tenté l’aventure du compact avancé sous la forme du Panasonic LX3, mais j’avais vraiment envie de quelque chose de très complet, tant au niveau des réglages que de l’ergonomie, et surtout la possibilité d’utiliser plusieurs types d’objectifs différents avec le même boitier. J’ai donc revendu le LX3 à Maurice et il semble qu’il a fasse depuis un excellent usage 
Bref, je vous fait donc part de quelques clichés réalisé récemment avec cet appareil[2].
Notes
[1] Je me suis par ailleurs équipé d’un objectif 50mm f1/8 en plus du 18/55 livré en kit.
[2] Pour info, certains on été retouchés avec l’excellentissime Lightroom d’Adobe
D’autres photos sont par ailleurs accessibles sur mon flux flickr.
N’hésitez pas à critiquer ou à me suggérer des axes d’amélioration, ce billet est là pour ça 
Ce billet intitulé Y'a photo a été rédigé par Nicolas Perriault et publié sur le blog Prendre un Café sous licence Creative Commons BY-NC-SA.
Quasiment tout le monde a peur de perdre son boulot et fait ce que demande l’actionnaire (produire plus, vendre plus…), même si chacun de nous commence à réaliser que notre société n’est pas durable. On le sait, il est beaucoup plus difficile d’expliquer quelque chose à quelqu’un s’il est payé pour ne pas le comprendre.
Voila, tout est dit, rien à ajouter.
PS : Oui oui, le contenu intéressant revient bientôt sur ce blog.
PPS : Oups, j’ai oublié de fêter le quatrième anniversaire de ce blog. Alors bon anniversaire, blog.
Ce billet intitulé QOTD a été rédigé par Nicolas Perriault et publié sur le blog Prendre un Café sous licence Creative Commons BY-NC-SA.
I must admit it, I am a guitarist. Not a good one, but I like playing the instrument, and listening to good guitar players. So I’ve just opened a little blog, the Guitar Tune Of The Day blog which aims to present a song I like, every day if I can.
Oh, and happy end of year people.
Ce billet intitulé Announcing the Guitar Tune Of The Day Weblog a été rédigé par Nicolas Perriault et publié sur le blog Prendre un Café sous licence Creative Commons BY-NC-SA.
Je suis pas super fan des gros lieux communs faciles et généralistes, mais :
Ma conclusion de cette journée est qu’on ne peut pas laisser le web aux “entrepreneurs”, c’est pas possible.
Christian Fauré, à propos de "LeWeb" (sic)
En fait, ça serait totalement drôle si ce n’était pas aussi vrai, et triste.
Edit : Olivier a pas tort, on peut y adjoindre les consultants experts[1] autoproclamés. Désolé, je suis pas particulièrement politiquement correct ces derniers temps, ça doit être la fatigue.
Edit2 : Pfff, décidemment… On peut bien évidemment aussi ajouter les politiques (mais comment aie-je pu les oublier ?)
Notes
[1] Et en tant qu’ancien consultant, je sais particulièrement de quoi je parle, propulsé expert du jour au lendemain sans même une formation sur la techno…
Ce billet intitulé QOTD a été rédigé par Nicolas Perriault et publié sur le blog Prendre un Café sous licence Creative Commons BY-NC-SA.
[13:13:07] Glooze: hey, doctrine + sf, ca roxxe quand même
[13:13:29] NiKo: génial, tu peux faire un billet pour le dire steup ?
[13:13:48] Glooze: dès que j’aurai trouvé un pdf de la doc !
[13:13:54] NiKo: un pdf oO
[13:14:05] NiKo: tu connais pomme P -> PDF
[13:14:13] Glooze: Ouais mais non
[13:14:29] Glooze: j’suis pas sous mac tout le temps (notamment mon portable il est sous ubuntu)
[13:14:32] NiKo: ahhh ok môssieur veut un beau livre relié cuir, bien sûr
[13:14:39] NiKo: ben sous ubuntu c’est natif
[13:14:43] NiKo: imprimer -> pdf
[13:14:47] NiKo: depuis firefox
[13:14:50] Glooze: et pis surtout une doc sur 8 pages, ça me fait aller sur chaque et imprimer
[13:14:51] Glooze: :o
[13:14:59] Glooze: Alors une doc plus grosse
[13:15:30] NiKo: si tu fais pas de billet, je faillote sur mon blog en faisant un gros copier coller de cette discussion
[13:15:32] NiKo: </menace>
[13:15:36] Glooze: Y a eu des tas de changements (en mieux d’ailleurs) pour la 1.2, donc mon definitive guide (acheté môssieur) il est plus trop utile
[13:15:44] Glooze: Mais vas-y, faillote !
[13:15:47] NiKo: ça marche
Ce billet intitulé Fayotage a été rédigé par Nicolas Perriault et publié sur le blog Prendre un Café sous licence Creative Commons BY-NC-SA.
Sorry for the lame title of this blog post, but I’m happy enough to announce the immediate availability of both symfony 1.2 and Jobeet, the new symfony advent calendar!
Jobeet It is a set of 24 tutorials, published day-by-day between December 1st and Christmas. Each tutorial is meant to last one hour, and will be the occasion to see the ongoing development of a web application with symfony, from A to Z.
So don’t hesitate to start reading day one of this great tutorial 
Edit: I forgot to mention the simultaneous release of the symfony and Doctrine book 
Ce billet intitulé Meet Joe Beet a été rédigé par Nicolas Perriault et publié sur le blog Prendre un Café sous licence Creative Commons BY-NC-SA.
It’s been quite a long time I didn’t give a go to Doctrine, so as it’s gonna be bundled by default in with the upcoming 1.2 release of symfony, I thought it was a good occasion to play with it.
So let’s checkout the 1.2 SVN branch of symfony and create a test project with a main application[1]:
$ mkdir sf12test && cd sf12test $ mkdir -p lib/vendor $ svn co http://svn.symfony-project.com/branches/1.2 lib/vendor/symfony $ php lib/vendor/symfony/data/bin/symfony generate:project sf12test $ ln -s ../lib/vendor/symfony/data/web/sf web/sf $ ./symfony generate:app main
Create a webserver vhost pointing to the web folder of the project directory. I’ve already explained plenty of times how to achieve this step.
Now, let’s enable the sfDoctrinePlugin and disable the Propel one by editing the setup() method of the config/ProjectConfiguration.class.php file:
public function setup() { $this->disablePlugins('sfPropelPlugin'); $this->enablePlugins('sfDoctrinePlugin'); }
You can list the available tasks running this simple command:
$ ./symfony list doctrine
Managing the Database Schema
First, configure your config/databases.yml file to set the database connection parameters. If you want to quick test Doctrine, use a local SQLite db, like this:
all:
doctrine:
class: sfDoctrineDatabase
param:
dsn: sqlite://<?php echo dirname(__FILE__).'/../data/data.db' ?>
We’re going to make a very simple weblog application, so let’s configure our database schema. We can do it in YAML[2], so fire up your favorite editor/IDE and edit a brand new config/doctrine/schema.yml:
BlogPost:
actAs:
Sluggable:
fields: [title]
Timestampable:
columns:
title: string(255)
body: clob
author: string(255)
BlogComment:
actAs: [Timestampable]
columns:
blog_post_id: integer
author: string(255)
email: string(255)
content: clob
relations:
BlogPost:
class: BlogPost
local: blog_post_id
foreign: id
foreignType: many
type: one
Note that Doctrine offers several pretty cool features including native behaviors (timestampable and slugable are used here).
Now, create a data/fixtures folder and put a data.yml file in, containing some test data in YAML format:
BlogPost:
p1:
title: My first post
body: |
This is cool.
author: NiKo
created_at: "<?php echo date('Y-m-d H:i:s', time() - 86400) ?>"
p2:
title: My second post
body: |
This is still cool.
author: NiKo
created_at: "<?php echo date('Y-m-d H:i:s', time() - 7200) ?>"
p3:
title: Third post
body: |
Is this one cool?
author: Roger Hanin
created_at: "<?php echo date('Y-m-d H:i:s') ?>"
BlogComment:
c1:
BlogPost: p3
author: John
email: john@doe.com
content: Hey, you're right there.
created_at: "<?php echo date('Y-m-d H:i:s', time() - 86400) ?>"
c2:
BlogPost: p3
author: Paul
email: paul@doe.com
content: Nope, he's not.
created_at: "<?php echo date('Y-m-d H:i:s') ?>"
Okay, now run the command below to generate the needed files, create the database and fill it with the data fixtures:
$ ./symfony doctrine:build-all-load
We can run several DQL queries in command line to check if everything is fine. DQL is very powerful, and compatible with a lot of RDBMS. You’ll find more information on DQL on the doctrine website.
For example, to find all blog posts:
$ ./symfony doctrine:dql "From BlogPost p" found 3 results - id: '21' title: 'My first post' body: "This is cool.\n" author: NiKo slug: my-first-post created_at: '2008-10-29 15:14:25' updated_at: '2008-10-30 15:14:25' - id: '22' title: 'My second post' body: "This is still cool.\n" author: NiKo slug: my-second-post created_at: '2008-10-30 13:14:25' updated_at: '2008-10-30 15:14:25' - id: '23' title: 'Third post' body: "Is this one cool?\n" author: 'Roger Hanin' slug: third-post created_at: '2008-10-30 15:14:25' updated_at: '2008-10-30 15:14:25'
Another example, to find informations about the blog post with slug third-post and its associated comments:
$ ./symfony doctrine:dql "Select p.title, p.author, c.author, c.content From BlogPost p, p.BlogComment c Where p.slug = 'third-post' Group by c.id"
found 3 results
-
id: '23'
title: 'Third post'
author: 'Roger Hanin'
BlogComment: [{ id: '15', author: John, content: 'Hey, you''re right there.' }, { id: '16', author: Paul, content: 'Nope, he''s not.' }]
Put the Query Logic in the Model
The Model part of any MVC architecture must contains the business data and associated logic. In other words, these data and logic should never be handled anywhere else, to decouple your components at max. So we’ll add some query methods in the lib/model/doctrine/BlogPostTable.class.php file, which represents our blog_post table and available operations on it:
<?php class BlogPostTable extends Doctrine_Table { public function getAll() { return Doctrine_Query::create()-> select('p.title, p.slug, p.body, p.author, p.created_at, count(c.id) numcomments')-> from('BlogPost p, p.BlogComment c')-> orderBy('p.created_at DESC')-> groupBy('p.id')-> execute(); } public function getOneBySlug($slug) { $posts = Doctrine_Query::create()-> from('BlogPost p')-> leftJoin('p.BlogComment c')-> where('p.slug = ?')-> orderBy('c.created_at ASC')-> limit(1)-> execute(array($slug)); return isset($posts[0]) ? $posts[0] : null; } }
A Weblog is About Web Interface, uh?
Okay, let’s add pretty controllers and templates to give some life to our blog. First, generate a post module in the main app:
$ ./symfony generate:module main post
Then, edit the apps/main/modules/post/actions/actions.class.php file:
<?php class postActions extends sfActions { public function executeIndex($request) { $this->posts = Doctrine::getTable('BlogPost')->getAll(); } public function executeShow($request) { $this->post = Doctrine::getTable('BlogPost')->getOneBySlug($slug = $request->getParameter('slug')); $this->forward404Unless($this->post, 'No post with slug=' . $slug); $this->comments = $this->post->getBlogComment(); } }
We should have display templates too. The first one will show the posts list, in apps/main/modules/post/templates/indexSuccess.php:
<?php foreach ($posts as $post): ?> <?php include_partial('post/post', array('post' => $post, 'numComments' => $post->getNumcomments())) ?> <hr/> <?php endforeach; ?>
Note that we must create the _post partial template, in apps/main/modules/post/templates/_post.php:
<h2><?php echo link_to($post->getTitle(), 'post/show?slug='.$post->getSlug()) ?></h2> <p> <small>Posted by <?php echo $post->getAuthor() ?> on <?php echo $post->getCreatedAt() ?> <?php if (isset($numComments)): ?> - <?php echo $numComments ?> comments <?php endif; ?> </small> </p> <?php echo $post->getBody(ESC_RAW) ?>
The other main template will display one post and its comments, in apps/main/modules/post/templates/showSuccess.php:
<?php include_partial('post/post', array('post' => $post)) ?> <h2>Comments</h2> <?php if (!count($comments)): ?> <p>No comment yet.</p> <?php else: ?> <?php foreach ($comments as $comment): ?> <p><small>By <?php echo $comment->getAuthor() ?> on <?php echo $comment->getCreatedAt() ?></small></p> <blockquote><?php echo $comment->getContent() ?></blockquote> <?php endforeach; ?> <?php endif; ?>
That’s it. A rough but functional weblog if you lauch your browser to yourhost/main_dev.php/post/index:

And if you click a post title:

Good News, the Forms Framework Works with Doctrine Too
Symfony 1.1 introduced the new forms framework, and good news, Doctrine can take part of it. So maybe you’ve already noticed it, we have form classes generated already, in the lib/form/doctrine folder of the project.
So let’s add a neat commenting system to our blog, by first editing the lib/form/doctrine/BlogCommentForm.class.php file:
<?php class BlogCommentForm extends BaseBlogCommentForm { public function configure() { unset($this['id'], $this['created_at'], $this['updated_at']); $this->widgetSchema['blog_post_id'] = new sfWidgetFormInputHidden(); $this->validatorSchema['author'] = new sfValidatorString(array('min_length' => 3)); $this->validatorSchema['email'] = new sfValidatorEmail(); $this->validatorSchema['content'] = new sfValidatorString(array('min_length' => 5)); } }
Now, use the form in the executeShow() method of our controller:
<?php // ... public function executeShow($request) { $this->post = Doctrine::getTable('BlogPost')->getOneBySlug($slug = $request->getParameter('slug')); $this->forward404Unless($this->post, 'No post with slug=' . $slug); $this->comments = $this->post->getBlogComment(); $comment = new BlogComment(); $comment->setBlogPost($this->post); $this->form = new BlogCommentForm($comment); if ($request->isMethod('post') && $this->form->bindAndSave($request->getParameter('blog_comment'))) { $this->redirect('post/show?slug='.$this->post->getSlug()); } }
And in the showSuccess.php template, we’ll append the form display:
<h3>Add a comment</h3> <?php echo $form->renderFormTag(url_for('post/show?slug='.$post->getSlug())) ?> <table> <?php echo $form ?> <tr> <td></td><td><input type="submit"/></td> </tr> </table> </form>
We’ve now a pretty commeting system added to our blog, thanks to all the goodness provided by symfony and Doctrine:

Conclusion
The time when everyone choosed Propel because it was more stable than Doctrine seems to be over. Doctrine is robust, and performs quite well on my box. Furthermore, it handles complex relationships and dynamic object hydratation natively and better than Propel. Doctrine is also very well integrated into symfony, certainly because Jonathan Wage - the Doctrine lead developer - now works for Sensio, creator and main sponsor of symfony.
Notes
[1] Note that Windows users should replace calls to ./symfony by php symfony.
[2] If you hate YAML, you can still write Doctrine table definition classes in raw PHP by hand
Ce billet intitulé Let's Play with Symfony 1.2 and Doctrine a été rédigé par Nicolas Perriault et publié sur le blog Prendre un Café sous licence Creative Commons BY-NC-SA.
Ayant récemment eu besoin de travailler sur une application utilisant memcached, j’ai du l’installer sur ma machine perso tournant sous Mac OS X. Pour mémoire, memcached est un système de stockage distribué de paires clé/valeur en mémoire vive, très rapide et performant. Cela peut s’avérer un outil de choix pour faire monter en charge une architecture, par exemple en ajoutant des frontaux web et en utilisant memcached comme espace partagé de stockage des données de session utilisateur. On peut également imaginer d’y stocker les résultats de traitements complexes, des templates compilés, des jeux de résultats SQL, etc.
J’ai trouvé un excellent tutoriel d’installation de memcache pour OS X pour cela, que je vous invite à suivre pour mettre en œuvre les exemples ci-après. Une fois l’installation effectuée, vous pouvez lancer le démon memcached avec cette ligne de commande :
$ sudo memcached -d -u nobody -m 128 127.0.0.1 -p 11211
Notez que cette dernière ligne de commande lance le démon memcached sous l’utlisateur nobody, en local sur le port 11211 et alloue 128 Mo de mémoire vive au service de stockage.
Exemple d’utilisation en PHP
Le tutoriel couvre également l’installation de l’extension PECL memcache, fournissant une API particulièrement simple et efficace à PHP pour utiliser le service.
Exemple d’utilisation basique :
<?php $m = new Memcache; $m->connect('localhost', 11211) or die ("Could not connect"); $m->set('toto', 'tata'); echo $m->get('toto'); // tata
Pour utiliser memcached comme système de stockage des sessions, PHP dispose d’un gestionnaire de sessions memcache qu’il suffit d’activer par configuration dans votre fichier php.ini. Il suffit de remplacer la valeur :
session.save_handler = files
Par ces deux lignes, en adaptant au besoin les valeurs de connexion au démon :
session.save_handler = memcache session.save_path="tcp://127.0.0.1:11211?persistent=1&weight=1&timeout=1&retry_interval=15"
Attention cependant, en cas de coupure du service memcached, toutes les données de sessions actives seront perdues.
Ce billet intitulé Utiliser Memcached avec PHP sous Mac OS X a été rédigé par Nicolas Perriault et publié sur le blog Prendre un Café sous licence Creative Commons BY-NC-SA.
Apparemment, la disparition du numéro de département français sur les plaques minéralogiques n’aura pas lieu. Le gouvernement a décidé de prendre en compte les revendications d’un groupe régionaliste, Jamais sans mon département[1], prônant l’affichage obligatoire du département sur ces plaques.

La disposition vient d’être modifiée en ce sens et oblige désormais le possesseur d’un véhicule à faire figurer un numéro de département mais pas forcément celui de son lieu de résidence réel : c’est à dire qu’il peut choisir n’importe lequel, pour peu qu’il le fasse figurer sur sa plaque.
Oui, vous avez bien lu : nous avons la première loi imposant l’utilisation de stickers régionalistes.
Notes
[1] Non mais savourez-moi ce CV d’association !
Ce billet intitulé Jamais sans mes beaufs a été rédigé par Nicolas Perriault et publié sur le blog Prendre un Café sous licence Creative Commons BY-NC-SA.
Le package complet pour la version stable d’Eclipse PDT fournit Subclipse[1] en version 1.2 par défaut.
Cette version de Subclipse est incapable de gérer la dernière version du client Subversion, la 1.5.2. La moindre tentative d’update devrait vous afficher ce message laconique : The version of this client is too old
[2].
Et bien entendu, il est au premier abord impossible de désinstaller le plugin Subclipse en version 1.2 fournit par PDT.
Aussi, voici l’astuce permettant de mettre à jour votre version de Subclipse au sein de votre environnement Exclipse/PDT :
- Dans le menu Software updates, choisissez Manage configuration
- Dépliez l’arborescence des dépendances pour le module PDT, et sélectionnez Subclipse
- Cliquez sur Disable, puis relancez Eclipse
- Dans Software Updates, choisissez Find and Install et ajoutez un nouveau dépôt distant[3], et renseignez le comme ci-dessous :
- Name :
Subclipse 1.4.x - URL :
http://subclipse.tigris.org/update_1.4.x
- Name :
- Sélectionnez ce dépôt, puis lancer la recherche de packages
- Sélectionnez les modules Subclipse et SVNKit
- Redémarrez Eclipse
Après ces manipulations, vos devriez retrouver vos fonctionnalités préférées.
Notes
[1] Subclipse est un plugin intégrant Subversion à Eclipse
[2] Et c’est pas la première fois que ça arrive…
[3] Chez Eclipse, on appelle ça un Update site
Ce billet intitulé Eclipse PDT, Subclipse et Subversion 1.5.2 sont dans un bateau a été rédigé par Nicolas Perriault et publié sur le blog Prendre un Café sous licence Creative Commons BY-NC-SA.
There should be a standard way for sending emails in upcoming symfony 1.2, and I’m in charge of implementing it, using the excellent SwiftMailer library. So I’ve created a dedicated RFC page on the symfony wiki just to get your opinions on the Right Way It Should Be Done®.
If you’re interested, there’s also a dedicated thread on the devs mailing list.
Edit: Swift integration didn’t make it for symfony 1.2, and here are my main reasons:
- I didn’t get enough time
- Swift is strangely coded from an architecture point of view: you must override the SMTP connection class to be able to send a mail using PHP
mail()native function ; so it’s hard to extend or tweak it easily - I didn’t get enough time
- Swift looked like a dead project at the time symfony 1.2 was released
- I didn’t get enough time
To be honnest I’d like to see it integrated for symfony 1.3, but maybe with another lib… Stay tuned.
Ce billet intitulé Request For Comments: sending emails in symfony 1.2 a été rédigé par Nicolas Perriault et publié sur le blog Prendre un Café sous licence Creative Commons BY-NC-SA.
I’m back from the symfony camp 2008. It’s been a really great pleasure to meet the community[1], there are so many smart people using symfony all around the world, it’s just amazing.
I gave a one day training session on symfony 1.1 to eleven attendees the day before, I think it was somewhat interesting even if it may have been too short to see every important aspects of the framework…
The conferences were also great, and some slides are already available:
- Edit: Opening Conference, by Lambert Beekhuis
- Be RESTful, by Fabien Potencier
- Beyond symfony 1.2, by Fabien
- Full Stack Web Application Performance Tuning, by Fabian Lange
- Debugging with symfony, by Stefan Koopmanschap
- The symfony Admin Generator, by Ian P. Christian
- Edit: Lessons Learned at Yahoo!, by Dustin Whittle
- Edit: Using YUI with symfony, by Dustin Whittle
- Edit: Developing for Developer, by François Zaninotto
Stefan has also taken some shots of the event.
Last and as a side note, as of now all my symfony related posts will be written in English, as it’s the main language used by the community.
Notes
[1] even if the weather was… well, dutch wet
Ce billet intitulé Back from the camp! a été rédigé par Nicolas Perriault et publié sur le blog Prendre un Café sous licence Creative Commons BY-NC-SA.
Juste une note rapide pour vous informer que le geek-guitariste-procrastinateur-multiframeworkophile-lunatique-surdoué le plus attachant de la blogosphère vient de faire son come-back sur la blogoscène, et que ça c’est quand même un peu plus enthousiasmant que les annonces chromatiques de Sergey et Larry.
Ce billet intitulé He's back a été rédigé par Nicolas Perriault et publié sur le blog Prendre un Café sous licence Creative Commons BY-NC-SA.
Bon blague à part, a priori plutôt une bonne nouvelle pour le libre, les standards et le Web en général. Reste la question que soulève Daniel Glazman :
Your search engine is google, your mail is google mail, your docs are on google docs, your maps are google, the ads you see are google, your system is Android, your browser is Google Chrome. Did someone hear the word "monopoly" ?
Ça commence effectivement à sentir pas très bon le monopole. J’adore sa conclusion finale :
Let’s see it from the bright side of life: there’s a new OSS and standards-compliant browser and that’s good, and there’s a high probability Steve Ballmer is currently breaking a few chairs and it’s even better
Rien à ajouter 
Ce billet intitulé define:Chrome a été rédigé par Nicolas Perriault et publié sur le blog Prendre un Café sous licence Creative Commons BY-NC-SA.
Hier matin, je m’insère comme tous les matins sur mon périphérique quotidien quand une petite boule de poil traverse juste devant moi, en faisant une pause juste devant ma trajectoire. N’allant pas vite et n’ayant personne me collant immédiatement au train, je m’arrête, active mes warnings et descend de la voiture pour voir ce qui se terre sous mon chassis, sous les invectives des autres voitures maintenant arrêtées derrière moi.
Je découvre une petite boule de poil totalement apeurée, un bébé chat d’à peine deux mois à tout casser. Je le récupère, le montre à ma poursuivante vociférante pour la faire taire et monte dans la voiture avec mon butin du moment. Je rentre chez moi, dépose la bestiole dans des mains de confiance, nourris la bête et repars derechef en direction du boulot. Le sourire aux lèvres.

Bienvenue, Périf’ !
Ce billet intitulé Chalut a été rédigé par Nicolas Perriault et publié sur le blog Prendre un Café sous licence Creative Commons BY-NC-SA.
C’est bien connu, il est déjà sufisament dur de faire (re)venir des utilisateurs sur vos services en ligne pour ne pas les faire partir à la moindre occasion. C’est pourtant ce que fait un site dédié à la guitare que j’ai tenté de consulter récemment. Connaissant les tendances dérivistes des services juridiques de certaines entités, je m’abstiendrai donc de faire un lien hypertexte direct vers ce dernier, et même de le citer textuellement[1].
Je tombe sur ce site, qui propose apparemment moult ressources sur l’instrument et qui m’intéressent potentiellement, mais au moment de consulter l’article objet de ma convoitise, on me notifie du message suivant :

Jusque-là, rien de profondément choquant même si on peut imaginer que nombre d’internautes ne s’embêteront pas à créer un compte pour consulter la ressource et passeront à la concurrence[2].
Allez, je suis dans un bon jour, je demande la création d’un compte. Je me retrouve face à un formulaire assez copieux, exigeant bien entendu des informations hautement nécessaires pour consulter un tutoriel de guitare comme ma localisation géographique, mon nom de famille, ma date de naissance, sans oublier bien entendu les inévitables propositions d’abonnement à des newsletter très étroitement liées à la pratique de la guitare :

Sentant le SPAM arriver à grand pas, je rentre mon email suffixé pour détecter a posteriori le service à l’origine d’éventuels courriels indésirables reçus. Ben non :

Vous noterez le plus fort, c’est que non seulement le service n’est pas à même de valider convenablement une adresse email (le signe + est acceptable), mais en plus on me soupçonne ouvertement de SPAM potentiel.
Normalement, à ce stade, je me casse sur Mars, comme on dit. Mais pour la beauté de l’exercice, je corrige mon adresse email, pérsévère en entrant un mot de passe et valide à nouveau le formulaire :

Oui, cela commence à faire beaucoup. Je ne réexpliquerai pas ici pourquoi limiter les caractères dans les mots de passe est idiot, cela a déjà été fait ici-même précédemment.
Toujours dans la perspective de poursuivre cette expérience amusante, j’arrive enfin à valider le formulaire sans retours d’erreur et m’identifie donc sur le service pour consulter la ressource en question. Patatra :

Non seulement la création d’un compte était obligatoire, mais maintenant il faut s’abonner (c’est à dire payer) pour consulter la ressource en question, chose qui n’avait été aucunement stipulée auparavant. Sachant bien entendu qu’à ce stade, je n’ai toujours aucune idée de la qualité des contenus proposés par le site.
Bref, je leur souhaite malgré tout un avenir comptable radieux, même si je ne peux m’empêcher de pouffer à l’idée du chiffre d’affaire généré par le se(r)vice.
Notes
[1] Mais les curieux trouveront bien entendu sans peine le site en question.
[2] Sur le Web, vous avez quasiment systématiquement un concurrent qui propose la même chose que vous gratuitement. C’est comme ça, et c’est aussi un peu pour ça que c’est chouette.
Ce billet intitulé Comment faire fuir à coup sûr vos utilisateurs ? a été rédigé par Nicolas Perriault et publié sur le blog Prendre un Café sous licence Creative Commons BY-NC-SA.




















