En este tutorial te planteo crear un lector de feeds o agregador de contenidos utilizando Twig como motor de plantillas y la librería nativa PDO para el acceso a una base de datos tipo SQL.
El tutorial es de un nivel medio y se requiere alguna soltura con PHP, conocer un poco el lenguaje de plantillas Twig y no estaría mal entender aunque sea por encima lo que es el modelo MVC para la creación de aplicaciones web por capas, aunque aquí sólo distinguiremos entre vistas y controladores. No requiere prácticamente conocimientos de Programación Orientada a Objetos. He intentado que tenga un nivel asequible para alguien que está empezando o lleva un tiempo atascado en como organizar mejor su código.
Según la wikipedia, un lector de contenidos (también conocido como agregador, agregador de noticias o lector de RSS) es un software para suscribirse a fuentes de noticias en formatos RSS, Atom y otros derivados de XML. El agregador reúne las noticias o historias publicadas en los sitios elegidos (blogs, noticias, podcasts, etc.) y muestra las novedades o modificaciones que se han producido en esas fuentes, es decir, avisa de qué webs han incorporado contenido nuevo desde nuestra última lectura y cuál es ese contenido.
El lector que te propongo será muy sencillo porque sólo mostrará en cada momento los últimos artículos de cada sitio web seleccionado, sin llevar cuenta de lo que has leído o dejado de leer (al menos por ahora).
Las especificaciones funcionales del proyecto serían:
- Tener una página web a la que poder agregar fuentes RSS mediante un formulario.
- Mostrar los títulos de los artículos de cada fuente.
- Poder acceder a los artículos mostrados.
Las especificaciones técnicas serían:
- Lenguaje PHP.
- Librería PDO para conexión a datos.
- MySQL, MariaDB o SQLite para almacenar datos.
- Lenguaje de plantillas Twig.
Si te ves preparado, te animo a crear o esbozar el proyecto por tu cuenta, para luego compararlo con este. Si prefieres ir siguiendo el tutorial… ¡empezamos!.
Preparando el entorno de desarrollo
Si ya sabes manejar Git o algún otro software de gestión de versiones ve a GitHub o a tu gestor de proyectos favorito y crea un nuevo repositorio para albergar la aplicación. Luego ve a la carpeta de tu equipo donde vayas a trabajar y haz el git clone correspondiente.
En mi caso sería:
1 | git clone https://github.com/galatar/gestor-de-feeds-con-twig-y-pdo.git |
Pero, claro, no copies esto exacto porque si no te traes ya el proyecto terminado. Si aún no conoces Git no te preocupes por esta parte, si te pica la curiosidad prueba con esta guía sencilla de git.
En cualquier caso tienes todo el código y la estructura del proyecto en github por si te pierdes o te cansas de teclear.
Ahora vas a utilizar Composer para poder hacer uso de la librería Twig. Si no sabes de que hablo puedes leer el artículo sobre como utilizar Composer. Entonces ve al directorio del nuevo proyecto y teclea
1 | composer init |
Composer te pedirá el nombre del proyecto, una descripción, el tipo de licencia, etc. y cuando te pregunte por las dependencias le dices «yes» y luego agregas el paquete «twig/twig». Teclea un «enter» adicional para no instalar más paquetes (a no ser que quieras alguno por tu cuenta) y confirma para que se genere el fichero composer.json
Por último para descargar el paquete Twig ejecuta
1 | composer update |
Como verás Twig ha metido alguna dependencia más que el mismo necesita, ¡estupendo, esta es la magia de Composer!
Ahora crea algunas carpetas que vas a necesitar para estructurar de manera estándar el código: public, public/css, src, templates, var, var/cache.
El archivo de configuración
En la carpeta raíz, creas un archivo config.php donde definirás algunas constantes para personalizar cada instalación concreta de la aplicación. No debes subir este fichero al gestor de versiones, porque contiene información sobre el servidor de base de datos, claves, etc.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 <?php
// Activa o desactiva el modo debug para cuando estás en desarrollo
define('FEED_DEBUG', true);
// Parámetros de configuración de Twig
define('FEED_TWIG_RUTA_PLANTILLAS', '../templates');
define('FEED_TWIG_RUTA_CACHE', '../var/cache');
// Parámetros de conexión a tu base de datos
// Pon los que hayas dispuesto o vayas a disponer para tu base de datos
define('FEED_DB_DRIVER', 'mysql');
define('FEED_DB_HOST', 'localhost');
define('FEED_DB_NAME', 'feederico');
define('FEED_DB_USER', 'galatar');
define('FEED_DB_PASSWORD', 'Un_mal_password_lo_tiene_cualquiera');
El controlador principal, única puerta de entrada a tu aplicación
En la carpeta public creas un archivo con el nombre index.php que será el controlador principal, encargado de orquestar toda la aplicación. En el mismo fichero te explico lo que va haciendo.
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 <?php
/* /public/index.php */
// Llama al fichero de autocarga de clases generado por composer
require_once '../vendor/autoload.php';
// Llama al fichero con las constantes definidas para la aplicación
// Este fichero no debe subirse al gestor de versiones
require_once '../config.php';
// Configura la librería Twig
$twig_loader = new Twig_Loader_Filesystem(FEED_TWIG_RUTA_PLANTILLAS);
$twig = new Twig_Environment($twig_loader, array(
'cache' => FEED_TWIG_RUTA_CACHE,
'debug' => FEED_DEBUG)
);
// Conecta base de datos con PDO
try {
// dsn: data source name
$dsn = FEED_DB_DRIVER. ':host=' . FEED_DB_HOST . ';dbname=' . FEED_DB_NAME;
// dbh: database handler
$dbh = new PDO($dsn, FEED_DB_USER, FEED_DB_PASSWORD);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e){
echo 'Error de conexión a la base de datos';
if (FEED_DEBUG) {
echo $e->getMessage();
}
}
// Enrutado primitivo pero efectivo
if (filter_has_var(INPUT_GET, 'pagina')) {
$pagina = filter_input(INPUT_GET, 'pagina', FILTER_SANITIZE_URL);
} else {
$pagina = 'inicio';
}
// Llama al fichero php indicado en la ruta
$ruta_pagina = '../src/' . $pagina . '.php';
if (is_file($ruta_pagina)){
require_once($ruta_pagina);
} else {
require_once('../src/error_404.php');
}
// Muestra errores si los hay
if ($error) {
echo '<div class="alert alert-danger">Ha ocurrido un error. Contacte con el responsable del sistema.</div>';
if (FEED_DEBUG) {
// Muestra el contenido del error si está en modo debug
echo '<div class="alert alert-danger">' . $error . '</div>';
}
}
En resumen, el archivo index.php, que será el controlador principal, hace lo siguiente:
- Carga las librerías que vas a usar utilizando el fichero autoload.php de Composer.
- Carga el fichero de configuración de la aplicación, config.php, donde va todo aquello que puede cambiar de una instalación a otra.
- Configura y carga el motor de plantillas Twig.
- Configura y carga la librería PDO para conectar a la base de datos.
- Se encarga de ver que página ha solicitado el usuario.
- Llama a la página que el usuario ha solicitado.
- Muestra los errores que se hayan producido
Plantilla base con Twig
Creas una plantilla base de Twig llamada layout_base.html.twig, dentro de la carpeta templates si tienes dudas puedes consultar el tutorial de Twig que te he enlazado más arriba.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 {# /templates/layout_base.html.twig #}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>{% block titulo %}Mi Gestor de Feeds{% endblock %}</title>
<link rel='stylesheet' href="css/bootstrap.css">
</head>
<body>
<div class="container">
<header><h1><a href="index.php">Feederico</a></h1></header>
<div id="contenido">
{% block contenido %}{% endblock %}
</div>
</div>
</body>
</html>
Te explico por encima esta plantilla base. Lo primero que ves es un comentario Twig, que se construye con las etiquetas {# #}. Luego ves la definición de un bloque dentro de la etiqueta «title». Los bloques son los contenidos de las plantillas base en donde podrás colocar contenido cuando otra plantilla herede de esta otra. En la plantilla hija llamas a los bloques tal como ves aquí pero sustituyes el contenido. Piensa en esos cuadros que vienen con su marco y su cristal y varias ventanitas para poner tus fotos o dibujos y te harás una idea de lo que son los bloques en Twig. Un poco más adelante tienes otro bloque: «contenido» que como podrás suponer se va a llevar todo el trabajo cuando rellenes las plantillas hijas.
Por cierto, no olvides descargar la hoja de estilo de bootstrap para que el conjunto quede bonito.
Un controlador secundario y su plantilla para el error 404
Para ver que esto empieza a funcionar puedes crear la típica página error 404 que aparece cuando alguien quiera cargar una página que no exista. Cada página que crees va a necesitar normalmente dos partes: un controlador secundario, que será un fichero php encargado de gestionar la lógica de la página y una plantilla hecha con twig que será la encargada de la presentación.
1
2
3
4 <?php
/* /src/error_404.php */
global $plantilla;
$plantilla='error_404.html.twig';
Como ves este primer controlador es muy sencillo y lo único que hace es definir la plantilla que hay que mostrar, se declara la variable $plantilla como global para que se entienda que viene del controlador principal y para evitar un «warning» en el editor de código.
Aquí la única nueva etiqueta de Twig que encuentras es extend que es la que se utiliza para que esta nueva plantilla herede de la que has creado antes.
Si ahora vas al navegador y accedes a tu sitio con algo como http://localhost:8080/index.php?page=no_existo debe salirte un flamante «error 404».
Y ahora toca pelearse con los feeds.
Atacando los feeds
Esta parte del tutorial me ha costado bastante porque tengo que confesarte que nunca había trabajado con feeds ni había tratado en serio con ficheros XML, que son la base de los mismos.
Para mi hacer esta parte del tutorial ha sido un verdadero reto, así que si te animas te invito a dejar de seguir leyendo y buscar una solución por ti mismo. Se tarda más pero también se aprende mucho 😉
Como te acabo de comentar un feed es un fichero XML que contiene los últimos artículos publicados en un blog o en cualquier otra publicación electrónica que libere artículos periódicamente.
Para acceder al feed normalmente hay que escribir la URL de la web seguida de algo como «/feed», «/rss», «/atom.rss», etc. A veces son cosa mucho más locas, que puedes averiguar buscando el típico icono de feed.
Si quieres ver el aspecto del feed de este mismo blog visita la dirección http://galatar.com/feed. Aquí tienes un fragmento de lo que te devuelve.
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 <?xml version="1.0" encoding="UTF-8"?>
<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:atom="http://www.w3.org/2005/Atom"
xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
xmlns:georss="http://www.georss.org/georss"
xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#">
<channel>
<title>Galatar</title>
<atom:link href="http://galatar.com/feed" rel="self" type="application/rss+xml" />
<link>http://galatar.com</link>
<description>Programación Web de cero a infinito</description>
<lastBuildDate>Wed, 08 Aug 2018 14:39:35 +0000</lastBuildDate>
<language>es-ES</language>
<sy:updatePeriod>hourly</sy:updatePeriod>
<sy:updateFrequency>1</sy:updateFrequency>
<generator>https://wordpress.org/?v=4.9.8</generator>
<image>
<url>http://galatar.com/wp-content/uploads/2018/07/g_torre_3d-1-150x150.png</url>
<title>Galatar</title>
<link>http://galatar.com</link>
<width>32</width>
<height>32</height>
</image>
<site xmlns="com-wordpress:feed-additions:1">123870268</site>
<item>
<title>Marcar y desmarcar checkbox de manera simultánea con jQuery</title>
<link>http://galatar.com/marcar-y-desmarcar-checkbox-de-manera-simultanea-con-jquery/</link>
<comments>http://galatar.com/marcar-y-desmarcar-checkbox-de-manera-simultanea-con-jquery/#respond</comments>
<pubDate>Tue, 07 Aug 2018 15:31:39 +0000</pubDate>
<dc:creator><![CDATA[Juanan Ruiz]]></dc:creator>
<category><![CDATA[JavaScript]]></category>
<guid isPermaLink="false">http://galatar.com/?p=187</guid>
<description><![CDATA[Hace unos días tuve que hacer un formulario para enviar un correo a una lista cerrada de personas, pero me pedían la posibilidad de enviar el correo a todos o a una parte de la lista cerrada. Algo parecido a lo que se muestra en la siguiente imagen Tenía hecho algo similar en un proyecto […]]]></description>
<content:encoded><![CDATA[<p>Hace unos días tuve que hacer un formulario para enviar un correo a una lista cerrada de personas, pero me pedían la posibilidad de enviar el correo a todos o a una parte de la lista cerrada. </p>
<p>Algo parecido a lo que se muestra en la siguiente imagen</p>
...
Pues bien, de aquí tendrás que sacar la información para hacer tu agregador de feeds (¡Aggggg! Sí, eso mismo pensé yo). Si intentas leer el fichero con calma, verás que primero se confiesa como un documento XML versión 1.0. A continuación se abre una etiqueta
Si sigues bajando un poco más llegarás, por fin, a una etiqueta
Además de la especificación rss que es la que acabas de ver y es la más común, existe la especificación atom, usada por ejemplo por todos los blogs basados en «blogger». Para no extender ni complicar más el tutorial de momento esta aplicación no será capaz de tratar con estos ficheros. Si más adelante quieres tratar con feeds atom te recomiendo leer el artículo Parsing Atom Feeds using XPath.
Librerías PHP para XML
En PHP existen varías librerías nativas para trabajar con XML para trabajar feeds las dos más adecuadas son DOM y SimpleXML, me he decidido por esta última porque he encontrado más ejemplos sobre ella. La documentación sobre el tema es escasa y un poco confusa si no estás acostumbrado a trabajar con documentos XML (como es mi caso).
La puerta de entrada a SimpleXML para la lectura de ficheros es la función simplexml_load_file que te permite cargar una URL o un fichero en tu disco duro en un objeto de la clase SimpleXMLElement. Este objeto contiene todas las propiedades del fichero XML. Si el fichero que has cargado contiene elementos repetitivos (como los artículos de un blog) podrás iterar sobre ellos. En la documentación de PHP sobre SimpleXML tienes un ejemplo bastante completo
Utilizando SimpleXML para destripar el primer feed
Creas un nuevo controlador secundario dentro de la carpeta src al que puedes llamar inicio.php
1
2
3
4
5
6
7 <?php
/* /src/inicio.php */
global $plantilla;
$xml = simplexml_load_file('http://galatar.com/feed');
$articulos = $xml->xpath("//item");
$plantilla = 'inicio.html.twig';
$datos = array('articulos' => $articulos);
En la línea 4 creas el objeto $xml (si no sabes lo que es un objeto piensa en el para este ejemplo como en una variable gorda con una cierta estructura). Este objeto contiene todo el contenido del fichero XML, o sea el contenido del feed.
Otra de las ventajas de los objetos es que también tienen funciones internas y una de ellas se utiliza en la línea 5 para decirle que busque todas las ramas que empiecen con la etiqueta item y las meta en la variable $articulos.
A continuación le pasas el nombre de la plantilla y un array con los datos que esta necesitará.
Eso es todo lo que respecta al código para capturar los artículos del feed y esta sería la plantilla.
1
2
3
4
5
6
7
8
9
10
11
12 {# /templates/inicio.html.twig #}
{% extends 'layout_base.html.twig' %}
{% block titulo %}Inicio{% endblock %}
{% block contenido %}
<ul>
{% for articulo in articulos %}
<li>
<span>{{ articulo.pubDate|date('d-m-Y') }}</span>
<br><a href="{{ articulo.link|escape('html') }}">{{ articulo.title|escape('html') }}</a>
</li>
{% endfor %}
</ul>
Aquí aparecen nuevas etiquetas de Twig muy interesantes:
La construcción {% for articulo in articulos %} … {% endfor %} recorre los elementos contenidos en el array articulos y los va asignando a la variable articulo para poder mostrarla en la página.
El modificador «escape(‘html’)» evita que alguien pueda pasar un feed a tu aplicación con un XML que contenga código malicioso, de esta manera el contenido que se muestre en tu html irá filtrado para evitar ataques.
A su vez la variable articulo tiene las propiedades pubDate, link y title que puedes mostrar en tu listado de artículos. ¿De dónde salen esas propiedades? Las generó la librería SImpleXML con la función xpath que utilizamos en el controlador y vienen del archivo XML del feed. Mira el fragmento de XML que te mostré al inicio de esta sección y allí las podrás encontrar debajo de la etiqueta item
Estas propiedades o variables las puedes mostrar en el html utilizando la doble llave de Twig {{ … }}
El modificador «|escape(‘html’)» evita que alguien pueda pasar un feed a tu aplicación con un XML que contenga código malicioso, de esta manera el contenido que se muestre en tu html irá filtrado para evitar ataques.
Creación de la base de datos
La estructura de la base de datos es muy sencilla, consiste en una única tabla «feed» para almacenar los sitios a los que te vas suscribiendo, un identificador, la url del feed y una columna para marcar los favoritos, serán los únicos campos. Así que puedes crearla con una consulta SQL desde consola, desde phpMyAdmin o desde la herramienta que uses.
1
2
3
4
5
6 CREATE TABLE `feed` (
`id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`url` VARCHAR(254) COLLATE utf8mb4_spanish_ci DEFAULT NULL,
`favorito` tinyint(4) DEFAULT '1',
PRIMARY KEY (`id`)
);
Agrega una primera entrada a tu tabla de feeds
Ahora vas a crear una página desde donde poder verificar y agregar a la base de datos los feeds a los que te quieras ir suscribiendo. Para ello crea un fichero con el nombre «mostrar_feed.php» en la carpeta «src».
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 <?php
global $plantilla;
global $datos;
// Comprueba si el formulario viene relleno
if (filter_has_var(INPUT_GET, 'feed')
&& $feed = filter_input(INPUT_GET, 'feed', FILTER_SANITIZE_STRING)){
$datos['feed'] = $feed;
// Recupera los artículos del feed
$xml = simplexml_load_file($feed);
if (is_object($xml) && $articulos = $xml->xpath("//item")) {
$datos['articulos'] = $articulos;
}
// Comprueba si el feed existe en la base de datos
$datos['feed_existe'] = false;
$query = $dbh->prepare('SELECT count(*) FROM feed WHERE url = :feed');
// Es más seguro pasar las entradas de usuario como parámetro
// y no insertarlas directamente en la cadena SQL
$query->bindParam(':feed', $feed);
$query->execute();
if ($query->fetchColumn()) {
$datos['feed_existe'] = true;
}
$plantilla = 'mostrar_feed.html.twig';
} else {
header("location:index.php?page=inicio");
}
Este controlador cumple una triple misión:
- Mostrar un formulario donde puedes escribir la dirección de un nuevo feed.
- Comprobar si el feed introducido existe ya en la base de datos.
- Mostrar el contenido del feed tras enviar el formulario y un enlace para confirmar que lo quieres añadir a tu colección.
En este caso el trabajo más duro lo hace la plantilla, que tiene que pintar un montón de cosas. Crea un archivo «/templates/agregar_feed.html.twig»
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 {# /templates/agregar_feed.html.twig #}
{% extends 'layout_base.html.twig' %}
{% block titulo %}Agregar Feed{% endblock %}
{% block contenido %}
{# Si el feed es valido y contiene artículos los muestra #}
{% if articulos %}
<div class="alert alert-info mt-4">
<p>Estos son los contenidos del feed que has indicado.<p>
{# Si el feed está en la BD lo dice y si no pinta el botón para guardarlo #}
{% if feed_existe %}
<p>El feed ya existe en tu base de datos</p>
{% else %}
<p><a href="index.php?pagina=confirmar_feed&feed={{ feed }}"
class="btn btn-primary">Agregar a mis feeds</a></p>
{% endif %}
</div>
<h4>{{ feed }}</h4>
<div class="mt-4">
<ul>
{% for articulo in articulos %}
{% set host = articulo.link|split('/')[2] %}
<li><span class="small text-muted">{{ articulo.pubDate|date('d-m-Y') }}</span>
<br><a href="{{ articulo.link }}">{{ articulo.title }}</a>
</li>
{% endfor %}
</ul>
</div>
{% else %}
{# Si el feed no es válido o no contiene artículos lo dice y vuelve a pintar el formulario #}
<form method="get" class="form-inline">
<input type="hidden" name="pagina" value="mostrar_feed">
<div class="form-group col-md-8 mb-2">
<input class="form-control col-md-12" type="text" name="feed"
placeholder="https://mi_blog_favorito.com/feed"
value="{{ feed }}">
</div>
<button type="submit" class="btn btn-primary mb-2">Mostrar feed</button>
</form>
<div class="alert alert-danger mt-4">
<p>Parece que el feed introducido no es valido o no es compatible con Feederico.</p>
<p><strong>{{ feed }}</strong></p>
<p>Intenta cambiar la url a algo como:
<ul>
<li>https://mi_blog_favorito.com/feed</li>
<li>https://mi_blog_favorito.com/rss</li>
<li>https://mi_blog_favorito.com/atom.rss</li>
</ul>
</div>
{% endif %}
{% endblock %}
Recuperando los feeds desde la base de datos
Está bien ir agregando feeds a tu colección pero en algún momento querrás saber que tienes ahí dentro. Para eso recupera los registros de la base de datos y lo muestras en tu página, por supuesto usando Twig.
Sustituye el código del controlador de la página de inicio «/src/inicio.php» por este otro .
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 <?php
/* /src/inicio.php */
global $plantilla;
global $datos;
global $dbh;
$query = $dbh->prepare('SELECT * FROM feed;');
$query->setFetchMode(PDO::FETCH_ASSOC);
$query->execute();
$feeds = query->fetchAll();
$xml = simplexml_load_file('http://galatar.com/feed');
$articulos = $xml->xpath("//item");
$datos = array('articulos' => $articulos, 'feeds' => $feeds);
$plantilla = 'inicio.html.twig';
La plantilla «/templates/inicio.html.twig» la completas con un formulario para cargar feeds (idéntico al de la plantilla agregar_feeds) y una columna para que muestre los feeds que tienes en la base de datos
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 {# /templates/inicio.html.twig #}
{% extends 'layout_base.html.twig' %}
{% block titulo %}Inicio{% endblock %}
{% block contenido %}
<div class="row">
<div class="col-md-8">
<form method="get" class="form-inline">
<input type="hidden" name="pagina" value="mostrar_feed">
<div class="form-group col-md-10 mb-2">
<input class="form-control col-md-12" type="text" name="feed"
placeholder="https://mi_blog_favorito.com/feed"
value="{{ feed }}">
</div>
<button type="submit" class="btn btn-primary mb-2">Mostrar feed</button>
</form>
<ul>
{% for articulo in articulos %}
{% set host = articulo.link|split('/')[2] %}
<li><span class="small text-muted">{{ articulo.pubDate|date('d-m-Y') }} · {{ host|escape('html') }}</span>
<br><a href="{{ articulo.link|escape('html') }}">{{ articulo.title|escape('html') }}</a>
</li>
{% endfor %}
</ul>
</div>
<div class="col-md-4">
<div class="card">
<div class="card-header">Mis feeds</div>
<div class="card-body">
<ul>
{% for feed in feeds %}
{% set host = feed.url|split('/')[2] %}
<li><a href="index.php?pagina=mostrar_feed&feed={{ feed.url|escape('html') }}">{{ host|escape('html') }}</a></li>
{% endfor %}
</ul>
</div>
</div>
</div>
</div>
{% endblock %}
Para seguir avanzando
El proyecto hasta aquí es bastante básico aunque puede ser una forma cómoda y personalizable de mantener recopiladas todas las web que sigues habitualmente (bueno casi todas).
De momento sólo pinta un feed en la página de inicio, el que puse de muestra al principio, pero es fácil recorrer los feeds que tienes en la base de datos para ir cargando todos sus artículos, lo malo es que si tienes muchos feeds será un poco lento. Sería sustituir en el fichero «/src/inicio.php» las dos líneas donde se cargan el feed y los artículos de galatar por algo como esto.
1
2
3
4
5
6
7
8
9
10
11
12
13 ...
$articulos = array();
foreach ($feeds as $feed) {
$xml = simplexml_load_file($feed['url']);
if (is_object($xml)) {
$articulos = array_merge($articulos, $xml->xpath("//item"));
}
}
//Ordena las articulos por fecha de publicación
usort($articulos, function ($art1, $art2) {
return strtotime($art2->pubDate) - strtotime($art1->pubDate);
});
...
Para evitar la lentitud podrías cachear los resultados, o marcas como favoritos sólo los sitios que más lees para cargar de entrada sólo estos, etc.
Bueno, espero que este artículo te haya sido de utilidad, hayas aprendido un poco de XML, algo de PDO y Twig y en general mucho PHP. No es el código más estándar ni el más ajustado a las prácticas actuales, pero creo que puede ir bien para alguien que esté empezando y necesite ir digiriendo los conceptos poco a poco.
Espero tus comentarios, tus dudas y tus ideas para mejorar el código o las explicaciones. Dime si te interesa este tipo de tutoriales o prefieres artículos más cortos. Y si te ha gustado y piensas que pueda ser útil a otro te pido que lo compartas: por correo, twitter, facebook, linkedin o cualquier otra red social que frecuentes.
Referencias
- Manual de Twig en español – http://gitnacho.github.io/Twig/
- https://stackoverflow.com/questions/4887300/using-simplexml-to-read-rss-feed
- http://makitweb.com/how-to-read-rss-feeds-using-php/
- https://makitweb.com/demo/rssreader_php/
- http://www.baltcica.org/htdocs/
- http://simplepie.org/wiki/
- https://www.ibm.com/developerworks/library/x-xpathphp/index.html
- https://www.sitepoint.com/php-dom-working-with-xml/
- https://www.sitepoint.com/php-dom-using-xpath/
- https://www.htmlgoodies.com/beyond/php/parsing-atom-feeds-using-xpath.html
- https://github.com/dg/rss-php
- https://www.skptricks.com/2018/04/php-xml-reader-example.html
Deja una respuesta