HomeRésuméOpen SourceWorkBlog

Blog RSS Feed

Sunday, 17 May 2026

Last month, I received a request to add an RSS feed to my blog. I am happy to share that I have added such a feed, available at /Blog/feed/rss.xml.

RSS (short for "Really Simple Syndication") is a web feed specification built on top of XML. Rather than generating the XML entirely from scratch (potentially using the PHP dom extension), I opted to use an open source library, laminas/laminas-feed, to create the XML content. While the library certainly helped, I ran into a few challenges along the way.

Laminas package

The first was the fact that the library unconditionally enables a "Slash" extension which adds some extra elements to the output. Rather than manually removing those elements from the resulting XML, I wanted to work within the constraints of the library API. The result? A custom extension manager that behaves differently based on the backtrace. The Laminas package still believes that the extension exists, but the slash extension is skipped during registration.

$old = Writer::getExtensionManager();
$manager = new class( $old ) extends ExtensionManager {
	public function has( $entryName ) {
		if ( $entryName === 'Slash\Renderer\Entry' ) {
			// Needs to return true when checking if the extension
			// exists, otherwise Laminas throws an exception
			$bt = debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS, 2 );
			if (
				$bt[1]['class'] === Writer::class
				&& $bt[1]['function'] === 'hasExtension'
			) {
				return true;
			}
			return false;
		}
		return parent::has( $entryName );
	}
};
Writer::setExtensionManager( $manager );

While I'm not the most pleased with this approach, it does work, and it presents a great example for my talk at PHPTek next week about what is and is not part of the public API of PHP libraries.

Another issue that I encountered was the unconditional addition of <guid> tags in the output - for these, I just removed them from the XML result with a post-processing step.

Of course, I could have used another library, or forked the Laminas package, but the Laminas package seemed like the easiest to use.

Forward compatibility

I had initially planned for the RSS feed to live at .../Blog/rss.xml, but realized that I might want to support other feed formats (e.g. Atom) in the future. To keep all feeds organized together, I put the RSS feed at .../Blog/feed/rss.xml, allowing other feeds to be added more easily. If you visit the feed page without specifying a feed format (/Blog/feed), a list of available feeds is shown; it is also shown when an unknown feed is requested.

Caching

Rather than regenerating the RSS feed on every request, I generate it ahead of time and store the resulting XML in my website's git repository. At runtime, the cached file is simply read from disk. Tests exist to ensure that the cached version remains up-to-date.

Thinking about this further, the same approach could be taken to every other known page on my website. Other than HTTP 404 and 405 pages that depend on what path or method were used, the rest of my pages are static and could be similarly cached. If performance ever becomes a concern, I may extend the same approach to the rest of the site.

Field testing

This blog post was published at the same time the RSS feed was created, so it does not serve as a test of the feed working properly. After PHPTek next week, I plan to write up another post about my experiences there, which will serve as a great opportunity to confirm that the RSS feed behaves as expected.