mykemeynell / laravel-syndication
RSS and Atom feeds for laravel
Requires (Dev)
- laravel/laravel: ^9.3
This package is auto-updated.
Last update: 2024-10-21 15:17:02 UTC
README
A super simple RSS and Atom feed package for Laravel. Can generate either RSS, Atom or both - for specified models.
Installation
composer require mykemeynell/laravel-syndication
With auto-discovery
The service provider has already been registered, so you can continue to the next step.
Without auto-discovery
Add the LaravelSyndicationServiceProvider
to your config/app.php
file.
'providers' => [ // ... LaravelSyndication\LaravelSyndicationServiceProvider::class, // ... ],
Publish the configuration
This will create a new configuration file under config/syndication.php
.
php artisan vendor:publish --tag=laravel-syndication
Config
Feeds
/* * Feeds that can be used for syndication are defined here. This should be * done using a key-value pair -- where the key is the identifier * of the feed, adn the value is the feed object. * * For example: * 'posts' => App\Feeds\Posts::class */ 'feeds' => [],
Routing
'routing' => [ /* * Sets the prefix of any generated feeds. * default is 'feeds'. */ 'prefix' => 'feeds', /* * If you'd like to serve your feeds from a separate domain * or subdomain - you can specify the domain here. */ 'domain' => null, ],
Encoding
/* * Encoding for the generated files, it will default to utf8 if there is no * other value specified -- so if you'd like a simpler config * file, then feel free to remove this key. */ 'encoding' => 'utf-8',
Caching
Sets the default caching value for all feeds. If set to false, nothing will be cached and no values current cached will be read.
'cache_feeds' => true,
Specify the cache store to use. Using null
will default to the default cache
store.
'cache_store' => null,
How long (in minutes) the cache is valid for.
'cache_ttl' => 1440,
If you would like to specify different TTLs for different feeds, then
you can do this here. It should be keyed using the same keys defined in
the feeds
key array, appended with the type of feed, for example;
'podcasts.atom'
or 'podcasts.rss'
To disable caching for specific feeds, set the value to false
.
To disable caching for all feeds except those specified, set
cache_feeds
to false, and specify a value greater than 0
in caching
.
'caching' => [ 'posts.atom' => 10080 ],
Usage
Creating a new feed
Use artisan to create a new feed class.
For example, if you wanted to create a feed for podcasts;
php artisan make:feed Postcasts
This will output a feed class object at app/Feeds/Postcasts.php
.
Add the feed class to config/syndication.php
Under the feeds
key, add the FQN of the feed you just created.
'feeds' => [ // ... 'podcasts' => App\Feeds\Postcasts::class // ... ],
Configuring a Feed
Feed Types
Use the following base classes to determine the kind of feeds that can be
generated, and the methods that are available in the setUp()
method.
Configuration methods
All configuration on a feed object is done in the setUp()
method.
For example:
namespace App\Feeds; class Podcast extends RssAndAtomFeed { public function setUp(): void { $this->model(\App\Models\Podcast::class) ->title("Awesome Podcast") ->description("An amazing podcast.") ->url(url('/podcasts')) ->language("en") ->updated($this->lastCachedAt()); } }
Configuring the feed model
Once you have created your feed object and specified the model and filter you
would like to use when generating feed contents. You will need to add the
LaravelSyndication\Contracts\Models\IsSyndicationItem
interface to your model.
The IsSyndicationItem
interface specifies a single method toFeedItem
that
is expected to return an instance of LaravelSyndication\Feeds\FeedItem
.
For example:
function toFeedItem(): FeedItem { return (new FeedItem()) ->title($this->title) ->description($this->excerpt) ->url(route('postcast.listen', $this->slug)); }
You can also create the feed item using an associative array if you prefer, by passing it as an argument to the FeedItem construct. For example:
function toFeedItem(): FeedItem { return new FeedItem([ 'title' => $this->title, 'description' => $this->excerpt, 'url' => route('podcast.listen', $this->slug) ]); }
Additional options are also available when creating your FeedItem:
/** * Will specify the URL for comments. */ FeedItem::comments(string $commentsUrl)
/** * The email address of the feed item author. * * Can be specified as an array or Collection of \LaravelSyndication\Feeds\Structure\Atom\Person objects, * or a single LaravelSyndication\Feeds\Structure\Atom\Person object. */ FeedItem::author(array|Collection|Person $author)
/** * Includes a media file to be included with an item. * * The enclosure method accepts either 2, or 4 arguments, depending on what data you pass: * * @param string $url The public URL to the enclosure item. * @param int|null $length Filesize in bytes -- if omitted, then an attempt to read the file is made. * @param string|null $type MIME type of the enclosure -- required if $filename is null. * @param string|null $filename Optional, can be left blank if $length and $type are specified. */ FeedItem::enclosure(string $url, ?string $type = null, ?string $filename = null, ?int $length = null)
/** * Specifies the value of the <id> tag on an <entry>. * * If a Uuid instance of string is passed, then it is prepended with 'urn:uuid:' * before being output. Otherwise, it is output as it is passed. * * This method can be omitted, and the value of the url() method will be used. * * Atom only. */ FeedItem::id(int|\Ramsey\Uuid\Uuid|string $idUri)
/** * Specifies the <content> tag of the <entry>. * * Atom only. */ FeedItem::content(null|string|\LaravelSyndication\Feeds\Structure\Atom\Content $content)
/** * When specified, the value of FeedItem::content() is ignored and content is * generated from a passed enclosure instead. * * Note: If used, this should be called after FeedItem::enclosure(). * * Atom only. */ FeedItem::contentFromEnclosure()
/** * Sets the <updated> tag on an entry. * * Atom only. */ FeedItem::updated(\Carbon\Carbon $updated)
/** * Atom: Sets the <published> tag on an entry. * RSS: Sets the <pubDate> tag on an item. */ FeedItem::published(\Carbon\Carbon $published)
/** * Sets the <rights> attribute on an entry. * * Atom only. */ FeedItem::copyright(string $copyright)
/** * Sets the value of the <category> tag on an <entry>. * * Atom only. */ FeedItem::category(string $term)
/** * Used to specify the <source> tag of an <entry>, for example if the <entry> * is a copy, or references another source. */ FeedItem::source(\LaravelSyndication\Feeds\Structure\Items\Atom\Source $source)
Below is an example of how you might configure a source:
FeedItem::source( new Source( id: route('podcast.listen', $this->getKey()), title: $this->title, updated: $this->updated_at, author: new Person(name: $this->author->name, email: $this->author->email) ) )
Fully configured model example
function toFeedItem(): FeedItem { return (new FeedItem()) // Using the ID method assumes that the model is making use of UUID // primary keys. ->id($this->getKey()) // These are the common fields between Atom and RSS fields. ->title($this->seo_title ?? $this->title) ->description($this->meta_description ?? $this->excerpt ?? $this->title) ->url(route('podcast.listen', $this->getKey())) // The URL for comments. // This is only used in RSS feeds and is not output as part of Atom. ->comments(route('podcast.single', $this->slug . '#comments')) // Atom feeds will output specific <author> tags, whereas RSS // will output a comma-separated list of email addresses. ->author([ new Person(name: $this->authorId->name, email: $this->authorId->email), new Person(name: $this->authorId->name, email: $this->authorId->email), ]) // Specifies the data to be used in the <enclosure> tag in an RSS feed. // can be used in conjunction with FeedItem::contentFromEnclosure() to // create the appropriate <content> tag on an Atom feed. ->enclosure( url: route('post.read', $this->slug), filename: storage_path('podcasts/' . $this->podcast_file_location) ) // ... Like this. ->contentFromEnclosure() // Sets the value of the <updated> tag. Only used as part of Atom feeds. ->updated($this->updated_at) // Sets the value of the <published> or <pubDate> tag in Atom and RSS // feeds respectively. ->published($this->published_at) // Copyright information relating specifically to an entry on an Atom feed // <entry> item. ->copyright("Copyright 2022 Acme Inc.") // Copyright information relating specifically to an entry on an Atom feed // <entry> item. ->category("Tech") // Builds the value of the <source> tag. // Statically typed here -- but you get the idea of what it does. ->source( new Source( id: 'https://example.com/some-unqiue-url-that-wont-change', title: 'The Title of The Source', updated: now(), author: new Person(name: "John Doe", email: "john@example.com", uri: "https://example.com/authors/john") ) ); }
Outputting meta tags to view
Add the following code to your blade views to output meta tags for registered feeds.
These use the alias of the facade at: LaravelSyndication\Facades\Syndicate
To meta tags for all registered feeds:
<head> {!! LaravelSyndication::meta() !!} </head>
To output meta tags for specific feeds:
<head> {!! LaravelSyndication::meta('podcasts', 'blog') !!} </head>