Adding RSS to any Laravel site (Canvas/Wink)

I recently updated my site to include a blog, and I build it around Laravel Canvas. Since Canvas does not feature an RSS feed by default, in this article I’ll show you how you can add such a feed to any Laravel based site.
Sep 13, 2019 — 5 mins read — Laravel

Adding RSS to any Laravel site (Canvas/Wink)

To provide the feed functionality, we will use a package by Spatie called “laravel-feed”. This package allows us to add an RSS feed to our site by just setting up a few simple configuration options and very little coding.

One of the major requirements for using this package is to add a special method to our main feed model and this is the biggest problem that we need to solve.

When building a site with Canvas, the entire platform is added as a package through Composer. With that, we are basically unable to directly add edits to the model in order to add this functionality. If we do so, we lose the ability to later make updates to the package as they will be overwritten. Instead, we will create an additional model that extends the main “Post” model from Canvas and we will add the extra functionality there. 

To start, we first need to install the package by running this command:

composer require spatie/laravel-feed

Once the installation finishes, we need to register the routes in the web.php file by calling the provided “feeds” macro.

Route::feeds();

Next, we need to publish the config file by running the following command:

php artisan vendor:publish --provider="Spatie\Feed\FeedServiceProvider" --tag="config"

If this was a regular Laravel site where you have the control over the used model, then you would proceed with the installation by adding the required interface and method to your model, as per the documentation, but here we don’t have that. We first need to create a new model in our application and in this model, we will first implement the Feedable interface with the example implementation form the documentation and change the inheritance to be the Post model from Canvas, instead of the default Model class. 

class NewsItem extends Post implements Feedable
{
    // interface implementation will be added here
}

To know which of the properties on the Post model we can get and use, we can go to its implementation and explore the properties and attributes that it has. Since not all of the properties are written directly in the model, we can explore the migrations that create the posts table to see exactly what is in it. 

Now that we know what we can use, we can go to our newly created model and update the properties in the toFeedItem method. For the id, we will use the slug of the post, title and summary are the same and for the updated field, we will use the published at date from the post. 

For the link to the article, we will get the route helper from the views as we have them implemented and in my case, this will basically be the root domain, plus the post slug next to it. The author will be pulled from the post author attribute but we need to send in the name only as this property contains the entire user model. So the final code of the method will look like:

public function toFeedItem()
{
    return FeedItem::create([
      'id' => $this->slug,
      'title' => $this->title,
      'summary' => $this->summary,
      'updated' => $this->published_at,
      'link' => route('blog.post', $this->slug),
      'author' => $this->author->name
    ]);
  }

With the data created, we now need to implement the getFeedItems method on our model that will be called to get the items to display in the feed. For now, we will leave it with the default implementation to get all of the items and we will move to the configuration file where we need to specify what is the method that returns the feed items, what will be the URL of the feed, the title of the feed and the view that will be used to render it. 

In my case, for the items setting, I’ve added the getFeedItems method that we just created on the NewsItem model and for the URL I've set “/feed”.  The full content of the feed.php config file is:

return [
    'feeds' => [
        'main' => [
            'items' => 'App\[email protected]',
            'url' => '/feed',
            'title' => 'Taste The Code latest blog posts',
            'view' => 'feed::feed',
        ],
    ],
];

As a final step, we need to add the link to the feed in our main layout file so it can be automatically recognized by feed readers. The package provides a convenient way for doing this by directly providing a partial view with the link implementation. This is added in the main layout file of your application, in the head section just above the page title. 

@include('feed::links')

Now we can test out the feed by accessing the /feed URL and if we did everything right, we should see the result. After opening it thou, I immediately noticed that instead of showing the latest post on top, it is on the bottom so I went into the NewsItem model and updated the getFeedItems method to order the retrieved posts by the published date in a descending order and I also added a limit of 50 posts at the most. This should be more than enough content for newcomers and also will prevent the feed from taking too much time to load down the line when there are a lot of posts on the blog. 

public static function getFeedItems()
{
    return NewsItem::orderBy('published_at', 'desc')->limit(50)->get();
}

As many of Spatie’s packages, the “laravel-feed” package is really well documented and easy to be used. By using an extra model as in this example, you can create feeds for any other platforms and packages that don’t support them yet, as Wink for example. 

If this article was helpful to you, then feel free to subscribe to my YouTube channel and share it with your friends.

php rss laravel feed
Read this next

Fix your broken subscriber counters - YouTube Sight

Ever since I started the channel I wanted to build myself a subscriber counter to use it as a decoration in my home office and make a video...

You might enjoy

Variable Variables in PHP

In PHP we are allowed to name a variable with the content of another variable. These are called variable variables and can be used at...