Chez Xavier

Home / Votre blog sous Symfony, pas à pas

Excuse me, I think I'm naked: on a wall of Barcelona.

Excuse me, I think I'm naked: on a wall of Barcelona.

Attention, cet article n'est plus à jour. Cependant, une nouvelle version devrait voir le jour d'ici mi-août.

Introduction

Cet article s'adresse aux développeurs Web disposant des connaissances basiques en PHP, gestion de bases de données, et plus généralement d'une culture en développement Web. Il présente les différentes étapes nécessaires à la construction d'un blog à l'aide du Framework Symfony. Ce guide, spécialement adapté aux utilisateurs de Linux et plus particulièrement d'Ubuntu, présente successivement l'installation d'Apache2, PHP5, MySQL, et de Symfony, puis explique en détail les différentes étapes du développement d'un weblog. Les fonctionnalités avancées comme la possibilité de rédiger des commentaires ou de permettre des trackbacks, ne seront pas abordées dans ce tutoriel d'initiation.

Sommaire

  1. Présentation de Symfony
    1. Qu'est-ce que Symfony ?
    2. Pourquoi choisir un framework ?
  2. Installer Symfony
    1. Installation de PHP5 et Apache2
    2. Installation de PEAR et de Symfony
    3. Création d'un projet Symfony
    4. Activation d'un Virtualhost
  3. Créer votre structure de données
    1. Différentes approches possibles
    2. Création des tables
    3. Paramétrage de Symfony pour l'utilisation de votre base de données
    4. Génération des classes métier
  4. Développement du blog
    1. Création d'une interface d'administration minimaliste
    2. Insérer des données dans le blog
    3. Module public de blog
      1. Choix des url à utiliser : le routage
      2. Création des actions correspondantes
      3. Écriture des templates
      4. Réglages finaux du framework
    4. Mise en place de fils rss

Présentation de Symfony

Qu'est-ce que Symfony ?

Symfony est un cadre d'applications (ou framework) OpenSource développé en PHP5. Il reprend les grands concepts du Modèle Vue Contrôleur et des design patterns. Développé par l'entreprise française Sensio, Symfony est entièrement orienté objet et respecte un grand nombre de bonnes pratiques qui facilitent un développement Web de qualité. On y trouve, entre autres :

  • gestion de l'encodage et des types MIME
  • url propres (routage)
  • système de cache évolué
  • mise en œuvre de CRUD
  • support de l'internationalisation (i18n) par XLIFF
  • gestion des droits d'accès
  • génération assistée de l'interface d'administration
  • mise en œuvre aisée d'AJAX au sein des applications
  • ...

Il faut bien comprendre que Symfony n'est ni un CMS, ni un blog ni un forum. Symfony est un framework Web, c'est-à-dire un ensemble de librairies assemblées de manière à faciliter le développement d'applications Web. En ce sens, il est assez aisé de construire un CMS simple avec Symfony, même si de base aucune fonctionnalité de ce type n'existe dans le framework.

Pourquoi choisir un framework comme Symfony ?

La création d'un weblog n'est sans doute pas le plus grand problème auquel on a à faire face sur le Web. Différentes solutions existent, de la simple création d'un compte sur une plateforme de blog, à l'utilisation d'un des nombreux logiciels de blog à installer sur son espace Web, comme par exemple Dotclear ou Wordpress. Ceci dit, il me semble que la création d'un espace numérique personnel devrait nécessiter plus d'attention : si l'on décide de se doter d'une mémoire numérique, d'un carnet Web, c'est bien pour exprimer de manière pérenne ses idées, et pouvoir les relire 3, 5, 10 ou 20 ans plus tard. En ce sens, maitriser la manière dont fonctionne son outil de publication comporte de vrais enjeux, surtout s'il est aussi simple à mettre en œuvre qu'avec Symfony.

Le choix d'un framework pour ses développements Web est donc un choix tout à fait justifié. Il existe différents frameworks - Cake PHP, Code Igniter, Ruby on Rails, Django pour ne citer que les plus connus et dynamiques du monde Open-Source. Il s'agit, au final, d'une question de choix personnel, de préférences, et pour bien choisir il faut avoir utilisé et testé plusieurs frameworks. Considérez-donc que ce tutoriel vous permettra de vous faire une idée plus précise de ce que vous permet de faire Symfony, et comment vous pouvez y parvenir.

