Digitaler Multifeed-Reader zeigt gebündelte Inhalte verschiedener Websites auf einem Bildschirm.
Übersichtliche Darstellung eines Multifeed-Readers, der Inhalte von verschiedenen Quellen in einer einzigen Ansicht zusammenfasst.

Wer die eigene Website oder das eigene Portfolio liebt, will Newsfeeds und Updates natürlich auch perfekt präsentieren – am besten gebündelt, aktuell und völlig ohne externe Tracker oder Werbung.

Hier kommt die ultimative Lösung: Ein eigener, selbstgehosteter RSS-Multifeed auf Basis von PHP – inklusive vollständigem Caching, YouTube-Support und einem schicken Dark-Grid-Layout.

Und das Beste: Der komplette Code ist Open Source und kann sofort verwendet werden!


🛠 Was wird benötigt?

  • Einen Webserver mit PHP-Unterstützung (z. B. Apache oder Nginx)
  • PHP 7.4 oder neuer
  • Zwei kleine Skripte:
    • combined_feed.php – kombiniert und cached die Feeds
    • reader.php – stellt die Feeds hübsch dar

📜 Kurz erklärt: Wie funktioniert das?

  • combined_feed.php sammelt verschiedene RSS- und Atom-Feeds, inklusive YouTube-Channel-Feeds, in einem einzigen, kombinierten RSS-Feed. Dabei wird ein Caching-System eingesetzt, um unnötige Serverlast zu vermeiden.
  • reader.php lädt diesen kombinierten Feed und zeigt ihn in einem modernen Grid-Layout im Dark Mode an – perfekt für mobile Geräte optimiert!

⚡ Schritt-für-Schritt Anleitung

  1. Dateien hochladen: Lade combined_feed.php und reader.php auf deinen Server – z. B. in ein Verzeichnis wie /multifeed/.
  2. Feed-Quellen anpassen: Öffne die combined_feed.php und trage deine eigenen RSS- oder Atom-Feed-Links ein (YouTube-Channel-Feeds sind ebenfalls möglich).
  3. Feed aufrufen: Im Browser https://deine-domain.de/multifeed/reader.php</code aufrufen – und fertig ist dein privater News-Hub!

🧩 Vollständiger Quellcode

📄 combined_feed.php

<?php
header("Content-Type: application/rss+xml; charset=UTF-8");

// === KONFIGURATION ===
$sources = [
    'https://matdan.de/blog/feed/',
    'https://portfolio.matdan.de/blog/feed/',
    'https://www.youtube.com/feeds/videos.xml?channel_id=UCFr2IhgmGbU9SzjWbCA8hRQ' // Ersetzt mit deiner YouTube-Channel-ID
];

$cache_file = __DIR__ . '/cache_combined_feed.xml';
$cache_lifetime = 1800; // 30 Minuten Cache

// === CACHE HANDLING ===
if (file_exists($cache_file) && (time() - filemtime($cache_file)) < $cache_lifetime) {
    echo file_get_contents($cache_file);
    exit;
}

// === FEED SAMMELN ===
$items = [];

foreach ($sources as $url) {
    $xml = @simplexml_load_file($url);
    if ($xml !== false) {
        if (isset($xml->channel->item)) {
            foreach ($xml->channel->item as $item) {
                $items[] = [
                    'title' => (string) $item->title,
                    'link' => (string) $item->link,
                    'description' => (string) $item->description,
                    'pubDate' => strtotime((string) $item->pubDate)
                ];
            }
        } elseif (isset($xml->entry)) {
            // YouTube Feed (Atom)
            foreach ($xml->entry as $entry) {
                $items[] = [
                    'title' => (string) $entry->title,
                    'link' => (string) $entry->link['href'],
                    'description' => (string) $entry->content,
                    'pubDate' => strtotime((string) $entry->published)
                ];
            }
        }
    }
}

// === SORTIEREN ===
usort($items, function($a, $b) {
    return $b['pubDate'] - $a['pubDate'];
});

// === RSS GENERIEREN ===
$output = '<?xml version="1.0" encoding="UTF-8"?>' . "\n";
$output .= '<rss version="2.0">' . "\n";
$output .= '<channel>' . "\n";
$output .= '<title>matdan MegaFeed</title>' . "\n";
$output .= '<link>https://matdan.de/</link>' . "\n";
$output .= '<description>Alle neuesten Inhalte von matdan.de und Portfolio</description>' . "\n";

