Skip to content

Plain PHP

Rumen Damyanov edited this page Jul 29, 2025 · 1 revision

Plain PHP Examples

This guide shows how to use php-feed in vanilla PHP applications without any framework.

Installation

Install the package via Composer:

composer require rumenx/php-feed

Basic Example

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');

Database Integration

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');

Multiple Feeds

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');
}

File-based Content

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();

RSS Reader / Feed Aggregator

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();

Caching Implementation

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);

Configuration-based Feed Generator

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);

Next Steps

Clone this wiki locally