Installer Symfony

Ce paragraphe aurait pû avoir pour titre "coiffé sur le poteau", mon cher collègue papa NiKo m'ayant devancé de quelques jours avec son guide d'installation de Symfony, auquel vous pourrez vous reporter si les explications ci-dessous ne vous suffisent pas.

Installation de PHP5 et Apache2

Comme cela a été expliqué en introduction, Symfony profite des avancées apportées par PHP5 en terme de programmation objet; il est donc nécessaire d'installer sur sa machine. Avant cela, il faut activer certains dépôts de logiciels, notamment pour pouvoir profiter de phpMyAdmin. Dans le fichier /etc/apt/sources.list, décommentez les lignes :

deb http://fr.archive.ubuntu.com/ubuntu/ dapper universe
deb-src http://fr.archive.ubuntu.com/ubuntu/ dapper universe

Ceci fait, on peut procéder à l'installation des outils nécessaires :

$ sudo apt-get update
$ sudo apt-get dist-upgrade
$ sudo apt-get install php5 php5-cli php5-mysql mysql-client mysql-server phpmyadmin

Si apt fait bien son travail, les dépendances nécessaires devraient également être automatiquement installées. Il est cependant de donner un accés à phpmyadmin, dont les sources ont uniquement été déposées sur votre serveur. Concrètement, nous allons créer un Virtualhost pour phpmyadmin, puis configurer l'accès au serveur MySQL. Dans la console, tapez :

$ sudo gedit /etc/apache2/sites-available/phpmyadmin

collez dans ce fichier les lignes suivantes :

NameVirtualHost 127.0.0.1:80
<VirtualHost phpmyadmin:80>
  ServerName phpmyadmin
  ServerAdmin webmaster@phpmyadmin
  DocumentRoot /usr/share/phpmyadmin

  <Directory /usr/share/phpmyadmin>
    Options Indexes FollowSymLinks MultiViews
    AllowOverride All
    Order allow,deny
    allow from all
  </Directory>

  ErrorLog /var/log/apache2/phpmyadmin.log
  CustomLog /var/log/apache2/phpmyadmin.log combined

  # Possible values include: debug, info, notice, warn, error, crit,
  # alert, emerg.
  LogLevel error
  ServerSignature On
</VirtualHost>

Il faut également ajouter le nom de domaine "phpmyadmin" à votre fichier /etc/hosts, qui devrait commencer par quelque chose comme :

127.0.0.1 localhost.localdomain localhost phpmyadmin

Cela permet d'indiquer à votre machine que le nom de domaine "phpmyadmin" ne doit pas faire l'objet d'une requête dns, et que la machine vers laquel il pointe est votre propre serveur.

Activez le nouveau Virtualhost en utilisant $ sudo a2ensite phpmyadmin, puis rechargez Apache 2 : $ sudo /etc/init.d/apache2 reload. Rendez-vous à l'adresse http://phpmyadmin/ dans votre navigateur Web favori, vous avez normalement accès à l'écran d'authentification de phpmyadmin.

capture de l'écran d'authentification de phpmyadmin

Par défaut, le seul utilisateur est "root", et son mot de passe est vide. Créez une base de données, par exemple nommée "symfony", avec comme interclassement "utf8_general_ci". Revenez ensuite à l'écran d'accueil de phpmyadmin, puis créez un nouvel utilisateur en cliquant sur "privilèges", puis "créer un nouvel utilisateur". Nommons par exemple cet utilisateur "symfony_user", et donnons-lui pour mot de passe "symfony_password". Cet utilisateur doit uniquement pouvoir se connecter depuis la machine locale, et ne dispose d'aucun droit général. Nous allons uniquement lui affecter les droits MySQL "SELECT", "INSERT", "UPDATE", "DELETE", "ALTER" et "DROP" pour la base "symfony" récemment créée. Lorsque ceci est fait, nous sommes prêts à travailler avec Symfony !

Installation de Pear et de Symfony

