Creare un Feed RSS in PHP e MySQL
Un Feed RSS è un modo semplice e comodo per venire informati sulla presenza di nuovi contenuti (ad esempio notizie) di un sito web senza dover periodicamente accedere al sito stesso.
E' sufficiente "abbonarsi" al feed del sito utilizzando l'apposito pulsante presente sul sito stesso.
Nelllo screenshot seguente, a titolo di esempio, vediamo i FeedRss della Gazzetta dello Sport. E' possibile rendere disponibili più feed sul proprio sito, ad esempio uno con tutte le notizie, ed uno per ogni sezione del sito.
Dopo essersi abbonati, possiamo consultare l'RSS utilizzando un programma dedicato a questo scopo (un "feed reader"). I programmi disponibili sono molti. Noi, ad esempio, utilizziamo il browser di Firefox: nella sua barra superiore (la barra dei segnalibri) saranno presenti gli RSS a cui ci siamo abbonati.
In questo tutorial vedrai come ottenere questo risultato e cioè creare un feed RSS utilizzando una pagina PHP e il supporto di un database MySQL.
Prima di realizzare il Feed Rss con le ultime notizie del nostro sito, vediamo come è strutturato un feed rss.
Struttura di un Feed Rss
Un Feed Rss non è altro che un file xml, che presenta una struttura simile a questa.
<?xml version='1.0' encoding='UTF-8'?>
<rss version='2.0'>
<channel>
<title>Il mio sito web</title>
<link>https://www.miosito.it</link>
<description>Blog di notizie tecnologiche</description>
<language>it-IT</language>
<item>
<title>Huawey P10, il nuovo smartphone in casa Huawey</title>
<link>https://www.miosito.it/news/recensione-huawei-p10</link>
<description>Recensione del nuovo smartphone Huawey P10</description>
<pubDate>Fri, 06 Apr 2018 12:30:00 +0200</pubDate>
</item>
<item>
<title>Il primo smartphone con intelligenza artificiale</title>
<link>https://www.miosito.it/news/migliore-smartphone-oggi-sul-mercato</link>
<description>Grazie al primo processore Kirin 970 con AI, HUAWEI Mate 10 Pro è in grado di capire e rispondere istantaneamente agli stimoli del mondo reale</description>
<pubDate>Thu, 05 Apr 2018 11:13:00 +0200</pubDate>
</item>
</channel>
</rss>
Vediamo nel dettaglio cosa abbiamo scritto in questo esempio.
Le prime righe rappresentano la dichiarazione che il nostro file è un file di tipo xml ed in particare un file RSS che apriamo e chiudiamo usando il tag <rss>.
<?xml version='1.0' encoding='UTF-8'?>
<rss version='2.0'>
........
</rss>
Il contenuto del nostro rss sarà racchiuso all'interno del marcatore <channel>
<channel>
........
</channel>
Il contenuto di <channel> inizia con alcune informazioni relative al nostro sito web: il titolo <title> del sito, il link al sito <link>, una sua breve descrizione <description> e la sua lingua <language>.
<title>Il mio sito web</title>
<link>https://www.miosito.it</link>
<description>Blog di notizie tecnologiche</description>
<language>it-IT</language>
Successivamente inizia la rassegna delle notizie.
Ogni notizia è racchiusa all'interno dei marcatori <item>, con il titolo della notizia <title>, il link alla notizia <link>, una breve descrizione della notizia <description> e la data della notizia <pubdate>
<item>
<title>Huawey P10, il nuovo smartphone in casa Huawey</title>
<link>https://www.miosito.it/news/recensione-huawei-p10</link>
<description>Recensione del nuovo smartphone Huawey P10</description>
<pubDate>Fri, 06 Apr 2018 12:30:00 +0200</pubDate>
</item>
E' evidente che, in presenza di un sito con un numero elevato di notizie, non possiamo creare a mano un file di questo tipo, ma dobbiamo fare in modo che venga generato dinamicamente prendendo le notizie da un database MySQL.
La tabella notizie in MySQL
Ipotizziamo che la tabella da cui attingere le notizie da inserire nel Feed si chiami "news" e i suoi campi principali (quelli che ci interessano per il Feed) siano:
- news_id : è l'id incrementale dei records (ad esempio "1456")
- news_idsez: è l'id della specifica sezione della notizia (ad esempio l'id 1 per la sezione "smartphone", 2 per "tablet", ...)
- news_datapub: la data di pubblicazione della notizia. è un datetime in formato "anno-mese-giorno ore:minuti:secondi" (ad esempio "2018-04-05 11:13:00")
- news_ titolo: il titolo della notizia codificato in UTF-8 (ad esempio "Il primo smartphone con intelligenza artificiale")
- news_testo: il testo della notizia codificato in UTF-8 (ad esempio "Grazie al primo processore Kirin 970 con AI, HUAWEI Mate 10 Pro è in grado di capire e rispondere istantaneamente agli stimoli del mondo reale......")
- news_url: la url della notizia (ad esempio "https://www.miosito.it/news/migliore-smartphone-oggi-sul-mercato")
Il file PHP per erogare il Feed RSS
Abbiamo quindi la tabella "news" da cui prelevare le notizie per creare dinamicamente il File Rss del nostro sito.
Per prima cosa creiamo un file php per la connessione al database mysql, e lo chiamiamo "connection.php"
<?php
$mysql_host = 'localhost'; //host
$mysql_username = 'root'; //username
$mysql_password = 'pippo'; //password
$mysql_database = 'test'; //db
$mysql_link = @mysqli_connect($mysql_host,$mysql_username,$mysql_password);
mysqli_select_db($mysql_link,$mysql_database);
mysqli_set_charset($mysql_link,'utf8');
?>
Creiamo anche un file "funzioni.php" dove andremo ad inserire la funzione "xmlentities", che utilizzeremo nella costruzione del feed, e serve ad evitare errori nell'xml che si potrebbero determinare con la presenza dei caratteri "&" e "<". Andiamo a convertire questi caratteri in entità html.
<?php
function xmlentities ($string) {
return str_replace(array('&', '<'), array('&', '<'), $string);
}
?>
Creiamo infine il file php preposto alla creazione del feed, a cui assegnamo comel nome "feedrss.php" e al suo interno come prima cosa includiamo la connessione al MySQL appena creata e la funzione.
Dopo la connessione, andiamo ad query sulla tabella news per estrarre le ultime 20 notizie di tutte le sezioni in ordine descrescente (dall'ultima creare alla più vecchia) che andranno a popolare il nostro feed. Creiamo una variabile $items al cui interno andremo ad inserire le news estratte, cioè gli "items" del Feed secondo lo schema visto ad inizio articolo.
<?php
include "connection.php";
include "funzioni.php";
$items="";
$query = "SELECT news_id,news_data,news_titolo,news_testo,news_url FROM news ORDER BY news_id DESC LIMIT 20";
$result = mysql_query($query, $mysql_link);
$rows = mysql_num_rows($result);
if($rows>0)
{
while($row = mysql_fetch_array($result))
{
$sintesi=substr($row['news_testo'],0,200)."...";
$items .="<item>";
$items .="<title><![CDATA[".xmlentities($row['news_titolo'])."]]></title>";
$items .="<description><![CDATA[".xmlentities($sintesi)."]]></description>";
$items .="<link>".$row['news_url']."</link>";
$items .="<pubDate>".date("D, d M Y H:i:s O",strtotime($row['news_data']))."</pubDate>";
$items .="</item>";
}
}
?>
Sofferiamo l'attenzione su 4 punti
- Come possiamo vedere, non abbiamo inserito tutto il testo della notizia, ma solo un estratto di 200 caratteri. Il feed infatti deve fornire solo un accenno alla norizia ed invogliare l'utente al click e quindi all'accesso alla pagina della notizia stessa.
- Alcuni caratteri speciali vanno rimpiazzati con le relative entità XML, per evitare errori nell'output. Per questo scopo abbiamo creato una funzione "xmlentities".
- Abbiamo utilizzato sia per il <title> che per le <description> il marcatore "CDATA", che si apre così "<![CDATA[" e si chiude così "]]". Questo marcatore ci consente di inserire dell'xml del codice HTML sia nel titolo che nella descrizione.
- La data che dobbiamo inserire nel feed deve aver questo formato "Fri, 06 Apr 2018 12:30:00 +0200". A tal fine convertiamo il datetime della notizia, ad esempio "2018-04-05 11:13:00", nel formato utile al nostro scopo.
Abbiamo così ottenuto la lista degli items. Non ci resta che inserire gli items all'interno della struttura completa del feed assemblando tutti i concetti visti poc'anzi.
<?php
include "connection.php";
include "funzioni.php";
$items="";
$query = "SELECT news_id,news_data,news_titolo,news_testo,news_url FROM news ORDER BY news_id DESC LIMIT 20";
$result = mysql_query($query, $mysql_link);
$rows = mysql_num_rows($result);
if($rows>0)
{
while($row = mysql_fetch_array($result))
{
$sintesi=substr($row['news_testo'],0,200)."...";
$items .="<item>";
$items .="<title><![CDATA[".xmlentities($row['news_titolo'])."]]></title>";
$items .="<description><![CDATA[".xmlentities($sintesi)."]]></description>";
$items .="<link>".$row['news_url']."</link>";
$items .="<pubDate>".date("D, d M Y H:i:s O",strtotime($row['news_data']))."</pubDate>";
$items .="</item>";
}
}
$toprint ='<?xml version="1.0" encoding="utf-8" ?>';
$toprint .="\n<rss version=\"2.0\" xmlns:dc=\"http://purl.org/dc/elements/1.1/\" xmlns:sy=\"http://purl.org/rss/1.0/modules/syndication/\" xmlns:admin=\"http://webns.net/mvcb/\" xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\" xmlns:content=\"http://purl.org/rss/1.0/modules/content/\">";
$toprint .="<channel>";
$toprint .="<title>Il mio sito web</title>";
$toprint .="<link>https://www.miosito.it</link>";
$toprint .="<description>Blog di notizie tecnologiche</description>";
$toprint .="<language>it-IT</language>";
$toprint .=$items;
$toprint .="</channel>";
$toprint .="</rss>";
header("Content-Type: text/xml; charset=utf-8");
print $toprint;
?>
Abbiamo creato un variabile $toprint che poi printerò a fondo pagina, con all'interno la struttura del feed e gli items ottenuti, cioè l'xml completo.
Nota: al fondo del file, poco prima del print del codice, abbiamo forzato l'invio di un header: stiamo dicendo al browser che il file da visualizzare è un xml encodato in utf-8
header("Content-Type: text/xml; charset=utf-8");
Il nostro lavoro è quasi ultimato. Ultimo accorgimento: il file si chiamo "feedrss.php"... ma quello che vogliamo ottenere è un file xml.
Nessun problema, ci viene in aiuto il file .htaccess. Utilizziamo un RewriteRule per fare in modo che, richiamando il file come feedrss.xml, si apra il file feedrss.php
RewriteEngine on
RewriteBase /
RewriteRule ^feedrss.xml$ feedrss.php [NC,L]
Il nostro lavoro è utlimato. Abbiamo creato un Feed Rss con tutte le ultime notizie del nostro sito.
Mettiamo on line il file, apriamo il nostro browser, ad esempio Firefox che dispone di un lettore RSS integrato, e proviamo ad aprirlo digitando: https://www.miosito.it/feedrss.xml
Il risultato è il seguente: ci viene richiesto di abbonarci al Feed. Accettiamo. Il feed apparirà nella barra superiore di Firefox, pronto per essere aperto ogni qualvolta vogliamo per visualizzare le ultime notizie del sito, senza accedere al sito stesso.
E se volessimo creare anche un feed per sezione? Nessun problema, con qualche accorgimento sul file .htaccess e sul file feedrss.php, senza creare altri files, possiamo ottenere questo risultato.
Ad esempio voglio creare un feed per la sezione "smarphone" (id sezione 1) ed uno per la sezione "tablet" (id sezione 2).
Modifichiamo il file .htaccess così
RewriteEngine on
RewriteBase /
RewriteRule ^rss-smartphone.xml$ feedrss.php?idsez=1 [NC,L]
RewriteRule ^rss-tablet.xml$ feedrss.php?idsez=2 [NC,L]
RewriteRule ^feedrss.xml$ feedrss.php [NC,L]
Al feed generico feedrss.xml abbimo aggiunto due nuovi feed: con il rewrite rule chiamiamo sempre il file feedrss.php ma in più viene aggiunto il parametro idsez con l'id della sezione richiesta, che quindi verrà ricevuto dal file feedrss.php in GET.
A questo punto modifichiamo la query del file php in questo modo:
if(empty($_GET['idsez'])) {
$query = "SELECT news_id,news_data,news_titolo,news_testo,news_url FROM news ORDER BY news_id DESC LIMIT 20";
}
else {
$query = "SELECT news_id,news_data,news_titolo,news_testo,news_url FROM news WHERE news_idsez=".$_GET['idsez']." ORDER BY news_id DESC LIMIT 20";
}
In poche parole se non viene ricevuto in GET il parametro idsez estraggo tutte le notizie, altrimenti estraggo solo le notizie della specifica sezione.
Vediamo il file php completo, in cui abbimo anche apportato una ulteriore modifica: se ricevo il parametro idsez visualizzo un <title>, quello in testa al file che identifica il sito stesso, rappresentativo della specifica sezione.
<?php
include "connection.php";
include "funzioni.php";
$items="";
if(empty($_GET['idsez'])) {
$query = "SELECT news_id,news_data,news_titolo,news_testo,news_url FROM news ORDER BY news_id DESC LIMIT 20";
}
else {
$query = "SELECT news_id,news_data,news_titolo,news_testo,news_url FROM news WHERE news_idsez=".mysqli_real_escape_string($mysql_link,$_GET['idsez'])." ORDER BY news_id DESC LIMIT 20";
}
$result = mysql_query($query, $mysql_link);
$rows = mysql_num_rows($result);
if($rows>0)
{
while($row = mysql_fetch_array($result))
{
$sintesi=substr($row['news_testo'],0,200)."...";
$items .="<item>";
$items .="<title><![CDATA[".xmlentities($row['news_titolo'])."]]></title>";
$items .="<description><![CDATA[".xmlentities($sintesi)."]]></description>";
$items .="<link>".$row['news_url']."</link>";
$items .="<pubDate>".date("D, d M Y H:i:s O",strtotime($row['news_data']))."</pubDate>";
$items .="</item>";
}
}
$toprint ='<?xml version="1.0" encoding="utf-8" ?>';
$toprint .="\n<rss version=\"2.0\" xmlns:dc=\"http://purl.org/dc/elements/1.1/\" xmlns:sy=\"http://purl.org/rss/1.0/modules/syndication/\" xmlns:admin=\"http://webns.net/mvcb/\" xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\" xmlns:content=\"http://purl.org/rss/1.0/modules/content/\">";
$toprint .="<channel>";
if(empty($_GET['idsez'])) {
$toprint .="<title>Il mio sito web</title>";
$toprint .="<link>https://www.miosito.it</link>";
$toprint .="<description>Blog di notizie tecnologiche</description>";
}
else {
if($_GET['idsez']==1) {
$toprint .="<title>Recensioni Smartphone | Il mio sito web</title>";
$toprint .="<link>https://www.miosito.it/smartphone</link>";
$toprint .="<description>Blog di notizie sul mondo degli smartphone</description>";
}
else if($_GET['idsez']==2) {
$toprint .="<title>Recensioni Tablet | Il mio sito web</title>";
$toprint .="<link>https://www.miosito.it/tablet</link>";
$toprint .="<description>Blog di notizie sul mondo dei tablet</description>";
}
}
$toprint .="<language>it-IT</language>";
$toprint .=$items;
$toprint .="</channel>";
$toprint .="</rss>";
header("Content-Type: text/xml; charset=utf-8");
print $toprint;
?>
Lascio a voi varie ed eventuali accortezze nello splittare le casistiche con e senza idsez.
That's all!