Développer un blog avec Symfony est une très belle initiative. Cela permet de se familiariser très rapidement avec tous les concepts classiques rencontrés dans la vaste majorité des projets. C’est même l’application idéale quand on découvre un nouveau langage ou une nouvelle version d’un framework, car c’est assez petit pour être réalisable (2 jours de travail pour mon blog), et vous obtenez un vrai produit fini destiné à être mis en ligne (ce qui vous permet de traiter l’ensemble de la chaîne de construction web, y compris la partie déploiement).
Cependant, bâtir un blog ex-nihilo sur un framework comme Symfony en (bientôt) 2011 est mauvais à long terme. Et c’est même inscrit dans la logique même des framework, puisqu’on nous conseille de ne pas se répéter. Or, pour une application ultra classique comme un blog, tout ce que vous ferez avec un blog custom est d’éternellement vous répéter. Vous répéter et perdre du temps, le tout pour une efficacité moindre, car votre intelligence d’atteindra jamais la somme de l’intelligence collective.
Pour ceux qui voudraient switcher d’un blog développé sous Symfony à un WordPress plus facile à gérer, je vous livre les petits scripts qui m’ont permis très rapidement (après intégration xHTML/CSS du thème, évidemment), de récupérer mes articles et mes commentaires en quelques secondes via l’outil d’import de WP.
Voici la structure de DB de mon ancien blog:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | mysql> show tables; +---------------------------+ | Tables_in_sadai_blog | +---------------------------+ | blog_category | | blog_comment | | blog_post | | blog_post_images | | sf_guard_group | | sf_guard_group_permission | | sf_guard_permission | | sf_guard_remember_key | | sf_guard_user | | sf_guard_user_group | | sf_guard_user_permission | | sf_tag | | sf_tagging | +---------------------------+ 13 rows in set (0.00 sec) |
Voici la description de la table “blog_post”:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | mysql> show columns from blog_post; +----------------+--------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +----------------+--------------+------+-----+---------+----------------+ | user_id | int(11) | YES | MUL | NULL | | | category_id | int(11) | YES | MUL | NULL | | | title | varchar(255) | YES | | NULL | | | main_pic | varchar(100) | YES | | NULL | | | slug | varchar(255) | YES | | NULL | | | content | text | YES | | NULL | | | is_published | int(11) | YES | | NULL | | | allow_comments | int(11) | YES | | NULL | | | created_at | datetime | YES | | NULL | | | published_at | date | YES | | NULL | | | id | int(11) | NO | PRI | NULL | auto_increment | +----------------+--------------+------+-----+---------+----------------+ 11 rows in set (0.00 sec) |
L’image titre, quand elle est présente, va automatiquement s’ajouter au début du contenu de l’article. Ce mécanisme est repris dans le script d’import.
Les tags, eux, sont simplement des tags, il n’y a pas de version libre et de version normalisée. Enfin, les commentaires se décrivent ainsi:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | mysql> show columns from blog_comment; +--------------+--------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +--------------+--------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | post_id | int(11) | YES | MUL | NULL | | | author_name | varchar(200) | YES | | NULL | | | author_email | varchar(255) | YES | | NULL | | | author_url | varchar(255) | YES | | NULL | | | ip | varchar(100) | YES | | NULL | | | content | text | YES | | NULL | | | is_active | int(11) | YES | | NULL | | | created_at | datetime | YES | | NULL | | +--------------+--------------+------+-----+---------+----------------+ 9 rows in set (0.00 sec) |
Nous allons donc générer un XML d’export au format WordPress, qui va nous permettre d’importer l’ensemble de notre blog (articles, tags, commentaires, catégories) en une seule commande.
Côté action, il nous faut donc récupérer l’ensemble des catégories, tags, et articles contenus en DB (on récupérera les commentaires via un accesseur sur le modèle Post). Une execution très simple (sous… Propel! Eh oui, ce blog est vieux)
1 2 3 4 5 6 7 8 | public function executeExport() { $c = new Criteria(); $this->blogCats = CategoryPeer::doSelect($c); $this->blogTags = TagPeer::doSelect($c); $this->posts = PostPeer::doSelect($c); $this->setLayout(false); } |
Puis,du côté du template, on effectue toutes les transformations nécessaires afin de satisfaire au format d’export WordPress. Pour en savoir plsu sur ce format, fouillez tout simplement le script d’export de WordPress, et parcourez cette ressource.
Voici la copie exacte du template exportSuccess.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 | <!-- This is a WordPress eXtended RSS file generated by WordPress as an export of your blog. --> <!-- It contains information about your blog's posts, comments, and categories. --> <!-- You may use this file to transfer that content from one site to another. --> <!-- This file is not intended to serve as a complete backup of your blog. --> <!-- To import this information into a WordPress blog follow these steps. --> <!-- 1. Log into that blog as an administrator. --> <!-- 2. Go to Manage: Import in the blog's admin panels. --> <!-- 3. Choose "WordPress" from the list. --> <!-- 4. Upload this file using the form provided on that page. --> <!-- 5. You will first be asked to map the authors in this export file to users --> <!-- on the blog. For each author, you may choose to map to an --> <!-- existing user on the blog or to create a new user --> <!-- 6. WordPress will then import each of the posts, comments, and categories --> <!-- contained in this file into your blog --> <!-- generator="WordPress/MU" created="2008-05-16 22:49"--> <rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:wp="http://wordpress.org/export/1.0/" > <?php $base = 'http://www.sadai.net';?> <channel> <title>Marketing & Technologies | Sadai.net</title> <link><?php echo $base;?></link> <description>Publicit´ digitale, Data, Science, Architectures.</description> <pubDate>Fri, 1 Jan 2008 22:46:22 +0000</pubDate> <generator>http://wordpress.org/?v=MU</generator> <language>fr</language> <wp:wxr_version>1.0</wp:wxr_version> <wp:base_site_url><?php echo $base;?></wp:base_site_url> <wp:base_blog_url><?php echo $base;?></wp:base_blog_url> <?php foreach ($blogCats as $blogCat):?> <wp:category> <wp:category_nicename><?php echo $blogCat->getSlug();?></wp:category_nicename> <wp:category_parent></wp:category_parent> <wp:cat_name><![CDATA[<?php echo $blogCat->getName()?>]]></wp:cat_name> </wp:category> <?php endforeach;?> <?php foreach ($blogTags as $blogTag):?> <wp:tag><wp:tag_slug><?php echo $blogTag->getName();?></wp:tag_slug><wp:tag_name><![CDATA[<?php echo $blogTag->getName();?>]]></wp:tag_name></wp:tag> <?php endforeach;?> <?php foreach ($posts as $post):?> <?php $content = $post->getContent()?> <?php if ($post->hasPic()):?> <?php $content = '<p>' . '<img src="'.$post->getPicUrl().'" border="0" align="left" style="padding-right:7px" />' . substr($content, 3);?> <?php endif;?> <item> <title><![CDATA[<?php echo $post->getTitle(); ?>]]></title> <link><?php $base . '/' . $post->getSlug(); ?></link> <pubDate><?php echo date( 'D, d M Y H:i:s +0000', strToTime($post->getCreatedAt())); ?></pubDate> <dc:creator><![CDATA[Cedric Sadai]]></dc:creator> <category><![CDATA[<?php echo $post->getCategory()->getName()?>]]></category> <category domain="category" nicename="<?php echo $post->getCategory()->getSlug()?>"><![CDATA[<?php echo $post->getCategory()->getName()?>]]></category> <?php foreach ($post->getTags() as $tag):?> <category domain="tag"><![CDATA[<?php echo $tag;?>]]></category> <category domain="tag" nicename="<?php echo $tag;?>"><![CDATA[<?php echo $tag;?>]]></category> <?php endforeach;?> <guid isPermaLink="false"><?php echo $base . '/' .$post->getSlug(); ?></guid> <description></description> <content:encoded><![CDATA[<?php echo preg_replace('/\/uploads\/assets\//i', '/wp-content/uploads/assets/', $content);?>]]></content:encoded> <wp:post_date><?php echo $post->getCreatedAt(); ?></wp:post_date> <wp:post_date_gmt><?php echo $post->getCreatedAt(); ?></wp:post_date_gmt> <wp:comment_status>open</wp:comment_status> <wp:ping_status>open</wp:ping_status> <wp:post_name><?php echo $post->getSlug(); ?></wp:post_name> <wp:status>publish</wp:status> <wp:post_type>post</wp:post_type> <wp:post_password></wp:post_password> <wp:is_sticky>0</wp:is_sticky> <?php foreach ($post->getAllComments() as $comment):?> <wp:comment> <wp:comment_id><?php echo $comment->getId()?></wp:comment_id> <wp:comment_author><![CDATA[<?php echo $comment->getAuthorName()?>]]></wp:comment_author> <wp:comment_author_email><?php echo $comment->getAuthorEmail()?></wp:comment_author_email> <wp:comment_author_url><?php echo $comment->getAuthorUrl()?></wp:comment_author_url> <wp:comment_author_IP><?php echo $comment->getIp()?></wp:comment_author_IP> <wp:comment_date><?php echo date( 'D, d M Y H:i:s +0000', strToTime($comment->getCreatedAt())); ?></wp:comment_date> <wp:comment_author_IP><?php echo $comment->getIp()?></wp:comment_author_IP> <wp:comment_date><?php echo date( 'D, d M Y H:i:s +0000', strToTime($comment->getCreatedAt())); ?></wp:comment_date> <wp:comment_date_gmt><?php echo date( 'D, d M Y H:i:s +0000', strToTime($comment->getCreatedAt())); ?></wp:comment_date_gmt> <wp:comment_content><![CDATA[<?php echo $comment->getContent()?>]]></wp:comment_content> <wp:comment_approved>1</wp:comment_approved> <wp:comment_parent>0</wp:comment_parent> <wp:comment_user_id>0</wp:comment_user_id> <wp:comment_type></wp:comment_type> </wp:comment> <?php endforeach;?> </item> <?php endforeach;?> </channel> </rss> |
Pas de grosse difficulté ici, à part qu’il faut bien donner un ID à chaque commentaire, sous peine de les voir assimiler à des doublons. Il faut également bien leur passer le statut “approved” à 1, sinon il ne seront pas importés. Enfin, à la ligne 71, je remplace toutes les occurences de /uploads/assets par /wp-content/uploads/assets/, afin que toutes mes images soient conservées au terme d’un simple copier-coller de répertoire au bon endroit.
J’ai hâte à présent de reprendre une activité de blogging plus soutenue!
La deuxième conférence 

Ces cinq dernières années ont vu l’avènement de mastodontes d’un nouveau type. Les Facebook, Youtube, et autres Twitter se sont développés à une vitesse phénoménale, un avènement se caractérisant entre autres par une explosion du volume (et de l’importance) des données stockées sur Internet.
A l’heure où pas mal de services web connaissent des
Voilà plusieurs mois que Snow Leopard trainait sur mon bureau. Précommandé à la hâte dès le mois d’Août, en bonne victime du marketing de la marque à la pomme, je ne l’ai jamais ouvert depuis. Comme si je sentais que quelque chose clochait. Les articles très critiques dans les forums, les tweets d’utilisateurs déplorant les cassures de compatibilité, les alertes reçues pour les différents* logiciels dont je possède la license (*bon, ok, les deux logiciels dont je possède la license), pour me proposer des patchs correctifs à la hâte. Bref, ça ne présageait rien de bon, et mon état d’esprit était assez bien résumé dans un de mes tweets, il n’y a pas si longtemps: “This DVD smells like Vista“. 