Symfony est disponible sous forme d'archive, mais la manière la plus simple est d'obtenir Symfony depuis son canal PEAR. L'installation est parfaitement décrite sur la page correspondante de la documentation de Symfony; voici les différentes étapes pour les utilisateurs de Debian (ou Ubuntu) :

  • installation de PEAR :
    $ sudo apt-get install php-pear
  • installation de Symfony et de Phing
    $ sudo pear channel-discover pear.symfony-project.com
    $ sudo pear install symfony/symfony
    $ sudo pear install --alldeps http://phing.info/pear/phing-current.tgz

Il y a de fortes chances que l'installation du paquet symfony échoue; à vrai dire, c'est même certain : il est nécessaire d'augmenter le niveau maximal de mémoire vive utilisée par le client PHP. Cela se fait dans le fichier /etc/php5/cli/php.ini; soyons larges, remplaçons les 8 Mo par défaut par 32 Mo :

memory_limit = 32M

Tant qu'on en est à modifier les fichiers de configuration de PHP, il est nécessaire de désactiver les magic quotes pour que Symfony fonctionne; ce n'est pas le même fichier de configuration que précédemment, cette fois ci cela concerne les instances de PHP appelées par Apache, et c'est donc dans le fichier /etc/php5/apache2/php.ini que cela se passe :

magic_quotes_gpc = Off

Création d'un projet Symfony

Symfony est installé, le binaire symfony est donc disponible en ligne de commande. Pour voir toutes les options disponibles, tapez simplement $ symfony -T. Vous découvrirez alors qu'un projet se crée en appelant $ symfony init-project MonProjet. Tapez cette commande dans un dossier de votre home, par exemple /home/VotreLogin/MonProjet, cela créera un projet vide nommé "MonProjet". Dans la philosophie de Symfony, un projet est un site Web complet, incluant à la fois front-office (partie "visible" du site) et back-office (la partie d'administration du site) : vous n'avez donc pas à créer plusieurs projets pour différentes parties d'un même site, mais vous devez plutôt créer différents applications (par exemple, pour la partie visible de notre blog, $ symfony init-app front). La structure de dossier du projet devrait alors ressembler à celle-ci :

drwxr-xr-x 12 xavier xavier 4096 2006-06-15 15:09 ./
drwxr-xr-x 15 xavier xavier 4096 2006-06-15 15:08 ../
drwxrwxrwx  2 xavier xavier 4096 2006-06-15 15:09 apps/
drwxr-xr-x  2 xavier xavier 4096 2006-06-15 15:09 batch/
drwxrwxrwx  2 xavier xavier 4096 2006-06-15 15:09 cache/
drwxr-xr-x  2 xavier xavier 4096 2006-06-15 15:09 config/
drwxr-xr-x  5 xavier xavier 4096 2006-06-15 15:09 data/
drwxr-xr-x  2 xavier xavier 4096 2006-06-15 15:09 doc/
drwxr-xr-x  4 xavier xavier 4096 2006-06-15 15:09 lib/
drwxr-xr-x  2 xavier xavier 4096 2006-06-15 15:09 log/
-rw-r--r--  1 xavier xavier    0 2006-06-15 15:09 SYMFONY
drwxr-xr-x  2 xavier xavier 4096 2006-06-15 15:09 test/
drwxr-xr-x  6 xavier xavier 4096 2006-06-15 15:09 web/

Activation d'un VirtualHost

Les bases du code de votre projet ont été générées, observons donc le résultat dans un navigateur Web. Créez un VirtualHost pour le projet, par exemple nommé "monProjetSymfony" :

$ sudo gedit /etc/apache2/sites-available/monProjetSymfony

collez dans ce fichier les lignes suivantes (pensez à remplacer "VotreLogin" par votre login) :

<VirtualHost monProjetSymfony:80>
  ServerName monProjetSymfony
  ServerAdmin webmaster@monProjetSymfony
  DocumentRoot /home/VotreLogin/MonProjet/web

  <Directory /home/VotreLogin/MonProjet/web>
    Options Indexes FollowSymLinks MultiViews
    AllowOverride All
    Order allow,deny
    allow from all
  </Directory>

  Alias /sf /usr/share/php/data/symfony/web/sf
  ErrorLog /var/log/apache2/monProjetSymfony.log
  CustomLog /var/log/apache2/monProjetSymfony.log combined

  # Possible values include: debug, info, notice, warn, error, crit,
  # alert, emerg.
  LogLevel error
  ServerSignature On
</VirtualHost>

