ویژگی تصویر

چرا RSS Feed با PHP بسازیم؟

  /  PHP   /  ساخت RSS Feed با PHP
بنر تبلیغاتی الف
آموزش PHP

فایل RSS ابزار ساده و استانداردی برای انتشار به‌روز‌رسانی‌ها است که توسط خبرخوان‌ها (RSS readers)، اپلیکیشن‌ها و موتورهای جستجو استفاده می‌شود. ساخت RSS با PHP به شما کنترل کامل روی خروجی، فیلترها، و امنیت می‌دهد. در این مقاله روش‌های عملی، نمونه‌کد و نکات بهینه‌سازی را به زبان ساده توضیح می‌دهیم.

ساختار کلی یک RSS Feed

یک فید RSS مبتنی بر XML است و حداقل باید عناصر زیر را داشته باشد:

  • <rss version=”2.0″>
  • <channel> شامل <title>, <link>, <description>, <lastBuildDate> و یک یا چند <item>
  • در هر <item> حداقل <title> و <link> و معمولاً <description> و <pubDate> و <guid>

نمونه ساده با PHP (آغاز سریع)

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

$posts = [
    [
        'title' => 'اولین پست',
        'link' => 'https://example.com/post/1',
        'description' => 'خلاصه‌ای از اولین پست.',
        'date' => strtotime('2025-01-01 10:00')
    ],
    // ... سایر پست‌ها
];

echo '<?xml version="1.0" encoding="UTF-8"?>';
echo '<rss version="2.0">';
echo '<channel>';
echo '<title>عنوان سایت</title>';
echo '<link>https://example.com</link>';
echo '<description>توضیحات سایت</description>';
echo '<lastBuildDate>' . date('r') . '</lastBuildDate>';

foreach ($posts as $post) {
    echo '<item>';
    echo '<title>' . htmlspecialchars($post['title']) . '</title>';
    echo '<link>' . htmlspecialchars($post['link']) . '</link>';
    echo '<description><![CDATA[' . $post['description'] . ']]></description>';
    echo '<pubDate>' . date('r', $post['date']) . '</pubDate>';
    echo '<guid>' . htmlspecialchars($post['link']) . '</guid>';
    echo '</item>';
}

echo '</channel>';
echo '</rss>';

این اسکریپت ساده یک فید RSS تولید می‌کند. از header برای تعیین نوع محتوا و از htmlspecialchars برای جلوگیری از آسیب XML استفاده شده است. توضیحات طولانی را در قرار می‌دهیم تا شامل تگ‌های HTML نیز باشند.

خواندن داده‌ها از دیتابیس با PDO

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

$pdo = new PDO('mysql:host=localhost;dbname=site;charset=utf8mb4', 'user', 'pass', [
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
]);

$stmt = $pdo->prepare('SELECT id, title, slug, summary, published_at FROM posts WHERE published = 1 ORDER BY published_at DESC LIMIT 20');
$stmt->execute();
$posts = $stmt->fetchAll(PDO::FETCH_ASSOC);

echo '<?xml version="1.0" encoding="UTF-8"?>';
echo '<rss version="2.0"><channel>';
echo '<title>وبلاگ من</title>';
echo '<link>https://example.com</link>';
echo '<description>آخرین پست‌ها</description>';
echo '<lastBuildDate>' . date('r') . '</lastBuildDate>';

foreach ($posts as $post) {
    $link = 'https://example.com/post/' . $post['slug'];
    echo '<item>';
    echo '<title>' . htmlspecialchars($post['title']) . '</title>';
    echo '<link>' . htmlspecialchars($link) . '</link>';
    echo '<description><![CDATA[' . $post['summary'] . ']]></description>';
    echo '<pubDate>' . date('r', strtotime($post['published_at'])) . '</pubDate>';
    echo '<guid isPermaLink="false">' . 'post-' . $post['id'] . '</guid>';
    echo '</item>';
}

echo '</channel></rss>';

این نسخه از PDO استفاده می‌کند تا داده‌ها را ایمن از دیتابیس بگیرد. توجه کنید که GUID را به صورت شناسه یکتا (نه لینک) تولید کردیم و summary را در قرار دادیم.

بهینه‌سازی: کش کردن فید و هدرهای HTTP