foreach (array_slice($items, 0, 20) as $item) {
    $output .= '<item>' . "\n";
    $output .= '<title>' . htmlspecialchars($item['title']) . '</title>' . "\n";
    $output .= '<link>' . htmlspecialchars($item['link']) . '</link>' . "\n";
    $output .= '<description><![CDATA[' . $item['description'] . ']]></description>' . "\n";
    $output .= '<pubDate>' . date(DATE_RSS, $item['pubDate']) . '</pubDate>' . "\n";
    $output .= '</item>' . "\n";
}

$output .= '</channel>' . "\n";
$output .= '</rss>';

// === CACHE SPEICHERN ===
file_put_contents($cache_file, $output);

// === FEED AUSGEBEN ===
echo $output;
?>

📄 reader.php

<?php
$feed_url = "https://matdan.de/multifeed/combined_feed.php";
$feed_content = @simplexml_load_file($feed_url);
?>
<!DOCTYPE html>
<html lang="de">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>matdan Multifeed</title>
    <style>
        body {
            background-color: #121212;
            color: #e0e0e0;
            font-family: Arial, sans-serif;
            margin: 0;
            padding: 20px;
        }
        h1 {
            text-align: center;
            margin-bottom: 40px;
            font-size: 2em;
            color: #00bcd4;
        }
        .feed-container {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
            gap: 20px;
        }
        .feed-item {
            background: #1e1e1e;
            border: 1px solid #333;
            border-radius: 12px;
            padding: 20px;
            transition: transform 0.2s;
        }
        .feed-item:hover {
            transform: scale(1.03);
            border-color: #00bcd4;
        }
        .feed-item a {
            color: #00bcd4;
            text-decoration: none;
            font-size: 1.2em;
            font-weight: bold;
        }
        .feed-item a:hover {
            text-decoration: underline;
        }
        .feed-date {
            font-size: 0.9em;
            color: #bbb;
            margin-top: 10px;
        }
        .feed-description {
            margin-top: 10px;
            font-size: 1em;
            color: #ccc;
        }
        .footer {
            margin-top: 50px;
            text-align: center;
            font-size: 0.8em;
            color: #666;
        }
    </style>
</head>
<body>

<h1>🔥 matdan Multifeed 🔥</h1>

<div class="feed-container">
<?php if ($feed_content && isset($feed_content->channel->item)): ?>
    <?php foreach ($feed_content->channel->item as $item): ?>
        <div class="feed-item">
            <a href="<?= htmlspecialchars($item->link) ?>" target="_blank"><?= htmlspecialchars($item->title) ?></a>
            <div class="feed-date"><?= date('d.m.Y H:i', strtotime($item->pubDate)) ?></div>
            <div class="feed-description"><?= strip_tags(substr($item->description, 0, 150)) ?>...</div>
        </div>
    <?php endforeach; ?>
<?php else: ?>
    <p>Leider konnten keine Feed-Daten geladen werden. 😢</p>
<?php endif; ?>
</div>

<div class="footer">
    © <?= date('Y') ?> matdan.de – Alle Rechte vorbehalten.
</div>

</body>
</html>

🚀 Fazit

Mit diesem kleinen, aber mächtigen Setup entsteht in Minuten ein moderner, privater RSS-Aggregator, der beliebig erweitert werden kann – z. B. um weitere Quellen, Kategorien, Caching-Optimierungen oder eigene Suchfunktionen.

Keine Tracker, keine Werbung, volle Kontrolle. Genau so, wie ein smarter Webauftritt heute aussehen sollte! 🚀

Von Daniel Mattick

Ich bin Daniel, Technik-Enthusiast mit einer Vorliebe für Automatisierung, Skripting und alles, was IT-Prozesse einfacher macht. Ich bastle gerne an Lösungen, die den Alltag in der IT erleichtern – egal ob für Profis oder Neugierige, die sich in die Materie einarbeiten wollen. Dabei teile ich mein Wissen und meine Skripte in der IT Toolbox, weil ich finde: Gute Lösungen sollte man nicht für sich behalten!

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert