debril/rss-atom-bundle

Symfony的RSS / Atom和JSONFeed支持

安装数: 1,083,070

依赖者: 7

建议者: 0

安全: 0

星标: 139

关注者: 7

分支: 49

开放问题: 4

类型:symfony-bundle


README

SensioLabsInsight Latest Stable Version Download Count Build Status Scrutinizer Code Quality Code Coverage

RssAtomBundle是一个用于Symfony的Bundle,旨在轻松访问和提供JSON / RSS / Atom馈送。它基于feed-io构建,并具有以下功能:

  • 检测馈送格式(JSON / RSS / Atom)
  • 支持封装
  • 构建了通用的StreamController来编写所有您的馈送。如果自上次访问以来馈送没有更改,则此控制器能够发送304 HTTP代码
  • 读取馈送时支持HTTP头,以节省网络流量
  • 内容过滤以获取最新条目
  • 多馈送写入
  • 能够将doctrine用作数据源
  • PSR兼容的日志记录
  • DateTime检测和转换
  • Guzzle客户端集成

了解有关新版本和即将推出的功能的信息: http://debril.org/category/rss-atom-bundle

您可以通过其演示尝试rss-atom-bundle。

安装

依赖关系

作为Symfony Bundle,RssAtomBundle必须使用Composer安装。如果您不了解Composer,请参阅其网站:https://getcomposer.org.cn/

您的应用程序使用Symfony 3.3或更高版本

激活Symfony的contrib recipes并使用Composer需要bundle

composer config extra.symfony.allow-contrib true
composer require debril/rss-atom-bundle

就是这样。要检查安装,您可以在浏览器中访问http://localhost:8000/rss以启动您的应用程序。您应该看到一个模拟的RSS流。

如果您的应用程序使用Symfony < 3.3

使用Composer安装bundle

composer require debril/rss-atom-bundle

在app/config/routing.yml中添加bundle的路由配置

rssatom:
    resource: "@DebrilRssAtomBundle/Resources/config/routing.yml"

编辑app/AppKernel.php以在registerBundles()方法中注册bundle,如上所述

class AppKernel extends Kernel
{