برای کاهش بار دیتابیس و سرعت بیشتر، فید را کش کنید و از هدرهای HTTP مثل Last-Modified یا ETag استفاده کنید تا در صورت عدم تغییر فید، کلاینت‌ها از کش محلی خود استفاده کنند.

<?php
// مثال ساده کش فایل
$cacheFile = __DIR__ . '/cache/rss.xml';
$cacheTtl = 300; // 5 دقیقه

if (file_exists($cacheFile) && time() - filemtime($cacheFile) < $cacheTtl) {
    header('Content-Type: application/rss+xml; charset=UTF-8');
    echo file_get_contents($cacheFile);
    exit;
}

// در غیر این صورت فید را بسازید (کد ساخت فید مانند قبل) و سپس در کش ذخیره کنید
$rssContent = '<?xml version="1.0" encoding="UTF-8"?>...'; // تولید فید
file_put_contents($cacheFile, $rssContent);
header('Content-Type: application/rss+xml; charset=UTF-8');
echo $rssContent;

این روش ساده فایل خروجی را برای ۵ دقیقه کش می‌کند. در پروژه‌های بزرگ‌تر می‌توانید از Redis یا سیستم فایل با قفل‌گذاری بهتر استفاده کنید تا رقابت نوشتن جلوگیری شود.

ایمن‌سازی و استانداردها

  • همیشه از htmlspecialchars برای فیلدهای متنی که مستقیماً در XML قرار می‌گیرند استفاده کنید.
  • وقتی متن شامل HTML است، از برای محتوای description بهره ببرید.
  • تاریخ‌ها را با فرمت RFC-2822 (در PHP با date(‘r’)) خروجی دهید تا اکثر کلاینت‌ها سازگار باشند.
  • برای هر آیتم GUID منحصربه‌فرد تعیین کنید؛ اگر GUID همان لینک است، isPermaLink=”true” قابل استفاده است.
  • برای جلوگیری از خطاهای XML، کاراکترهای کنترلی را حذف یا جایگزین کنید یا از DOMDocument/SimpleXML برای ساخت XML استفاده کنید.

نمونه با DOMDocument برای خروجی سالم‌تر

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

$dom = new DOMDocument('1.0', 'UTF-8');
$rss = $dom->createElement('rss');
$rss->setAttribute('version', '2.0');
$dom->appendChild($rss);

$channel = $dom->createElement('channel');
$rss->appendChild($channel);

$channel->appendChild($dom->createElement('title', 'وبلاگ من'));
$channel->appendChild($dom->createElement('link', 'https://example.com'));
$channel->appendChild($dom->createElement('description', 'توضیحات سایت'));
$channel->appendChild($dom->createElement('lastBuildDate', date('r')));

// فرض کنید $posts از قبل آمده
foreach ($posts as $p) {
    $item = $dom->createElement('item');
    $item->appendChild($dom->createElement('title', $p['title']));
    $item->appendChild($dom->createElement('link', 'https://example.com/post/' . $p['slug']));

    $desc = $dom->createElement('description');
    $desc->appendChild($dom->createCDATASection($p['summary']));
    $item->appendChild($desc);

    $item->appendChild($dom->createElement('pubDate', date('r', strtotime($p['published_at']))));
    $item->appendChild($dom->createElement('guid', 'post-' . $p['id']));
    $channel->appendChild($item);
}

echo $dom->saveXML();

DOMDocument تضمین می‌کند که ساختار XML معتبر است و خودِ کلاس کار پاک‌سازی و فرار از کاراکترهای مشکل‌ساز را بهتر مدیریت می‌کند. برای محتوای HTML از CDATA استفاده شده است.

جمع‌بندی و بهترین تمرین‌ها

  • از هدر Content-Type صحیح استفاده کنید: application/rss+xml; charset=UTF-8.
  • از caching برای کاهش بار سرور بهره ببرید.
  • تاریخ‌ها را با فرمت RFC-2822 خروجی دهید و GUID‌های یکتا تولید کنید.
  • در پروژه‌های حساس امنیتی، از PDO و prepared statements برای واکشی محتوا استفاده کنید.
  • برای تولید XML معتبر، از DOMDocument یا SimpleXML استفاده کنید.

با رعایت این نکات می‌توانید فیدی سریع، سازگار و قابل اعتماد برای کاربران و سرویس‌های دیگر ایجاد کنید.

آیا این مطلب برای شما مفید بود ؟

خیر
بله
موضوعات شما در انجمن: