0

I am making a personal feed to run on an unused monitor using PHP, and I want to display multiple RSS feeds simultaneously. Is that possible? This is my current code:

 <?php
class rss 
{
    var $feed;
    function rss($feed) 
    {
        $this->feed = $feed;
    }
    function parse() 
    {
        $rss = simplexml_load_file($this->feed);
    $rss_split = array();
    foreach ($rss->channel->item as $item) {
            $title = (string) $item->title;
                $link   = (string) $item->link;
            $description = (string) $item->description;
                $rss_split[] = '<div class="item">
                                <a href="'.$link.'" target="_blank" title="">'.$title.'</a>
                                <hr>
                                </div>';
        }
        return $rss_split;
    }
    function display($numrows,$head) 
    {
        $rss_split = $this->parse();
        $i = 0;
        $rss_data = '<div class="container">
                     <div class="title">'.$head.'</div>
                     <div class="links">';

        while ( $i < $numrows ) 
    {
                $rss_data .= $rss_split[$i];
                $i++;
        }
        $trim = str_replace('', '',$this->feed);
        $user = str_replace('&lang=en-us&format=rss_200','',$trim);
    $rss_data.='</div></div>';
        return $rss_data;
    }
}

$feedlist = new rss("https://rss.app/feeds/OzfHGFFGdG4RG4LV.xml");

echo $feedlist->display(1000,"");
?>

The only answer I could find on here was using SimplePie, but I would rather make it pure vanilla PHP even if it may be harder. Thanks.

1 Answer 1

1

I would suggest first separating the display of the data from the retrieval of the data. Eg:

// this is important later
class RssInterface {
    public function generateItems();
}

class Rss implements RssInterface {
    protected $feed;
    
    public function __construct($feed) {
        // load the feed in the constructor so that relevant errors are raised immediately
        $this->feed = simplexml_load_file($feed);
    }
    
    public function generateItems() {
        foreach ($this->feed->channel->item as $item) {
            yield $item;
        }
    }
}

class DisplayMyRss {
    protected $rss;
    
    public function __construct(RssInterface $rss) {
        $this->rss = $rss;
    }
    
    public function asHtml() {
        $out = '<div class="container" etc...>';
        foreach( $rss->generateItems() as $item ) {
            $out .= '<div class="item" etc...>';
            // ...
            $out .= '</div>';
        }
        $out .= '</div>';
    }
}

So now you could do something like:

$feed = new Rss('https://example.com/rss1.xml');
$display = new DisplayMyRss($feed);
echo $display->asHtml();

Then we can wrap multiple RSS iterator classes in something like:

class MultiRss implements RssInterface {
    protected $feeds = [];
    
    public function __construct(array $feeds) {
        foreach($feeds as $feed) {
            $this->addFeed($feed);
        }
    }
    
    // simply enforce that the items adhere to the interface
    public function addFeed(RssInterface $feed) {
        $this->feeds[] = $feed;
    }
    
    // adhere to the interface spec
    public function generateItems() {
        while( $this->hasValidIterators() ) {
            yield $this->getNext();
        }
    }
    
    // check if all the iterators have finished
    protected function hasValidIterators() {
        return ! empty(array_filter(array_map(function($f){return $f->valid;}, $this->feeds)));
    }
    
    // assumes lists are ordered ascending by $item->date, picks the earliest one and advances its iterator
    protected function getNext() {
        $next = NULL;
        $feed_index = -1;
        foreach( $this->feeds as $index => $feed ) {
            if( ! $feed->valid ) { continue; } // skip finished iterators
            $cur = $feed->cur;
            if( $feed_index == -1 || $cur->date < $next->date ) {
                $feed_index = $index;
            }
        }
        $this->feeds[$next_index]->next();
        return $next;
    }
}

and still use the same classes and display logic:

$feeds = [
    new Rss('https://example.com/rss1.xml'),
    new Rss('https://example.com/rss2.xml')
];
$feed = new MultiRss($feeds);
$display = new DisplayMyRss($feed);
echo $display->asHtml();

Note that none of this code has actually been run or tested, it is straight off the top of my head and likely contains some bugs.

References:

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.