    public function registerBundles()
    {
        $bundles = array(
            new Symfony\Bundle\FrameworkBundle\FrameworkBundle(),
            // ...
            // register the bundle here
            new Debril\RssAtomBundle\DebrilRssAtomBundle(),

用法

rss-atom-bundle旨在通过feed-io读取互联网上的馈送,并使用feed-io发布自己的馈送。feed-io提供了两个接口,每个接口都专门用于馈送的消费和发布。

获取FeedIo实例

您可以通过依赖注入或服务容器获取FeedIo\FeedIo实例。

依赖注入(强烈推荐)

namespace App\Feed;

class Consumer
{

    /**
     * @type \FeedIo\FeedIo
     */
    private $feedIo;

    public function __construct(FeedIo $feedIo)
    {
        $this->feedIo = $feedIo;
    }
}

服务容器

在您有权访问服务容器的任何地方

<?php
    // get feedio
    $feedIo = $this->container->get('feedio');

阅读馈送

要读取馈送,您需要使用提供两个方法的feedio服务:read()readSince()。此服务基于FeedIo

使用read()

read()旨在提供一个全新的Feed实例或任何实现了FeedInterface接口的自己的对象。它接受三个参数

  • $url:您想读取的RSS/Atom馈送的URL(例如:https://php.ac.cn/feed.atom
  • $feed(可选):一个FeedInterface实例。默认值是一个新的\FeedIo\Feed实例
  • $modifiedSince (可选) : 你最后一次读取此源的时间。这有助于只获取你上次访问后发布的文章。

使用一个名为 $feedIo\FeedIo\FeedIo 实例

<?php
    // this date is used to fetch only the latest items
    $modifiedSince = new \DateTime($date);

    // the feed you want to read
    $url = 'http://host.tld/feed';

    // now fetch its (fresh) content
    $feed = $feedIo->read($url, new \Acme\Entity\Feed, $modifiedSince)->getFeed();

    foreach ( $feed as $item ) {
        echo "item title : {$item->getTitle()} \n ";
        // getMedias() returns enclosures if any
        $medias = $item->getMedias();
    }

?>

read()$url 提取源并移除 $modifiedSince 之前的项目。如果你是第一次阅读这个源,你必须指定一个足够久远的日期以保留所有项目。此方法不会循环直到到达 $modifiedSince,它只会进行一次击中并过滤响应以保留新鲜的文章。

使用 readSince()

readSince() 帮助你获取一个 \FeedIo\Feed 而不必创建其实例

<?php
    // get feedio
    $feedIo = $this->container->get('feedio');

    // this date is used to fetch only the latest items
    $modifiedSince = new \DateTime($date);

    // the feed you want to read
    $url = 'http://host.tld/feed';

    // now fetch its (fresh) content
    $feed = $feedIo->readSince($url, $modifiedSince)->getFeed();
?>

提供源

RssAtomBundle 提供了提供 JSON/RSS/Atom 源的能力。路由将匹配以下模式:/ {format}/{contentId}

  • {format} 必须是 "rss" 或 "atom"(如果你在 routing.yml 中添加了正确的路由规则,可以是任何你想要的)
  • {contentId} 是一个可选参数。如果你有多个源,请使用它

请求将由 StreamController 根据以下步骤处理

  • 1:如果存在,则获取 ModifiedSince 头部
  • 2:创建一个包含请求参数的 Options 实例(如果存在则包含 contentId)
  • 3:获取在 services.yml 中定义的提供者并调用 getFeedContent(Options $options) 方法
  • 4:比较源的 LastModified 属性与 ModifiedSince 头部
  • 5:如果 LastModified 早于或等于 ModifiedSince,则响应只包含 "NotModified" 头部和 304 状态码。否则,构建流并将其发送到客户端

定义你自己的提供者

你必须向 RssAtomBundle 提供你希望在源中显示的内容。为此,需要两个步骤

  • 编写一个实现 FeedProviderInterface 的类。我们称这个类为 '提供者',它将负责构建源。
  • 配置依赖注入以使 RssAtomBundle 使用它
FeedContentProviderInterface 实现

你的类只需要实现 Debril\RssAtomBundle\Provider\FeedProviderInterface 接口,例如

<?php
# src/Feed/Provider.php
namespace App\Feed;

use FeedIo\Feed;
use FeedIo\FeedInterface;
use FeedIo\Feed\Item;
use Debril\RssAtomBundle\Provider\FeedContentProviderInterface;

class Provider implements FeedProviderInterface
{
    /**
     * @param array $options
     * @return \FeedIo\FeedInterface
     * @throws \Debril\RssAtomBundle\Exception\FeedNotFoundException
     */
    public function getFeed(Request $request) : FeedInterface
    {
        // build the feed the way you want
        $feed = new Feed();
        $feed->setTitle('your title');
        foreach($this->getItems() as $item ) {
            $feed->add($item);
        }

        return $feed;
    }

    protected function getItems()
    {
        foreach($this->fetchFromStorage() as $storedItem) {
            $item = new Item;
            $item->setTitle($storedItem->getTitle());
            // ...
            yield $item;
        }
    }
    protected function fetchFromStorage()
    {
        // query the database to fetch items
    }
}

StreamController 期望 getFeed() 的返回值是一个 FeedIo\FeedInterface 实例。它可以是一个 FeedIo\Feed 或你的自定义类,如果是这样,你的类必须实现 \FeedIo\FeedInterface

你还可以从这个类开始以节省时间: App\Feed\Provider.php

<?php
interface FeedInterface extends \Iterator, NodeInterface
{
    /**
     * This method MUST return the feed's full URL
     * @return string
     */
    public function getUrl();

    /**
     * @param string $url
     * @return FeedInterface
     */
    public function setUrl($url);

    // Full source can be read in the repository .......
?>
配置

现在,你需要在你的项目的 services.yml 中配置 debril.rss_atom.provider 服务,指定提供者的类

# config/services.yaml
parameters:
  debril.rss_atom.provider.class: 'App\Feed\Provider'

或者,如果你需要用参数构建它,你可以覆盖 debril.rss_atom.provider 的声明

# config/services.yaml
services:
  debril.rss_atom.provider:
    class: App\Feed\Provider
    arguments: ["@logger", "@doctrine"]

就是这样。转到 http://localhost:8000/atom,它应该显示你的源。

使 StreamController 返回 404

如果回收的源不存在,你只需要抛出 FeedNotFoundException 以使 StreamController 返回 404 错误。否则,getFeedContent(Options $options) 必须返回一个 \FeedIo\FeedInterface 实例。然后,控制器将正确地将对象转换为 XML 流。

有关 FeedContentProviderInterface 接口和如何直接将 rss-atom-bundle 与 doctrine 接口的信息,请参阅 提供源部分

有用提示

跳过 304 HTTP 状态码

在开发过程中,HTTP 缓存处理可能会很烦人,你可以在 app/config/config.yml 文件中的配置中跳过它

# config/packages/rss_atom.yaml
debril_rss_atom:
    force_refresh: true

这样,StreamController 将始终显示你的源内容并返回 200 HTTP 状态码。

私有源

你可能有一些私有源,如特定用户或某些身份验证后的源。
在这种情况下,您不希望添加 Cache-Control: public 头部,以免您的源被反向代理(如 Symfony AppCache 或 Varnish)缓存。
您可以在配置中将 private 参数设置为 true 来实现这一点。

# config/packages/rss_atom.yaml
debril_rss_atom:
    private: true

添加非标准日期格式

某些源使用与规范不兼容的日期格式。您可以通过在配置中添加该格式来修复此问题。

# config/packages/rss_atom.yaml
debril_rss_atom:
    date_formats:
      - 'Y/M/d'

为源生成使用自定义 Content-Type 头部

如果您需要自定义源的 Content-Type 头部,可以在配置中指定该值。

# config/packages/rss_atom.yaml
debril_rss_atom:
    content_type_json: application/json
    content_type_xml: application/xhtml+xml

回到 feed-io 3.0 版本

从 4.1 版本开始,rss-atom-bundle 随 feed-io 4 一起提供,如果您的应用程序依赖于 PHP 7.1+。如果您出于某种原因需要使用 feed-io 3,您可以在 composer.json 中这样做。

    "debril/rss-atom-bundle": "^4.1",
    "debril/feed-io": "~3.0",

覆盖提示

可能会发生这种情况,根据在 AppKernel 中注册的包的顺序,覆盖程序可能无法正常工作。当包在 rss-atom-bundle 之前注册时,就会发生这种情况。在这种情况下,您应该使用 Symfony 的 CompilerPass,如 文档 中所述。

Vendor/Bundle/VendorBundle.php:

use Vendor\Bundle\DependencyInjection\Compiler\OverrideRssAtomBundleProviderCompilerPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\Bundle\Bundle;

class VendorBundle extends Bundle
{
    public function build(ContainerBuilder $container)
    {
        parent::build($container);
        $container->addCompilerPass(new OverrideRssAtomBundleProviderCompilerPass());
    }
}

Vendor/Bundle/DependencyInjection/Compiler/OverrideRssAtomBundleProviderCompilerPass.php

use Vendor\Bundle\Provider\FeedProvider;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;

class OverrideRssAtomBundleProviderCompilerPass implements CompilerPassInterface
{
    public function process(ContainerBuilder $container)
    {
        $definition = $container->getDefinition('debril.rss_atom.provider');
        $definition->setClass(FeedProvider::class);
        $definition->addArgument(new Reference('my.service1'));
        $definition->addArgument(new Reference('my.service2'));
    }
}

您可以遵循 services.xmlCompilerPass,但使用服务时,您必须注意包的注册顺序。

获取存储库

如果您想做出贡献(您随时欢迎这样做)

git clone https://github.com/alexdebril/rss-atom-bundle.git

composer.phar install --dev

单元测试

您可以使用以下命令在包的源目录中运行单元测试套件:

bin/phpunit