Feeder is a syndication framework for PHP 5+. It generates RSS 0.92, RSS 2.0 and Atom feeds from single data source. Bundled Text Feeder generates feeds from text files so you don’t have to do any coding at all to get your channel running. And, since it’s part of Feeder, it outputs in all three supported feed formats.
All Feeder classes and related data is released under public domain. If you use it I’ll appreciate a backlink to this page; if you have feedback – feel free to drop a comment.
Last Feeder update was on 30 May 2012 – version 1.2.
Download PHP Feeder. See also GitHub repo.
TextFeeder – feed generator from YAML files:
API – dynamically generating feed using chained calls (see also More on the chained form):
require_once 'chained.php';
Feed::make() ->title()->add('text', 'My Feed')->add('html', 'My <em>Feed</em>')->up()
->author()->name('Proger_XP')->email('proger.xp@gmail.com')->up()
->description()->add('text', 'Just another PHP Feed')->up()
->baseurl('http://'.$_SERVER['HTTP_HOST'].dirname($_SERVER['REQUEST_URI']).'/')
->entry() ->title()->add('text', 'My first post')->up()
->updated(strtotime('22 Jan 2011'))
->author()->name('Proger_XP')->email('proger.xp@gmail.com')->up()
->content()->add('text', 'Thinking about something to write...')
->add('html', 'Thinking about <em>something</em> to write…')
->entry() ->title()->add('text', 'Another filler')->up()
->updated(strtotime('23 May 2012'))
->author()->name('Proger_XP')->email('proger.xp@gmail.com')->up()
->contributor()->name('Camilo')->url('http://camilomm.deviantart.com')->up()
->content()->add('html', 'Why? Because he\'s my friend <img src="smile.png" />')
->feed()->atom();
API – dynamically generating feed from arrays:
$channel = array(
'title' => 'My Feed',
'author' => 'Proger_XP proger.xp@gmail.com http://proger.i-forge.net',
'description' => 'Just another PHP Feed',
'category' => 'http://example.com Category Label here.',
// it doesn't matter what follows "category" after a space - we need
// something so this array key is unique and won't override preceding one:
'category 2' => 'Second Label',
// it's only possible to set width, height and image URL using text form:
'logo' => '100x20 http://example.com/logo.png',
);
$entries = array(
array(
'title' => 'My first post',
'updated' => strtotime('22 Jan 2011'),
'author' => 'Proger_XP proger.xp@gmail.com',
'content' => 'Thinking about something to write...',
),
array(
'title' => 'Another filler',
'updated' => strtotime('23 May 2012'),
'content html' => 'Smile! <img src="smile.png" />',
),
);
$feeder = new Feeder;
$feeder->Channel()->SetFromArray($channel);
foreach ($entries as $i => $entry) {
$feeder->Entry($i, new FeedEntry($entry));
}
$output = new AtomFeed;
$output->Output($feeder);
API – dynamically generating feed by setting object properties directly (see also More on direct assignment):
$proger = new FeedPerson;
$proger->Name('Proger_XP');
$proger->URL('http://proger.i-forge.net');
$feeder = new Feeder;
$feeder->Channel()->Title()->Add('text', 'My Feed');
$feeder->Channel()->Author(0, $proger);
$feeder->Channel()->Description()->Add('text', 'Just another PHP Feed');
$entry = new FeedEntry;
$entry->Title()->Add('text', 'My first post');
$entry->Updated(strtotime('22 Jan 2011'));
$entry->Author(0, $proger);
$entry->Content()->Add('text', 'Thinking about something to write...');
$feeder->Entry(0, $entry);
$entry = new FeedEntry;
$entry->Title()->Add('text', 'Another filler');
$entry->Updated(strtotime('23 May 2012'));
$entry->Author(0, $proger);
$entry->Content()->Add('html', 'Why? Because he\'s my friend <img src="smile.png" />');
$feeder->Entry(1, $entry);
$output = new Rss092Feed;
$output->Output($feeder);
Basically, chained form allows you calling all methods found in FeedChannel and other classes. Note that in this form you can use lower case method names even though Feeder in itself uses CamelCase so the following calls are all valid: PHPlinkurl()
, PHPlinkURL()
, PHPLinkURL()
.
For example, channel inherits from FeedDescriptor (which is common for channel and entry classes) and has Description property as can be seen here. This property is of FeedText type. When we call channel’s PHPDescription()
method we retrieve its FeedText object on which we can call PHPAdd()
or any other method it has (check its source code in feeder.php – it’s easy to follow).
Feed::make() // we have FeedChannel
->title() // now FeedText
->add('text', 'My Feed') // adding a string in plain text form
->add('html', 'My <em>Feed</em>') // we still have FeedText, adding another string - in HTML form
->up() // to return to FeedChannel we call up()
->description() // we have FeedText representing channel description
->add(...) // adding a string to it just like above
Similarly, FeedChannel has Category (FeedCategory), Icon (FeedImage) and other object properties. Here’s how to change them:
require_once 'chained.php';
Feed::make()->category('http://example.com Category Label here.')
->category('Second Label')
->icon('100x20 http://example.com/icon.gif')
->logo()->imageurl('http://example.com/logo.png')
->linkurl('http://example.com/home')
->title('My Example Resource')
->description()->add('html', 'Its <em>description</em>.')->up()
->width(121)
->height(83)
->feed()->rss20();
The best reference to Feeder object properties and methods is its source code (feeder.php). Basic classes like FeedChannel, FeedEntry and their ancestors FeedDescriptor and FeedObjWithCommonAttrs are listed in this section.
For example, here’s how we can assign a feed two categories, icon and logo images:
$feeder = new Feeder;
$category = new FeedCategory;
$category->URL('http://example.com');
$category->Term('Category');
$category->Label('Label here.');
$feeder->Channel()->Category(0, $category);
$category = new FeedCategory;
$category->Term('Second');
$category->Label('Label');
$feeder->Channel()->Category(1, $category);
$icon = $feeder->Channel()->Icon();;
$icon->Width(100);
$icon->Height(20);
$icon->ImageURL('http://example.com/icon.gif');
$logo = $feeder->Channel()->Logo();
$logo->Width(121);
$logo->Height(83);
$logo->ImageURL('http://example.com/logo.png');
$logo->LinkURL('http://example.com/home');
$logo->Title()->Add('text', 'My Example Resource');
$logo->Description()->Add('html', 'Its <em>description</em>.');
$output = new Rss20Feed;
$output->Output($feeder);
TextFeeder lets you generate feeds from YAML text files (example) and serve them (examples: Atom, RSS 0.92, RSS 2.0) without the need to configure anything else. Details are given in the section below.
Note: TextFeeder automatically attaches files to entries if they have the same base name (without .yml or .txt extension) – you can use this to attach related images, archives or other data to your entries as can be seen in the sample feed.
All TextFeeder files use simple text YAML format to define key/value pairs. Such files can contain comments (starting with #), blank lines or multiline values – see format description for details. However, the basic element is just this: key: value.
Key names are case-insensitive.
confTitle: My First Feed
Description: >
Hello! Nice to see you're reading my feed.
Remember to visit my site when you've got a minute!
Copyright: (c) Myself
Copyright HTML: © <strong>My</strong>self
Link: http://myhome.net
Link related: text/html http://outside.com Friend's blog
Link self: http://myhome.net/feed/ This feed
Author: Myself me@myhome.net http://myhome.net
WebMaster: Myself me@myhome.net http://myhome.net
Contributor: Micky http://micky.mo
Language: en_GB
BaseURL: http://myhome.net
Note: Description property above was specified using YAML’s folded value. In this mode leading and trailing line spaces are trimmed away, single line breaks are collapsed into spaces and double line breaks become single line break.
Full list of available properties is described below; compiled, channel file can have the following properties: Logo, Icon, WebMaster, Rating, PubDate, SkipHours, SkipDays, Generator, TextInput, TTL, Cloud – plus the following common properties: Title, Description, Copyright, Links, Permalink, Author, Contributor, Category, Updated and Language, BaseURL. When using TextFeeder you can also define Data URL and modRewrite.
Sample 20120507 My first post.yml file:
confAuthor: Myself me@myhome.net http://myhome.net CommentsURL: 20120507-my-first-post/comments Content: > So this is my first post... Thinking of something to write so nothing here yet. Content HTML: > So this <em>is</em> my first post… Thinking of something to write so nothing here yet. <img src="smile.png" alt=":)" />
The above file specifies entry author, commenting URL and content in two representations – plain text and HTML. Feeder will choose the best available and convert provided content into an alternative representation if one is missing.
Full list of available properties is described below; compiled, channel file can have the following properties: Published, CommentsURL, Source, Content – plus the following common properties: Title, Description, Copyright, Links, Permalink, Author, Contributor, Category, Updated and Language, BaseURL.
Entry file name sets additional details:
TextFeeder class is used to load a channel and fill it with entries based on one or more text files in YAML-style format with .yml extension.
You you can also use .txt extension instead of .yml – in this case the feed directory must not contain any files named *.yml. Also note that you won’t be able to autoattach text content to channel and entries when using .txt.
To define a new feed create feed.yml or channel.yml file (both are aliases). A YAML file may contain more than one «document»; you can specify channel entries inside either the same channel file or using separate .yml (or .txt, see above) files – the latter being more convenient as TextFeeder will automatically detect and attach pictures, entry contain and other resources to them. TextFeeder will look for external files if the channel file contains only one document.
Apart from regular FeedChannel properties two special ones can be defined:
This mode is enabled automatically if channel file (feed.yml or channel.yml) contains just one document.
Each entry file must begin with publication date in format YYYYMMDD, for example: 20120325 We have opened.yml (or .txt) – entry is dated March 25th, 2012 and titled «We have opened». This time determines the sorting of feed entries prior to their loading.
When TextFeeder loads FeedChannel’s YAML file it sets the following properties to default values unless they were specified:
Entries have these defaults:
TextFeeder will automatically set some missing channel and entry fields based on the files in the feed’s root. List of properties getting attachments (X stands for «feed» if channel was defined in feed.yml or for «channel» if it’s in channel.yml; works for .txt feeds as well):
TextFeeder will also attach the following files for entries (X stands for entry .yml or .txt file name):
Feeder’s YAML files are similar to regular YAML but differ in the following aspects:
TextFeeder uses its own YAML loading routine which is independent of PHP YAML extension.
A YAML file consists of key-value pairs separated by colons followed with at least one space. Key names re case-insensitive and may contain spaces.
Each value can be defined in 3 ways:
confSingle line key: Hellp, world! Folded value: > A "Hello world" program is a computer program that outputs "Hello, world" on a display device. From Wikipedia, the free encyclopedia. Preserved: | select inner prior from 'Hello, world!' / 2 where level % 2 == 0
Blank lines were added for better readability but don’t affect the processing in any way. The first key contains simple «Hellp, world!» string (without surrounding spaces); the second value consists of two lines both of which have no leading whitespace; the third value still contains 3 lines where only the leading indentation was removed:
select inner prior from 'Hello, world!' / 2 where level % 2 == 0
YAML document supports comments – they must start with hash symbol (#) optionally preceded by spaces. Note that comments cannot appear inside values:
conf# This is a comment line lasting until the line break. # Another one. key: Regular value folded: > Even though there are more than one space preceding ">" symbol it's still a folding block. # This is not a comment... ...it's rather a part of it because it has indentation. # And this is a comment. key 3: Just another value.
Each YAML file can have multiple documents (for entries only the first is used (parsing is abandoned after meeting the first ---), for channels their presense control «one file per entry» mode). End of stream marker (...) skips the file remainder. For example:
confTitle: Our Channel
Title HTML: <em>Our</em> Channel
---
Published: 9 Nov 2011
Description: This is the first entry we have.
---
Published: 6 May 2012
Title: We're back!
The above YAML markup defines 3 documents each having 2 keys. If this is placed in feed.yml TextFeeder will treat the first document as the channel definition and second and third will be definitions of the two entries it has.
In TextFeeder, YAML markup allows multiple keys with the same name – in this case an array is created rather then the later overriding the preceding one:
confAuthor: Proger_XP proger.xp@gmail.com
Author: Freeman http://freeman-s.net
FeedChannel inherits from FeedDescriptor ⇒ FeedObjWithCommonAttrs; its properties:
Logo FeedImage | Full-size channel logo picture, Atom specification requires it to have 2:1 aspect ratio. |
---|---|
Icon FeedImage | Small channel icon, Atom specification requires it to have 1:1 aspect ratio. |
WebMasters array of FeedPerson | Webmasters responsible for this feed or overall site production. |
WebMaster FeedPerson | Shorthand property for setting WebMasters (see above). |
Rating string | Channel ratin – e.g. «SFW» which means «Safe For Work». |
PubDate timestamp | The next time this cahnnel will be updated with new contents. |
SkipHours array of integers | List of day hours (0-23) when this channel is guaranteed not to be updated with new contents (e.g. at night). |
SkipDays array of strings | List of week days («Monday», etc.) when this channel is guaranteed not to be updated with new contents (e.g. on weekends). |
Generator FeedGenerator | Information about software used to generate the feed. |
TextInput FeedTextInput | Describes a simple form – for example, used to search the main resource or find channel entries; RSS-only. |
TTL integer | Time-to-live – indicates how long (in minutes) this feed can be cached; RSS-only. |
Cloud FeedCloud | Defines the interface to a cloud subscribing protocol; RSS-only. |
FeedEntry inherits from FeedDescriptor ⇒ FeedObjWithCommonAttrs; its properties:
Published timestamp | Date when this entry was published. |
---|---|
CommentsURL string | URL with user comments regarding this entry. |
Source FeedContent | Refers to the channel from which this entry was delivered or based on. |
Content FeedContent | Actual entry content. |
FeedDescriptor inherits from FeedObjWithCommonAttrs and is a base class for FeedChannel and FeedEntry; its properties:
Title FeedText | Channel’s title or an entry headline. |
---|---|
Description FeedText | Channel’s description or an entry synopsis. |
Copyright string | Plain text string describing channel or entry copyright information. |
Links FeedLinks | Set of related resources or pages such as full HTML version of the entry or the location of the site home; Atom-only. |
Permalink string | URL of the channel home page or the full HTML entry page. If omitted, TextFeeder sets this to channel self link for channels and to entry URL (served by TextFeeder) for entries. |
Authors array of FeedPerson | Authors of this channel or entry. |
Author FeedPerson | Shorthand property for setting Authors (see above). |
Contributors array of FeedPerson | Contributors of this channel or entry; Atom-only. |
Contributor FeedPerson | Shorthand property for setting Contributors (see above); Atom-only. |
Categories array of FeedCategory | List of categories this channel or entry belongs to (like «cats», «cars», «computers»). |
Category FeedCategory | Shorthand property for setting Categories (see above). |
Updated timestamp | Time when this feed or entry was last updated. |
FeedObjWithCommonAttrs properties:
Language string | ISO-639 language code like «en», «ru» or «en_US», «ru_RU». |
---|---|
BaseURL string | Base address prepended to all links, images and other entities referring to some resources. Usually points to the main site’s home; Atom-only (using xml:base). |
Each Feeder object has an ability to assign properties from an array of strings or a single string. Array contains property keys like the ones described above plus an optional argument after a space; the format of values (strings) depends on the property being set.
TextFeeder allows setting of object proeprties based on YAML-style channel and entry definition files.
It’s also possible to assign values to objects of these classes using their PHPSetFromString('...')
method:
$image = new FeedImage;
$image->SetFromString('50*100 http://example.com/image.jpg');
$feeder = new Feeder;
$feeder->Channel()->Image()->SetFromString('50*100 http://example.com/image.jpg');
The above is just a short notation for setting object properties directly:
$image = new FeedImage;
$image->Width(50);
$image->Height(100);
$image->ImageURL('http://example.com/image.jpg');
FeedText inherits from FeedObjWithCommonAttrs; optional argument specifies case-insensitive text format (one of text, HTML, XHTML) which defaults to text. Example:
confDescription: Plain text.
Description HTML: >
<p>Markup is <em>fine</em>.</p>
When an unspecified format is requested FeedText attempts to transform the ones it has by quoting HTML in plain text to produce (X)HTML and by stripping HTML tags from an existing (X)HTML to produce its text representation.
FeedContent inherits from FeedText ⇒ FeedObjWithCommonAttrs; it has the same string format except that an URL instead of the actual content is allowed – for this start the value with the «at» symbol (@).
If you start the value with @@ it will be treated as a string with leading @ and the second one will be removed.
Content HTML: @http://example.com/2012-03-12-this-entry/ Content: @@This text content just starts with a single "at" symbol.
FeedLinks is a collection of related channel or entry resources or the link to the feed itself. Optional argument specifies relation – one of alternate, related, self, enclosure, via. Value has the following format:
[text/html] http://example.com/page.html [18839] Title lasts until the end.
FeedImage inherits from FeedObjWithCommonAttrs; optional argument is unused; string has the following format:
[[Width][xX*][Height]] [height] http://example.com/picture.gif
FeedImage inherits from FeedObjWithCommonAttrs; optional argument is unused; string has the following format:
[Joe Goth] [e@mail.com] [www.example.com]
If e-mail is present it separates the person’s name on the left and his home page on the right. If e-mail is omitted the entire string is treated as the person’s name unless it contains : or www. – in this case it’s split and the name is taken from the leading part while the rest goes to the URL:
http:// prefix is added to all URLs that don’t contain a colon (:).
FeedImage inherits from FeedObjWithCommonAttrs; optional argument is unused; string has the following format:
[(http://|www.)example.com] Category [Label lasting until the end.]
FeedImage inherits from FeedObjWithCommonAttrs; optional argument is unused; string has the following format:
[http://|www.]homepage Name with spaces [v]1[.0]
Order of its parts doesn’t matter as they are unambiguously detected:
FeedTextInput defines a small channel form with a text input field and a button. Optional argument is unused; value has the following format:
(http://www.)URL input_name Caption lasting until the end.
FeedCloud defines an interface to a cloud domain used to subscribe the user to new updates. Only supported by RSS. Optional argument is unused; value has the following format:
domain.ru [/]path/subscribe http-post [80] procedure