Comme pour le nom de domaine "phpmyadmin" ajouté tout à l'heure dans le fichier /etc/hosts, ajoutons y maintenant "monProjetSymfony" :

127.0.0.1 localhost.localdomain localhost phpmyadmin monProjetSymfony

Activez le nouveau Virtualhost en utilisant $ sudo a2ensite monProjetSymfony, puis rechargez Apache 2 : $ sudo /etc/init.d/apache2 reload. Rendez-vous à l'adresse http://monProjetSymfony/ dans votre navigateur Web favori : alléluia !

capture d'une installation basique de Symfony

Créer votre structure de données

Différentes approches possibles

Les données de notre blog seront enregistrées dans une base de données MySQL. Un autre choix aurait pu être effectué, Propel proposant des interfaces vers différents types de bases de données (MySQL, MSSQL, Oracle, PostgreSQL, Sybase, SQLite, etc.). On pourrait même faire le choix de stocker les données directement dans des fichiers XML (RDF par exemple), en utilisant RAP.

Pour modéliser les structures de données que l'on emploie, plusieurs démarches peuvent être adoptées. Voici les deux principales :

  • Création des tables directement avec PHPMyAdmin ou un autre éditeur de base de données, génération d'un fichier de Schéma XML, puis génération des classes du modèle.
  • Modélisation de la structure avec un outil de modélisation, comme par exemple DBDesigner ou le plugin Azzuri Clay pour Eclipse, puis génération d'un fichier de Schéma XML, insertion dans la base de données et finalement génération des classes du modèle.

Même si la création de taches Symfony permet d'automatiser le processus, cela dépasse le cadre de ce tutoriel, et nous nous contenterons donc de la première alternative.

Création des tables

Vous pouvez utiliser PHPMyAdmin ou un autre outil comparable pour créer votre base de données; ce qui suit est la structure de données minimaliste pour notre blog :

