Laravel Framework, PHP & MySQL, Tutorials

In this post, I'll explain how to create an RSS feed.

First create a route that will respond with a feed, in this example I'm using a controller called BlogController and a method called feed.

Route::get('feed', 'BlogController@feed');

In your feed method query a model, in this case ordering by a created_at column and take the first 20 records, pass the data to a view:

public function feed()
{
    $posts = Post::orderBy('created_at', 'desc')->take(20)->get();
    return view('feed')->with(compact('posts'));
}

At the top of the view use a Request header to set the content type to application/xml

Start an rss and channel tags, set the title, description and link url

{{ Request::header('Content-Type : application/xml') }}

<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>

<title>{{ config('app.name') }}</title>
<description>RSS Feed</description>
<link>{{ url('/') }}</link>

Next loop through the data

@foreach ($posts as $post)

Now create a blade php block, inside the @php using str_replace swap & and &amp; and chate quotes.
Remove any slashes from the title, description, and slug.

Optionally an image can be embedded, in this case, a check is made to see if an image column is not empty, if so create an image tag.

@php
$post->title = str_replace("&", "&amp;", $post->title);
$post->description = str_replace("&rdquo;", "”", $post->description);
$post->description = str_replace("&ldquo;", "“", $post->description);

$post->title = stripslashes($post->title);
$post->description = stripslashes($post->description);
$post->slug = stripslashes($post->slug);

if ($post->image !='') {
    $img = "<img src='".url($post->image)."' alt='".$post->title."' width='600'>";
} else {
    $img = null;
}
@endphp

Next, create an item tag and display the following tags:

title - the title of the post
description - using CDATA display the img variable and description
pubDate - the date the post was created using date & strtotime to format the date lastly set the timezone.
link and guid - the url to the post
atomLlink - the link to the post 

NOTE I make use of a column called $slug this is a custom field that holds a search engine friendly version of the title.

<item>
    <title>{{ $post->title }}</title>
    <description><![CDATA[{!! $img !!} {!! $post->description !!}]]></description>
    <pubDate>{{ date('D, d M Y H:i:s', strtotime($post->created_at)) }} GMT</pubDate>
    <link>{{ url($post->slug) }}</link>
    <guid>{{ url($post->slug) }}</guid>
    <atom:link href="{{ url($post->slug) }}" rel="self" type="application/rss+xml"/>
</item>

Lastly, close the foreach and tags.

@endforeach

</channel>
</rss>

Putting it all together

{{ Request::header('Content-Type : application/xml') }}

<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>

<title>{{ config('app.name') }}</title>
<description>RSS Feed</description>
<link>{{ url('/') }}</link>

@foreach ($posts as $post)

    @php
    $post->title = str_replace("&", "&amp;", $post->title);
    $post->description = str_replace("&rdquo;", "”", $post->description);
    $post->description = str_replace("&ldquo;", "“", $post->description);

    $post->title = stripslashes($post->title);
    $post->description = stripslashes($post->description);
    $post->slug = stripslashes($post->slug);

    if ($post->image !='') {
        $img = "<img src='".url($post->image)."' alt='".$post->title."' width='600'>";
    } else {
        $img = null;
    }
    @endphp

    <item>
        <title>{{ $post->title }}</title>
        <description><![CDATA[{!! $img !!} {!! $post->description !!}]]></description>
        <pubDate>{{ date('D, d M Y H:i:s', strtotime($post->created_at)) }} GMT</pubDate>
        <link>{{ url($post->slug) }}</link>
        <guid>{{ url($post->slug) }}</guid>
        <atom:link href="{{ url($post->slug) }}" rel="self" type="application/rss+xml"/>
    </item>

@endforeach

</channel>
</rss>

An optional step is to add a link tag to your html head section.

<link href='{{ url('feed') }}' rel='alternate' title='RSS' type='application/rss+xml'/>