Learn to Create an RSS Feed from Scratch in Laravel
Published on by Paul Redmond
Creating an RSS feed in Laravel isn’t the most challenging task, but using a package and a few tips can help you create an RSS feed relatively quick.
We are going to use the spatie/laravel-feed package to walk through going from a brand new Laravel 5.6 project to serving RSS feeds.
Setup
The first thing we need to do is create a new Laravel project. You can use the laravel new
installer command, or use composer:
composer create-project --prefer-dist laravel/laravel:5.6 rss-examplecd rss-example
Next, let’s install the spatie/laravel-feed
package and copy the configuration file into the project:
composer require spatie/laravel-feedphp artisan vendor:publish \ --provider="Spatie\Feed\FeedServiceProvider" \ --tag="config"
Modeling the Data
We are going to create some test model data to set up our RSS feed for a collection of Events. Think of this model as an RSS feed for upcoming events for a church or a meetup group. The model name Event
is superfluous, but that’s the best name I could come up with, so we’ll go with it!
First up, let’s create the model for our RSS feed along with a migration file and a factory file:
php artisan make:model Event -mfModel created successfully.Factory created successfully.Created Migration: 2018_04_03_033916_create_events_table
In the migration class, let’s define the generic, simple schema:
public function up(){ Schema::create('events', function (Blueprint $table) { $table->increments('id'); $table->string('title'); $table->text('description'); $table->string('author'); $table->timestamps(); });}
Next up, open the database/factories/EventFactory.php
file and add the following:
$factory->define(App\Event::class, function (Faker $faker) { return [ 'title' => $faker->sentence, 'description' => "<p>".implode("</p>\n\n<p>", $faker->paragraphs(rand(3,6)))."</p>", 'author' => $faker->name, ];});
There might be a better way to generate an HTML description, but I am assuming that the UI for creating an event would provide a WYSIWYG field for writing the description.
We can use our schema and factory to seed some test data in order to finish setting up our RSS feed:
php artisan make:seeder EventsSeeder
In the created EventsSeeder class, generate some seed events we can use:
<?php use Illuminate\Database\Seeder; class EventsSeeder extends Seeder{ /** * Run the database seeds. * * @return void */ public function run() { factory('App\Event', 50)->create(); }}
Next, add the EventsSeeder
to the DatabaseSeeder
class:
<?php use Illuminate\Database\Seeder; class DatabaseSeeder extends Seeder{ /** * Run the database seeds. * * @return void */ public function run() { $this->call(EventsSeeder::class); }}
Depending on how you created the files, you might need to run composer dump-autoload
to pick up the seeder files. You can then run migrations (assuming you’ve set up a database following the documentation) to create the tables and populate the database with some seed data:
php artisan migrate:fresh --seedDropped all tables successfully.Migration table created successfully.Migrating: 2014_10_12_000000_create_users_tableMigrated: 2014_10_12_000000_create_users_tableMigrating: 2014_10_12_100000_create_password_resets_tableMigrated: 2014_10_12_100000_create_password_resets_tableMigrating: 2018_04_03_034457_create_events_tableMigrated: 2018_04_03_034457_create_events_tableSeeding: EventsSeeder
And just like that, we have some fake events to work with!
Setting up the Model
Using Spatie’s package, we implement an interface to support the spatie/laravel-feed
package configuration with our App\Event
model.
We will have two methods for using our Event
model with a feed:
- The
toFeedItem()
method to support Spatie’sFeedable
interface - A
getFeedItems()
static method to get all the feed items
First up, here’s the implementation for the toFeedItem()
method with our schema in the app/Event.php
file:
<?php namespace App; use Spatie\Feed\Feedable;use Spatie\Feed\FeedItem;use Illuminate\Database\Eloquent\Model; class Event extends Model implements Feedable{ public function toFeedItem() { return FeedItem::create() ->id($this->id) ->title($this->title) ->summary($this->description) ->updated($this->updated_at) ->link($this->link) ->author($this->author); }}
At the moment, this method won’t work quite right, because we don’t have a link
attribute but other than that, this method is pretty straightforward.
We are converting an individual model instance to a FeedItem
instance to generate the final RSS format.
Next, we’ll add the getFeedItems()
static method to the Event.php
file:
public static function getFeedItems(){ return static::all();}
We are merely returning all results as a collection that is converted to individual FeedItem
instances.
The last method we’ll add to the model is an accessor for the $event->link
attribute:
public function getLinkAttribute(){ return route('events.show', $this);}
Using implicit route model binding, we are generating the link
property on the model that will be used to link to individual RSS items.
Routes and the Events Controller
The last piece we need to work on is creating a controller and a route so the route('events.show', $this)
will work as expected.
First, let’s generate a controller:
php artisan make:controller EventsControllerController created successfully.
Inside the EventsController
create a show()
method that returns the model which results in a JSON response. We are not going to flesh out the EventsController@show
method and return HTML in this tutorial; I’ll leave that up to you:
<?php namespace App\Http\Controllers; use App\Event;use Illuminate\Http\Request; class EventsController extends Controller{ public function show(Request $request, Event $event) { return $event; }}
Next, we need to configure the main RSS feed route in the published config/feed.php
file we generated earlier:
<?php return [ 'feeds' => [ 'main' => [ 'items' => 'App\Event@getFeedItems', /* * The feed will be available on this url. */ 'url' => '/events.rss', 'title' => 'Upcoming Events', ], ],];
Last up, we need to add the RSS route and the EventsController@show
route to the bottom of routes/web.php
:
Route::get('/events/{event}', 'EventsController@show') ->name('events.show'); Route::feeds();
The Route::feeds()
method is a route macro that defines the necessary route(s) from our config/feed.php
configuration. We use the {event}
route parameter and take advantage of implicit route model binding that we used earlier to generate the event link from within the model.
Our feed should be available at /events.rss
now!
Linking to the Feed
You can also add an RSS link to the default welcome page by adding @include('feed::links')
in the <head>
of the view:
<!doctype html><html lang="{{ app()->getLocale() }}"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Laravel</title> @include('feed::links'){{-- ... --}}
If you visit the homepage of the project, you’ll get something like the following link
tag:
<link rel="alternate" type="application/rss+xml" href="http://127.0.0.1:8000/events.rss" title="Upcoming Events">
With hardly any effort, we created a working RSS feed for our model data, and you can imagine how little you’d have to do to add RSS to existing model data in your applications!
Learn More
Check out the laravel-feed GitHub page for the source code and package setup.
I wrote about Route macros yesterday in Laravel Route Tips to Improve Routing, and the Laravel feed package has an excellent route macro defined in the FeedServiceProvider that you should check out.