-
Notifications
You must be signed in to change notification settings - Fork 94
Plain PHP
Rumen Damyanov edited this page Jul 29, 2025
·
1 revision
This guide shows how to use php-feed in vanilla PHP applications without any framework.
Install the package via Composer:
composer require rumenx/php-feed
The simplest way to create a feed in plain PHP:
<?php
require 'vendor/autoload.php';
use Rumenx\Feed\FeedFactory;
// Create feed
$feed = FeedFactory::create();
$feed->setTitle('My Blog');
$feed->setDescription('Latest posts from my blog');
$feed->setLink('https://example.com');
$feed->setLanguage('en');
// Add items
$feed->addItem([
'title' => 'Hello World',
'author' => 'John Doe',
'link' => 'https://example.com/hello-world',
'pubdate' => date('c'),
'description' => 'My first blog post!'
]);
$feed->addItem([
'title' => 'PHP Feeds Tutorial',
'author' => 'Jane Smith',
'link' => 'https://example.com/php-feeds',
'pubdate' => date('c', strtotime('-1 day')),
'description' => 'Learn how to create RSS feeds in PHP.'
]);
// Output RSS feed
header('Content-Type: application/rss+xml; charset=utf-8');
echo $feed->render('rss');
Creating feeds from database content:
<?php
require 'vendor/autoload.php';
use Rumenx\Feed\FeedFactory;
use PDO;
// Database connection
$pdo = new PDO('mysql:host=localhost;dbname=blog', $username, $password, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
]);
// Create feed
$feed = FeedFactory::create();
$feed->setTitle('My Blog - Latest Posts');
$feed->setDescription('The latest posts from my blog');
$feed->setLink('https://myblog.com');
$feed->setLanguage('en');
// Fetch posts from database
$stmt = $pdo->prepare('
SELECT
p.title,
p.slug,
p.excerpt,
p.created_at,
u.name as author_name
FROM posts p
JOIN users u ON p.author_id = u.id
WHERE p.published = 1
ORDER BY p.created_at DESC
LIMIT 20
');
$stmt->execute();
$posts = $stmt->fetchAll();
// Add posts to feed
foreach ($posts as $post) {
$feed->addItem([
'title' => $post['title'],
'author' => $post['author_name'],
'link' => 'https://myblog.com/posts/' . $post['slug'],
'pubdate' => $post['created_at'],
'description' => $post['excerpt']
]);
}
// Output feed
header('Content-Type: application/rss+xml; charset=utf-8');
echo $feed->render('rss');
Creating different feeds for different content types:
<?php
require 'vendor/autoload.php';
use Rumenx\Feed\FeedFactory;
use PDO;
// Database connection
$pdo = new PDO('mysql:host=localhost;dbname=blog', $username, $password);
// Determine which feed to generate
$feedType = $_GET['type'] ?? 'posts';
switch ($feedType) {
case 'news':
generateNewsFeed($pdo);
break;
case 'tutorials':
generateTutorialsFeed($pdo);
break;
case 'posts':
default:
generatePostsFeed($pdo);
break;
}
function generatePostsFeed(PDO $pdo): void
{
$feed = FeedFactory::create();
$feed->setTitle('My Blog - All Posts');
$feed->setDescription('Latest blog posts');
$feed->setLink('https://myblog.com');
$posts = fetchContent($pdo, 'posts', 20);
addItemsToFeed($feed, $posts, 'posts');
outputFeed($feed);
}
function generateNewsFeed(PDO $pdo): void
{
$feed = FeedFactory::create();
$feed->setTitle('My Blog - News');
$feed->setDescription('Latest news updates');
$feed->setLink('https://myblog.com/news');
$news = fetchContent($pdo, 'news', 15);
addItemsToFeed($feed, $news, 'news');
outputFeed($feed);
}
function generateTutorialsFeed(PDO $pdo): void
{
$feed = FeedFactory::create();
$feed->setTitle('My Blog - Tutorials');
$feed->setDescription('Programming tutorials');
$feed->setLink('https://myblog.com/tutorials');
$tutorials = fetchContent($pdo, 'tutorials', 10);
addItemsToFeed($feed, $tutorials, 'tutorials');
outputFeed($feed);
}
function fetchContent(PDO $pdo, string $table, int $limit): array
{
$stmt = $pdo->prepare("
SELECT title, slug, excerpt, created_at, author_name
FROM {$table}
WHERE published = 1
ORDER BY created_at DESC
LIMIT ?
");
$stmt->execute([$limit]);
return $stmt->fetchAll();
}
function addItemsToFeed(object $feed, array $items, string $type): void
{
foreach ($items as $item) {
$feed->addItem([
'title' => $item['title'],
'author' => $item['author_name'],
'link' => "https://myblog.com/{$type}/" . $item['slug'],
'pubdate' => $item['created_at'],
'description' => $item['excerpt']
]);
}
}
function outputFeed(object $feed): void
{
header('Content-Type: application/rss+xml; charset=utf-8');
echo $feed->render('rss');
}
Creating feeds from file-based content (like a static blog):
<?php
require 'vendor/autoload.php';
use Rumenx\Feed\FeedFactory;
class MarkdownBlog
{
private string $postsDir;
public function __construct(string $postsDir)
{
$this->postsDir = $postsDir;
}
public function generateFeed(): string
{
$feed = FeedFactory::create();
$feed->setTitle('My Static Blog');
$feed->setDescription('Posts from my markdown blog');
$feed->setLink('https://myblog.com');
$posts = $this->loadPosts();
foreach ($posts as $post) {
$feed->addItem([
'title' => $post['title'],
'author' => $post['author'] ?? 'Blog Author',
'link' => 'https://myblog.com/posts/' . $post['slug'],
'pubdate' => $post['date'],
'description' => $post['excerpt']
]);
}
return $feed->render('rss');
}
private function loadPosts(): array
{
$posts = [];
$files = glob($this->postsDir . '/*.md');
foreach ($files as $file) {
$content = file_get_contents($file);
$post = $this->parseMarkdownPost($content);
$post['slug'] = basename($file, '.md');
$posts[] = $post;
}
// Sort by date descending
usort($posts, fn($a, $b) => strtotime($b['date']) - strtotime($a['date']));
return array_slice($posts, 0, 20);
}
private function parseMarkdownPost(string $content): array
{
// Simple front matter parser
if (strpos($content, '---') === 0) {
$parts = explode('---', $content, 3);
$frontMatter = $parts[1];
$body = $parts[2] ?? '';
$post = [];
foreach (explode("\n", $frontMatter) as $line) {
if (strpos($line, ':') !== false) {
[$key, $value] = explode(':', $line, 2);
$post[trim($key)] = trim($value);
}
}
$post['excerpt'] = substr(strip_tags($body), 0, 200) . '...';
return $post;
}
return [
'title' => 'Untitled',
'date' => date('c'),
'excerpt' => substr($content, 0, 200) . '...'
];
}
}
// Usage
$blog = new MarkdownBlog(__DIR__ . '/posts');
header('Content-Type: application/rss+xml; charset=utf-8');
echo $blog->generateFeed();
Create a simple feed aggregator:
<?php
require 'vendor/autoload.php';
use Rumenx\Feed\FeedFactory;
class FeedAggregator
{
private array $sources;
public function __construct(array $sources)
{
$this->sources = $sources;
}
public function generateAggregatedFeed(): string
{
$feed = FeedFactory::create();
$feed->setTitle('Aggregated Tech News');
$feed->setDescription('Latest posts from various tech blogs');
$feed->setLink('https://myaggregator.com');
$allItems = [];
foreach ($this->sources as $source) {
$items = $this->fetchFeedItems($source['url']);
foreach ($items as $item) {
$item['source'] = $source['name'];
$allItems[] = $item;
}
}
// Sort by date descending
usort($allItems, fn($a, $b) => strtotime($b['pubdate']) - strtotime($a['pubdate']));
// Add top 20 items
foreach (array_slice($allItems, 0, 20) as $item) {
$feed->addItem($item);
}
return $feed->render('rss');
}
private function fetchFeedItems(string $feedUrl): array
{
$xml = @simplexml_load_file($feedUrl);
if (!$xml) {
return [];
}
$items = [];
if (isset($xml->channel->item)) {
// RSS feed
foreach ($xml->channel->item as $item) {
$items[] = [
'title' => (string) $item->title,
'link' => (string) $item->link,
'description' => (string) $item->description,
'author' => (string) ($item->author ?? 'Unknown'),
'pubdate' => (string) $item->pubDate
];
}
} elseif (isset($xml->entry)) {
// Atom feed
foreach ($xml->entry as $entry) {
$items[] = [
'title' => (string) $entry->title,
'link' => (string) $entry->link['href'],
'description' => (string) $entry->summary,
'author' => (string) ($entry->author->name ?? 'Unknown'),
'pubdate' => (string) $entry->updated
];
}
}
return $items;
}
}
// Usage
$sources = [
['name' => 'TechCrunch', 'url' => 'http://feeds.feedburner.com/TechCrunch'],
['name' => 'Ars Technica', 'url' => 'http://feeds.arstechnica.com/arstechnica/index'],
['name' => 'The Verge', 'url' => 'https://www.theverge.com/rss/index.xml']
];
$aggregator = new FeedAggregator($sources);
header('Content-Type: application/rss+xml; charset=utf-8');
echo $aggregator->generateAggregatedFeed();
Adding simple file-based caching:
<?php
require 'vendor/autoload.php';
use Rumenx\Feed\FeedFactory;
class CachedFeedGenerator
{
private string $cacheDir;
private int $cacheTime;
public function __construct(string $cacheDir = './cache', int $cacheTime = 3600)
{
$this->cacheDir = $cacheDir;
$this->cacheTime = $cacheTime;
if (!is_dir($cacheDir)) {
mkdir($cacheDir, 0755, true);
}
}
public function getFeed(string $feedType = 'posts'): string
{
$cacheFile = $this->cacheDir . '/' . $feedType . '.xml';
// Check if cache exists and is still valid
if (file_exists($cacheFile) && (time() - filemtime($cacheFile)) < $this->cacheTime) {
return file_get_contents($cacheFile);
}
// Generate new feed
$feedXml = $this->generateFeed($feedType);
// Save to cache
file_put_contents($cacheFile, $feedXml);
return $feedXml;
}
private function generateFeed(string $feedType): string
{
$feed = FeedFactory::create();
switch ($feedType) {
case 'news':
$feed->setTitle('My Blog - News');
$feed->setDescription('Latest news updates');
$data = $this->getNewsData();
break;
case 'tutorials':
$feed->setTitle('My Blog - Tutorials');
$feed->setDescription('Programming tutorials');
$data = $this->getTutorialData();
break;
default:
$feed->setTitle('My Blog - Posts');
$feed->setDescription('Latest blog posts');
$data = $this->getPostData();
break;
}
$feed->setLink('https://myblog.com');
foreach ($data as $item) {
$feed->addItem($item);
}
return $feed->render('rss');
}
private function getPostData(): array
{
// Simulate database call
return [
[
'title' => 'Latest Post',
'author' => 'Author Name',
'link' => 'https://myblog.com/latest-post',
'pubdate' => date('c'),
'description' => 'This is the latest post content.'
]
];
}
private function getNewsData(): array
{
return [
[
'title' => 'Breaking News',
'author' => 'News Reporter',
'link' => 'https://myblog.com/breaking-news',
'pubdate' => date('c'),
'description' => 'Important news update.'
]
];
}
private function getTutorialData(): array
{
return [
[
'title' => 'PHP Tutorial',
'author' => 'Tutorial Author',
'link' => 'https://myblog.com/php-tutorial',
'pubdate' => date('c'),
'description' => 'Learn PHP programming.'
]
];
}
}
// Usage
$generator = new CachedFeedGenerator();
$feedType = $_GET['type'] ?? 'posts';
header('Content-Type: application/rss+xml; charset=utf-8');
echo $generator->getFeed($feedType);
A more advanced example with configuration files:
<?php
require 'vendor/autoload.php';
use Rumenx\Feed\FeedFactory;
class ConfigurableFeedGenerator
{
private array $config;
public function __construct(string $configFile)
{
$this->config = json_decode(file_get_contents($configFile), true);
}
public function generateFeed(string $feedName): string
{
if (!isset($this->config['feeds'][$feedName])) {
throw new InvalidArgumentException("Feed '{$feedName}' not found");
}
$feedConfig = $this->config['feeds'][$feedName];
$feed = FeedFactory::create();
$feed->setTitle($feedConfig['title']);
$feed->setDescription($feedConfig['description']);
$feed->setLink($feedConfig['link']);
$feed->setLanguage($feedConfig['language'] ?? 'en');
$data = $this->loadData($feedConfig['source']);
foreach ($data as $item) {
$feed->addItem($item);
}
return $feed->render($feedConfig['format'] ?? 'rss');
}
private function loadData(array $source): array
{
switch ($source['type']) {
case 'database':
return $this->loadFromDatabase($source);
case 'json':
return $this->loadFromJson($source['file']);
case 'csv':
return $this->loadFromCsv($source['file']);
default:
return [];
}
}
private function loadFromDatabase(array $config): array
{
$pdo = new PDO($config['dsn'], $config['username'], $config['password']);
$stmt = $pdo->prepare($config['query']);
$stmt->execute();
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
private function loadFromJson(string $file): array
{
return json_decode(file_get_contents($file), true);
}
private function loadFromCsv(string $file): array
{
$data = [];
if (($handle = fopen($file, 'r')) !== false) {
$header = fgetcsv($handle);
while (($row = fgetcsv($handle)) !== false) {
$data[] = array_combine($header, $row);
}
fclose($handle);
}
return $data;
}
}
// Example config.json:
/*
{
"feeds": {
"blog": {
"title": "My Blog",
"description": "Latest blog posts",
"link": "https://myblog.com",
"language": "en",
"format": "rss",
"source": {
"type": "database",
"dsn": "mysql:host=localhost;dbname=blog",
"username": "user",
"password": "pass",
"query": "SELECT title, link, description, author, pubdate FROM posts WHERE published = 1 ORDER BY pubdate DESC LIMIT 20"
}
}
}
}
*/
// Usage
$generator = new ConfigurableFeedGenerator('config.json');
$feedName = $_GET['feed'] ?? 'blog';
header('Content-Type: application/rss+xml; charset=utf-8');
echo $generator->generateFeed($feedName);
- Learn about Caching for better performance
- See Custom Views for custom templates
- Check out Advanced Features for more options