Générer un flux RSS avec CakePHP
Proposer un flux RSS est devenu une fonctionnalité incontournable sur la plupart des sites, et CakePHP simplifie grandement le processus de création de flux.
Partons d’un blog publiant des articles. Nous souhaitons créer un flux des articles récents, à la norme RSS version 2.0 et disponible via l’URL suivante : /articles/flux.rss.
1. Prise en compte de l’extension .rss dans le Router
Nous commençons par configurer le Router pour qu’il reconnaisse l’extension .rss. Nous ajoutons la route suivante dans le fichier{app}/config/routes.php :
1 2 | // {app}/config/routes.php Router::parseExtensions('rss'); |
Ainsi, CakePHP reconnaîtra les URL terminant par ‘.rss’ et appellera la bonne action.
2. Le Contrôleur
Nous allons maintenant créer l’actionflux dans le Contrôleur des articles. Cette action récupère simplement la liste des 10 articles les plus récents classés par ordre de date de création décroissante.
Mise à jour du 12/04/08 : nous devons également configurer les informations générales qui seront affichées dans l’entête du flux (titre, description, langue, email du webmaster, etc.). Merci à foxmask qui a décelé que la déclaration de ces informations dans la Vue plutôt que dans le Contrôleur déclenchait la duplication de la balise <description>.
Pour en savoir plus sur les balises disponibles dans la norme RSS, nous renvoyons le lecteur vers cet article complet et clair : Spécifications du format RSS.
Nous commençons par inclure le composant RequestHandler, qui en complément de la configuration du Router vue plus haut, va permettre d’appeler l’action flux lorsque l’url /articles/flux.rss est demandée. C’est ce composant qui va changer automatiquement le layout par défaut pour permettre la sortie du flux au format défini par l’extension requise (rss, xml, etc.).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | // {app}/controllers/articles_controller.php class ArticlesController extends AppController { var $components = array('RequestHandler'); function flux() { $articles = $this->Article->find( 'all', array( 'order' => 'created DESC', 'limit' => 10 ) ); $channel = array( 'title' => utf8_encode("Mon flux RSS"), 'description' => utf8_encode("Les derniers articles"), 'language' => 'fr', 'webMaster' => 'contact@monsite.com' ); $this->set(compact('articles', 'channel')); } } |
3. La Vue
Nous créons un nouveau fichier {app}/views/articles/rss/flux.ctp (notez le sous-répertoire rss dans le répertoire articles) :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | // {app}/views/articles/rss/flux.ctp
<?php
e($rss->items($articles, 'sortieRSS'));
function sortieRSS($article)
{
return array(
'title' => utf8_encode($article['Article']['titre']),
'link' => 'http://www.monsite.com/articles/view/'.$article['Article']['id'],
'description' => utf8_encode($article['Article']['description']),
'pubDate' => $article['Article']['created']
);
}
?> |
Quelques explications :
3 | e($rss->items($articles, 'sortieRSS')); |
CakePHP a créé automatiquement un objet $rss, duquel nous appelons la méthode items(). Cette dernière prend en premier paramètre un tableau de données, ici les 10 articles trouvés dans l’action flux, et en deuxième paramètre le nom d’une fonction que nous construisons juste après, sortieRSS, qui sera appliquée sur chaque élément du tableau $articles.
5 6 7 8 9 10 11 12 13 | function sortieRSS($article) { return array( 'title' => utf8_encode($article['Article']['titre']), 'link' => 'http://www.monsite.com/articles/view/'.$article['Article']['id'], 'description' => utf8_encode($article['Article']['description']), 'pubDate' => $article['Article']['created'] ); } |
Le rôle de cette fonction est de formater les données passées en paramètre avec les balises à la norme RSS.
Nous utilisons la fonction PHP utf8_encode pour rendre les caractères accentués lisibles par tous les agrégateurs de flux.
4. Liens vers le flux RSS
4.1 Dans l’entête HTML
La plupart des navigateurs récents peuvent détecter la présence d’un lien vers un flux RSS dans l’entête HTML d’une page et affichent une petite icône orange à droite de la barre d’adresse (comme nous le voyons sur ce site même). Nous établissons ce lien particulier dans notre layout général, quelque part entre les balises<head>...</head> :
1 2 | // {app}/views/layouts/default.ctp e($html->meta('rss', array('controller' => 'articles', 'action' => 'flux.rss'), array('title' => "Les derniers articles"))); |
4.2 Dans un lien classique
N’importe quel autre lien vers le flux se fera de la façon suivante :
e($html->link("Flux RSS des articles récents", array('controller' => 'articles', 'action' => 'flux.rss')));
Commentaires
24 avril 2008 à 13:50
Article très sympa !
Il faut penser à faire un petit Configure::write(‘debug’, 0); sinon l’affichage n’est pas correct en mode hors-production.
J’ai néenmoins un petit soucis : lorsque j’accède à mon flux, firefox me propose de le télécharger au lieu de l’afficher. Les données à l’intérieur sont correctes. Je suppose que c’est un problème de type mime ! Mais mêmeen faisant echo $rss->header(); dans la vue, ca ne fonctionne pas …
une idée ?
merci !
24 avril 2008 à 15:19
Que contient le fichier que Firefox te propose de télécharger ? A première vue je penserai à un problème de layout, celui par défaut étant utilisé à la place du layout xml. As-tu bien ajouté
Router::parseExtensions('rss');dans les routes ? As-tu bien inclu le composant RequestHandler dans ton Contrôleur ?25 avril 2008 à 13:00
Le fichier téléchargé contient le flux correctement formaté :
Neveldo : Flux RSSLes derniers articlesfrcontact@neveldo.frhttp://localhost/blog/…
J’ai bien rajouté l’extension RSS dans les routes et le composant RequestHandler dans le contrôleur.
Je vais voir du côté de la configuration de WAMP5 et tester avec un flux écrit en dur et je te tiens au courant.
Merci !
26 avril 2008 à 12:02
Ok problème résolu. Cela venait d’un caractère espace qui s’était glissé après la balise ?> dans l’appController ! Il s’est retrouvé en début de fichier , avant la balise (et sur toutes les autres pages).
Par contre, comment fait-on pour accéder à une méthode d’un helper à l’intérieur de la fonction outputRSS() ?
En faisant directement un $html->XXX(), il ne trouve pas l’objet et renvoie un flux vide … Même résultat en ajoutant un « global $html; ».
Une idée ?
merci !
26 avril 2008 à 12:43
Je suppose que tu voudrais utiliser les fonctions $html->link() ou $html->url()… Si tu passes un array à ‘link’, Cake se charge de le passer dans Router::url(), inutile d’appeler une méthode du Helper Html. Exemple :
function sortieRSS($article) { return array( 'title' => ..., 'link' => array('controller' => 'articles', 'action' => 'view', $article['Article']['id']), ... ); }26 avril 2008 à 14:45
Merci pour ta réponse ! En effet, pour les liens je les bidouillais grâce aux variables globales de Cake, ta solution est bien plus propre
Par contre, j’ai bien un helper que j’ai fait et qui contient une fonction permettant de raccourcir mes posts en fonction d’une balise html bien spécifique. Ceci afin de peupler le champ description. Et donc, dans ce cas, impossible d’accéder à cette méthode du helper à l’intérieur de la méthode (de la même façon, impossible d’accéder aux helpers intégrés à cake).
26 avril 2008 à 20:55
Tu ne peux pas appeler une fonction de Helper dans la fonction de callback. Par contre rien ne t’empêche d’effectuer un traitement préalable sur tes données dans la vue avant de les passer à la fonction $rss->items().
Exemple en coupant les textes trop long avec le Helper Text :
// {app}/views/articles/rss/flux.ctp foreach($articles as $key => $article) { $articles[$key]['Article']['description'] = $text->truncate($article['Article']['description']); }e($rss->items($articles, 'sortieRSS')); ...
27 avril 2008 à 10:48
Ok merci !
Je pensais qu’il était possible de le faire directement dans la fonction de callback :p
merci pour l’info !
27 juin 2008 à 10:36
Bonjour,
Tout d’abord, merci pour cet article. Maintenant j’ai essayé de le reproduire sur mon site. Seulement voila j’ai bien la page de RSS qui s’affiche mais sans mes news dedans
Je dois faire (ou pas..) quelque chose en plus ou en moins.
Merci de votre aide.
27 juin 2008 à 11:38
C’est un peu léger comme description pour pouvoir vous aider. N’hésitez pas utiliser le service de partage de code de Cake pour y coller la partie qui coince. http://bin.cakephp.org/
27 juin 2008 à 15:54
Désolé… J’ai posté mon code ici => http://bin.cakephp.org/saved/34173
Je rappelle mon problème, j’affiche la page de RSS mais les news que je veut y afficher n’y sont pas. J’avais réussit à les afficher avec une autre fonction (http://bin.cakephp.org/saved/34175) dans la page RSS mais pas dans des lecteurs RSS eux même(google reader, yahoo, netvibes, feedreader ou autre). Je suis bloqué et je ne sais pas pourquoi j’ai suivit pas à pas l’article refait 15fois les manip’ mais rien n’y fait. Merci de votre aide et si je ne suis pas clair, dites le moi
1 février 2009 à 1:33
Salut, Je viens de tester ton tuto mais ça m’affiche pas comme ça devrait enfin je pense… Je l’ai fait en locale et ça m’affiche ça: Les derniers postsfrcontact@monsite.comhttp://localhost/debs-cake/http://localhost/debs-cake/posts/view/249llo9lolo9Sun, 01 Feb 2009 01:05:01 et ainsi de suite pour tous mes posts… Est-ce du faite que je sois en local avec WAMP ? Je pense avoir bien suivi le tuto.
Et merci pour tous ces bons tutos
Mon blog avance ä grands pas grâce à toi
Debs.
11 août 2009 à 3:35
Bonjour,
j’ai testé le tutoriel mais j’ai eu le même probleme que NEVELDO. En effet, firefox me propose de telecharger le flux au lieu de l’afficher. J’ai aussi bien verifié le requesthandler mais rien. Au fait le layout xml doit se trouvé dans cakephp? car chez moi dans /layout/rss/ il n’y a qu’un fichier nommé empty. Merci d’avance.
5 février 2010 à 11:14
Bien le bonjour,
Après avoir bataillé pendant 2h sur le même problème que lioninho, et après avoir écumé le net, j’ai résolu le-dit problème et je vous livre comment j’ai fait.
Il m’a suffit de jeté un coup d’oeil à mes helpers ( app/views/helpers ) et supprimer le caractère espace en trop qui se trouvait après ma balise fermante ‘ ?> ‘ C’est également valable, apparament, pour les espaces se trouvant avant les balises ouvrante ‘ <?php ‘.
En espérant que ça puisse servir à quelqu’un dans un futur proche…
Cort-X-
15 juin 2010 à 15:14
Salut !
Merci encore pour ce super tuto !
Je rencontre néanmoins un petit problème… J’aimerais pouvoir passer une variable à ma fonction flux, pour pouvoir choisir quels articles mettre dans mon flux rss.
J’ai donc un link qui ressemble à ça :
mais ça ne fonctionne pas car (je pense…) l’url ne termine plus par .rss donc il est perdu. Du coup j’ai voulu mettre une petite route, comme cela :
mais ça ne fonctionne toujours pas, j’ai une erreur : le controlleur ‘id’Controller n’existe pas… (ex : 7Controller…)
Si quelqu’un sait comment je dois faire pour pouvoir y passer un paramètre à ce flux, ce serait super !!
Merci beaucoup
20 janvier 2011 à 20:22
Merci, L’information est clair et précise comme toujours
12 octobre 2011 à 11:45
Je rejoins vraiment ce qu’a dit Cort-X- en parlant des espaces avant ou après les balises . J’ai cherché un bout avant de penser a vérifier les helpers déclarés dans mon appController. Il y avait un espace après une balise de fermeture php … Du coup mon fichier XML contenait un espace en début de page. Merci encore pour tous ces supers tutos !!!