I have just started to use the Zend_Feed related components in earnest and am really liking the Zend_Feed_Writer (new to ZF 1.10.0). So what I wanted to do was created an RSS feed file is one didn’t exist and then keep updating that file as-and-when new items came in. Seems a really easy and simple thing to do, right? That, unfortunately, has not been my experience.
I have to say that to documentation seems quite lacking on the ZF site (for all the the Feed components, really, not just the Writer). Because of that, what follows may be idiotic and there really is an easy way. If so, I hope that you will post up a comment and let me know because I’d love to learn!
On with what I did…
My set up is actually to take an email sent to a particular address and add the contents to an RSS feed as-and-when the email arrives. So when the first email comes in the RSS feed file needs to be created. Using the Zend_Feed_Writer_Feed component, this is a really easy job. Once saved the XML looks well structured and everything is as expected. But then what happens when the next email comes in? Obviously I wouldn’t want to create a new feed file because it’d remove any previous entries. Also, I want to tweak the pubDate so that it reflects when this new email came in. I also wanted to use the Zend_Feed_Writer_Entry component so that the structure of the new item matches the previous ones.
The first thing to do was to load the RSS file and tweak the pubDate.
$now = new DateTime(); $now->setTimestamp(time()); $feed = new Zend_Feed_Rss(null, file_get_contents($feedFile)); $feed->pubDate = $now->format(DATE_RSS);
Then I created the entry:
$entry = new Zend_Feed_Writer_Entry(); $entry->setId($entryId); $entry->setTitle($emailSubject); $entry->addAuthor(array( 'name' => $emailFromName, 'email' => $emailFormAddress )); $entry->setDateCreated($emailDate->getTimestamp()); $entry->setContent($emailBody);
At this point it would be really nice to have some kind of Zend_Feed_Rss::addEntry(Zend_Feed_Writer_Entry|string of entry xml), or ::appendEntry()/::prependEntry(), but I was not able to see anything of the sort. So what I did was to create a DOMDocument with the feed file contents, render the entry and append it to the channel node.
$rss = new DOMDocument(); $rss->loadXML($feed->saveXML()); $rss->formatOutput = true; $rss->substituteEntities = false; $renderer = new Zend_Feed_Writer_Renderer_Entry_Rss($entry); $renderer->setRootElement($rss->documentElement); $renderer->render(); $element = $renderer->getElement(); $channel = $rss->getElementsByTagName('channel')->item(0); $imported = $rss->importNode($element, true); $channel->appendChild($imported); file_put_contents($feedFile, $rss->saveXML());
Now, that’s not a lot of code, but does it seem even remotely logical to do that when there’s already a fairly inclusive API for the feeds – perhaps just not inclusive enough?
Like I mentioned at the start, though; if you know a better way then please let me know – I’m always happy to learn!