CREATE TABLE `category` (
`id_category` int(2) NOT NULL auto_increment,
`name` varchar(255) default NULL,
`stripped_name` varchar(255) default NULL,
`description` text,
`enabled` tinyint(1) NOT NULL default '1',
PRIMARY KEY  (`id_category`),
UNIQUE KEY `stripped_name` (`stripped_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Categories list' AUTO_INCREMENT=1;

CREATE TABLE `post` (
`id_post` int(4) NOT NULL auto_increment,
`date` datetime NOT NULL default '1970-01-01 00:00:00',
`title` varchar(255) default NULL,
`stripped_title` varchar(255) default NULL,
`text` text,
`id_category` int(2) NOT NULL default '0',
`language` char(2) default NULL,
`enabled` tinyint(1) NOT NULL default '1',
PRIMARY KEY  (`id_post`),
KEY `id_category` (`id_category`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Post list' AUTO_INCREMENT=1;

ALTER TABLE `post`
ADD CONSTRAINT `post_ibfk_1` FOREIGN KEY (`id_category`) REFERENCES `category` (`id_category`);

Le moteur de stockage choisi est InnoDB, afin de profiter de sa capacité à gérer les clés étrangères. La structure ainsi choisie nous permet de créer des "posts", et d'attacher chacun d'entre eux à une catégorie. Les champs "enabled" permettent d'indiquer si le post ou la catégorie doivent être visibles ou non. On voit donc clairement que les objectifs affichés par le système sont relativement modestes : on ne parle pas ici de gestion multi-utilisateurs, on ne parle pas du support des tags, de syntaxe wiki ou d'autres jolies options que proposent les logiciels comme Dotclear ou Wordpress.

Paramétrage de Symfony pour l'utilisation de votre base de données

Il est nécessaire d'indiquer à votre projet à quel endroit se trouvent vos données. Pour cela, éditez le fichier de configuration /config/databases.yml :

all:
propel:
class:          sfPropelDatabase
param:
dsn:          mysql://symfony_user:symfony_password@localhost/symfony

Éditez également le fichier de configuration propre à Propel, et modifiez-en les premières lignes :

propel.targetPackage       = model
propel.project             = MonProjet
propel.database            = mysql
propel.mysql.tableType     = InnoDB
propel.database.createUrl  = mysql://localhost/
propel.database.url        = mysql://symfony_user:symfony_password@localhost/symfony

Génération des classes métier

Une des fonctionnalités intéressantes de Symfony, liée à l'utilisation de Propel, concerne la génération automatique de classes d'accès aux structures de données. Cette génération se fait en deux étapes :

  1. la création d'un fichier de schéma de base de données, par le biais de la commande $ symfony propel-build-schema. Un fichier /config/schema.xml est créé, il s'agit d'une représentation de la structure de la base de données sous forme XML. Ce type de fichier est directement exploitable par plusieurs applications, dont naturellement tous les outils de la sphère XML.
  2. A partir de ce fichier, Symfony peut générer les classes du modèle de données, cela se fait en tapant dans la console $ symfony propel-build-model

Normalement, si tout s'est bien passé, un dossier /lib/model est alors créé : il contient différentes classes qui "collent" parfaitement au modèle de données choisi.

Développement du blog

Le projet de blog va contenir deux applications séparées : un front office, visible par les visiteurs, et un back-office, réservé à l'adminstrateur du blog. Le code spécifique au blog sera localisé dans une module bien défini de l'application front, ce qui permettra plus tard d'étendre le site en créant d'autres modules (un module "gallery" pour gérer des galeries d'images, par exemple). La création de ces différents éléments se fait, encore une fois, par le biais de la ligne de commande, sachant que nous avons déjà créé l'application "front" :

$ symfony init-module front blog
$ symfony init-app back

Création d'une interface d'administration minimaliste

Les structures de données du blog sont en place, il faut maintenant pouvoir alimenter le blog. Nous allons utiliser les capacité de Symfony à générer des interfaces d'administration adaptées aux opérations récurrentes, toujours en ligne de commande :

$ symfony propel-init-admin back post Post
$ symfony propel-init-admin back category Category

Ces deux lignes permettent de générer, dans l'application back, deux modules dédiés à l'administration des posts et des catégories. Oh miracle, il suffit alors d'aller voir à l'adresse http://monProjetSymfony/back.php/category et on peu administrer les catégories du blog. Sur http://monProjetSymfony/back.php/post, ce sont les posts qui peuvent être écrits.

L'interface d'administration minimaliste est écrite; elle est certes spartiate, mais est très personnalisable [1] et permet de toute façon d'effectuer les opérations de base. Vous souhaiterez sans doute protéger ces pages par un mot de passe : il faudra alors vous pencher sur le chapitre "credentials" de la documentation.

Insérer des données dans le blog

Créez une catégorie puis un post attaché à cette catégorie. Alternativement, si vous n'avez pas généré le back-office, vous pouvez insérer les données suivantes dans votre base de données, par exemple en employant phpMyAdmin :


-- insertion de catégories
INSERT INTO `category` (`id_category`, `name`, `stripped_name`, `description`, `enabled`) VALUES ('1', 'Humeurs', 'Humeurs', 'Mes différentes pensées', 1);
INSERT INTO `category` (`id_category`, `name`, `stripped_name`, `description`, `enabled`) VALUES ('2', 'Cuisine', 'Cuisine', 'Mes meilleures recettes de cuisine', 1);

-- insertion des posts
INSERT INTO `post` VALUES (1, '2005-06-27 21:10:03', 'Mon premier post', 'mon-premier-post', '<p>Ceci est mon premier post fait avec Symfony, c\'est fantastique !</p>', 1, 'fr', 1);
INSERT INTO `post` VALUES (2, '2005-06-27 21:30:24', 'Recette des doubidchous de Sophia', 'recette-des-doubidchous-de-sophia', '<p>Les doubidchous de Sophia sont une grande spécialité culinaire, dont la préparation nécessite une grande préparation et beaucoup de soin.</p>', 2, 'fr', 1);

Module public de blog

Choix des url à utiliser : le routage

Établissons maintenant les règles de routage de l'application front, qui vont définir l'association entre les url demandées par l'utilisateur et les actions qui leur sont associées. Ceci se fait dans le fichier /apps/front/config/routing.yml. Remplacez son contenu par les quelques règles suivantes :

homepage:
url:   /
  param: { module: blog, action: list }

blog:
  url:   /blog
  param: { module: blog, action: list }

blog_annee:
  url:   /blog/:annee
  param: { module: blog, action: list }
  requirements: { annee: ^\d{4}$ }

blog_annee_mois:
  url:   /blog/:annee/:mois
  param: { module: blog, action: list }
  requirements: { annee: ^\d{4}$, mois: ^\d\d$ }

blog_annee_mois_jour:
  url:   /blog/:annee/:mois/:jour
  param: { module: blog, action: list }
  requirements: { annee: ^\d{4}$, mois: ^\d\d$, jour: ^\d\d$ }

blog_post:
  url:   /blog/:annee/:mois/:jour/:post_title.html
  param: { module: blog, action: view }
  requirements: { annee: ^\d{4}$, mois: ^\d\d$, jour: ^\d\d$ }

blog_langue:
  url:   /blog/:langue
  param: { module: blog, action: list }
  requirements: { langue: ^[a-z]{2}$ }

blog_categorie:
  url:   /blog/:categorie
  param: { module: blog, action: list }

#default rule
default:
  url:   /:module/:action/*

Chacune de ces règles porte un titre qui permet de l'identifier dans Symfony; on pourra voir la liste de tous les billets, ainsi que la liste pour une année, un mois et un jour donné. Il sera également possible d'accèder directement à un post par une url unique (règle "blog_post"). Les règles de routage blog_langue et blog_categorie permettent de lister les billets dans une langue donnée, ou appartenant à une catégorie donnée.

Certaines règles comportent des "requirements", c'est-à-dire des conditions nécesaires sur les éléments composant la règle pour que celle ci soit choisie par Symfony au moment du routage. Par exemple, dans la règle blog_annee, le paramètre annee doit être une succession de 4 chiffres, sans quoi cette règle ne sera pas utilisée par Symfony. Vous pouvez lire les différentes finesses du routage dans Symfony dans le chapitre correspondant de la documentation du framework.

Création des actions correspondantes

Les règles de routage précisent que deux actions sont possibles dans le module "blog" : une action "list", et une action "view". Pour chaque action, il faut écrire le code métier de l'action, ainsi que le template associé à cet action, dont le rôle est de mettre en forme pour affichage les données préparées dans le code de l'action.

Ajoutez le code suivant dans /apps/front/modules/blog/actions/actions.class.php, en dessous de l'action "index" :

/**
* Executes list action
*
*/
public function executeList()
{
  $c = new Criteria();
  $c->add(PostPeer::ENABLED, true);

  $annee = $this->getRequestparameter('annee');
  if ( $annee )
  {
    $c->add(PostPeer::DATE, $annee.'%', Criteria::LIKE);
  }

  $mois = $this->getRequestparameter('mois');
  if ( $mois )
  {
    $c->add(PostPeer::DATE, $annee.'-'.$mois.'%', Criteria::LIKE);
  }

  $jour = $this->getRequestparameter('jour');
  if ( $jour )
  {
    $c->add(PostPeer::DATE, $annee.'-'.$mois.'-'.$jour.'%', Criteria::LIKE);
  }

  $categorie = $this->getRequestparameter('categorie');
  if ( $categorie )
  {
    $c->add(CategoryPeer::STRIPPED_NAME, $categorie);
  }

  $language = $this->getRequestparameter('langue');
  if ( $language )
  {
    $c->add(PostPeer::LANGUAGE, $language);
  }

  $post = $this->getRequestparameter('post');
  if ( $post )
  {
    $c->add(PostPeer::STRIPPED_TITLE, $post);
  }

  $c->addDescendingOrderByColumn(PostPeer::DATE);
  $this->posts = PostPeer::doSelectJoinCategory($c);
  $this->setTitle('Mon blog - Liste des articles');
}

/**
* Executes view action
*/
public function executeView()
{
  $this->executeList();

  $this->setTitle('Mon Blog - '.$this->posts[0]->getTitle());
}
Écriture des templates

Créons ensuite deux fichiers de template dans le dossier /apps/front/modules/blog/templates. C'est dans les templates que doit être écrit le code HTML envoyé vers le navigateur : les templates sont donc responsables du rendu graphique des informations traitées par les actions :

  • le premier est nommé listSuccess.php :
    <?php use_helper('Date') ?>
    <?php foreach ( $posts as $post ): ?>
      <h2 id="post-<?php echo $post->getIdPost() ?>">
        <?php echo link_to($post->getTitle(),
        '@blog_post?annee='.format_date($post->getDate(), 'yyyy')
        .'&mois='.format_date($post->getDate(), 'MM')
        .'&jour='.format_date($post->getDate(), 'dd')
        .'&post_title='.$post->getStrippedTitle()) ?>
      </h2>
      <p class="post-info">
        publié <?php echo format_date($post->getDate(),
        'dddd dd MMMM yyyy à HH:mm',
        'fr') ?>
        dans la catégorie <?php echo link_to($post->getCategory()->getName(),
        '@blog_categorie?categorie='.$post->getCategory()->getStrippedName()) ?>
      </p>
      <?php $language = ( $post->getLanguage() != "" ) ? " lang=\"".$post->getLanguage()."\"" : ""; ?>
      <div class="post-content"<?php echo $language ?>>
        <?php echo $post->getText() ?>
      </div>
    
    <?php endforeach; ?>
  • le deuxième, nommé viewSuccess.php :
    <?php use_helper('Date') ?>
    <?php if ( isset($posts[0]) ): ?>
      <?php $post = $posts[0] ?>
      <h2 id="post-<?php echo $post->getIdPost() ?>">
        <?php echo link_to($post->getTitle(),
        '@blog_post?annee='.format_date($post->getDate(), 'yyyy')
        .'&mois='.format_date($post->getDate(), 'MM')
        .'&jour='.format_date($post->getDate(), 'dd')
        .'&post_title='.$post->getStrippedTitle()) ?>
      </h2>
      <p class="post-info">
        publié <?php echo format_date($post->getDate(),
        'dddd dd MMMM yyyy à HH:mm',
        'fr') ?>
        dans la catégorie <?php echo link_to($post->getCategory()->getName(),
        '@blog_categorie?categorie='.$post->getCategory()->getStrippedName()) ?>
      </p>
      <?php $language = ( $post->getLanguage() != "" ) ? " lang=\"".$post->getLanguage()."\"" : ""; ?>
      <div class="post-content"<?php echo $language ?>>
        <?php echo $post->getText() ?>
      </div>
    
    <?php else: ?>
      <p>
        Cette entrée n'a pu être trouvée dans le blog.
      </p>
    <?php endif; ?>

Rendez-vous à l'adresse http://monProjetSymfony/index.php/blog : la liste de vos articles s'affiche, c'est merveilleux. Il ne reste plus qu'à effectuer les réglages finaux du framework pour que le module de blog soit le module appelé par défaut.

Réglages finaux du framework

Symfony propose de nombreuses possibilités de réglages, permettant d'adapter le comportement du framework aux besoins du projet. La plupart de ces réglages s'effectuent dans des fichiers écrits en YAML [2]. Les réglages basiques que vous pouvez effectuer se trouvent dans :

  • le fichier /apps/front/config/view.yml, qui permet de régler les paramètres liés à la vue, comme par exemple les méta-tags associés aux différentes pages.
  • le fichier /apps/front/config/settings.yml, qui permet de définir les réglages principaux du framework. Afin, par exemple, d'indiquer quelle est l'action par défaut, vous pouvez écrire :
    all:
      .actions:
        default_module:         blog
        default_action:         list

Une fois vos paramètres modifiés, n'oubliez pas de vider le cache de configuration du projet, en tapant la commande symfony cc ou symfony clear-cache. Si vous avez effectué les modifications, votre liste de messages devrait désormais s'afficher à l'adresse http://monProjetSymfony/. Afin de ne plus voir le "index.php" dans l'url, vous devez activer le mod-rewrite d'Apache :

$ sudo a2enmod rewrite
$ sudo /etc/init.d/apache2 force-reload

Le système de paramétrage de Symfony est assez bien conçu : il est ainsi possible, par exemple, de placer certains fichiers de configuration directement au sein d'un module, de sorte qu'ils ne s'appliquent que pour ce module donné. Pour plus d'informations, vous pouvez consulter le chapitre de la documentation consacré à la configuration.

le blog réalisé avec symfony, une fois les règles de routage mises en place

Mise en place des fils RSS

Une fonctionnalité essentielle des blogs est la mise à dispositon de fils RSS, qui permettent aux lecteurs de s'abonner "on demand". Symfony propose un plugin à ajouter à l'installation de base, qui permet de générer avec peu d'efforts des fils RSS.

Commencez par installer le plugin. Pour cela, à la racine de votre projet, écrivez dans la console $ symfony plugin-install local symfony/sfFeed. Si tout se passe bien, le plugin est ajouté dans /lib/plugins/symfony/plugins/

Tout comme tout autre page issue du blog, le fil RSS va se décomposer en une action et un template. Le template est très simple : créez le fichier /apps/front/modules/blog/templates/syndicationSuccess.php, et placez-y :

<?php echo $feed->getFeed() ?>

Le code de l'action correspondante, à ajouter à /apps/front/modules/blog/actions/actions.php, est lui aussi assez concis :

/**
* Executes syndication action
*/
public function executeSyndication()
{
  $type = $this->getRequestparameter('type');

  if ( $type == 'atom' )
  {
    $type = 'atom1';
  }
  else
  {
    $type = 'rss201rev2';
  }

  $feed = sfFeed::newInstance($type);
  $feed->setTitle('Mon fil RSS');
  $feed->setLink('http://monProjetSymfony/');
  $feed->setAuthorEmail('gerard@lambert.com');
  $feed->setAuthorName('Gérard Lambert');

  $c = new Criteria();
  $c->add(PostPeer::ENABLED, true);
  $c->setLimit(15);
  $c->addDescendingOrderByColumn(PostPeer::DATE);
  $this->posts = PostPeer::doSelectJoinCategory($c);

  foreach ( $this->posts as $post )
  {
    $item = array(
    'title'       => $post->getTitle(),
    'link'        => '@blog_post?annee='.format_date($post->getDate(), 'yyyy')
    .'&mois='.format_date($post->getDate(), 'MM')
    .'&jour='.format_date($post->getDate(), 'dd')
    .'&post_title='.$post->getStrippedTitle(),
    'authorName'  => 'Gérard Lambert',
    'authorEmail' => 'gerard@lambert.com',
    'pubdate'     => $post->getDate(),
    'uniqueId'    => $this->getController()->genURL(
    '@blog_post?annee='.format_date($post->getDate(), 'yyyy')
    .'&mois='.format_date($post->getDate(), 'MM')
    .'&jour='.format_date($post->getDate(), 'dd')
    .'&post_title='.$post->getStrippedTitle(),
    true),
    'description' => $post->getText(),
    );

    $feed->addItemFromArray($item);
  }

  $this->feed = $feed;
}

Cette portion de code fait appel au helper "Date", qu'il faut inclure tout en haut du fichier :

require_once('symfony/helper/DateHelper.php');

Il ne reste plus qu'à ajouter les routes correspondant aux fils de syndication RSS et Atom dans le fichier /apps/front/config/routing.yml, juste avant la route par défaut ("default rule")...

syndication_blog_rss:
  url:   /syndication/blog.rss
  param: { module: blog, action: syndication, type: rss }

syndication_blog_atom:
  url:   /syndication/blog.atom
  param: { module: blog, action: syndication, type: atom }

... vider le cache de configuration ("symfony cc"), et enfin préciser les paramètres de la vue pour les fils de syndication dans le fichier /apps/front/modules/blog/config/view.yml :

syndicationSuccess:
  has_layout: off
  http_metas:
  content-type: text/xml

En théorie, un fil rss devrait être disponible à l'adresse http://monProjetSymfony/syndication/blog.rss, et un fil atom à l'adresse http://monProjetSymfony/syndication/blog.atom

Conclusion

Votre blog est maintenant accessible à l'url http://monProjetSymfony/. Evidemment, son look est encore assez spartiate et il reste du travail d'intégration pour le rendre plus agréables à consulter; mais on a vu qu'avec peu d'efforts, il est possible de créer un projet de site Web struturé et extensible. La nécessité de disposer d'une base de données est sans doute une faiblesse, mais il est possible d'employer d'autres moyens pour stocker les données; nous verrons dans un autre chapitre comment mettre en œuvre RAP - RDF API for PHP pour utiliser des fichiers RDF comme moyen de stockage.

En attendant, bonne découverte de Symfony ! En vous penchant plus sur le framework, vous irez de bonne surprise en bonne surprise. Ce tutoriel n'a parlé ni de cache, ni de composants, ni d'internationalisation, et encore moins d'AJAX : autant de choses que Symfony fait très bien, et qu'il vous reste à découvrir !

Notes :

  • written on: 2006-06-26