Hi all,
Being the ZF junkie that I am, I have been considering creating a proposal to address a few issues with Zend_Feed. Rather than let loose with the Proposal right away I figured I'd open the floor here (and on #zfdev where, for once :p, I am logged in at the moment), see what the community reception is, and steal...eh...borrow ideas where they make sense.
I'm currently towards the end of a second build of a simplified blog aggregation library based on Zend_Feed. Having done this twice I figured it was time to come up with a final solution so there's no third time ;).
In using Zend_Feed I've come to realise that it is largely an abstract API to PHP DOM. It imports, parses and presents a more natural API (akin to SimpleXML in a sense) for RSS and Atom feeds. However, Zend_Feed itself does not understand RSS or Atom - understanding these formats and their many versions is left entirely to the end programmer with a few exceptions. Zend_Feed_Reader's primary goal would be to take up the task of understanding and interpreting RSS and Atom.
This is a short email (from me, that means it's <3000 words ;)) throwing around some concepts for debate.
Current Potential Issues with Zend_Feed
Attempting to aggregate multiple feeds using different RSS and Atom standards requires a lot of extra work to correctly narrow all the available data down to common preferred points like: date, id, author, title, content, etc. It also means a lot of edge cases (malformed XML, non-standard RSS/Atom, etc.) also may need to be tracked by users. One of the few interpretive measures is being able to access RSS "content:encoded" data using a content() method. I also note "dc" namespaces are likewise resolved without the namespace prefix. Neither is consistent (e.g. content:encoded is accessible using the namespace prefix as the method name).
The second issue is that Zend_Feed is only minimally aware of HTTP. When given a URL it fetches that URL using Zend_Http_Client. Responses are neither cached nor conditionally fetched meaning that once again users must handle these scenarios by themselves or risk wasting precious memory, CPU cycles and bandwidth processing unchanged feeds. Not a biggie since it's easily implemented, but I've seen few Zend_Feed based apps doing it which is really poor practice in the wild.
A third potential problem is the assumption that all feeds will follow identical namespace patterns based on the namespace prefix (an arbitrary string). There are two examples here.
One is that some namespaces are resolved automatically by Zend_Feed while others are left unresolved which presents an inconsistent API. For example, an RSS 2.0 <entry> element might hold <dc:creator> and <slash:comments> elements with the <dc:creator> accessed as "$entry->creator()" (the dc namespace is automatically resolved by assumption) but the other only as "$entry->{'slash:comments'}" (the slash namespace is not resolved). This can become pretty confusing and require a lot of trial and error programming. Why doesn't "$entry->{'dc:creator'}" also return a typed result like "$entry->{'slash:comments'}?
The second is that namespaces are looked up based on the namespace prefix and not the namespace URI itself. Namespace prefixes may be standardised to a vast extent, but there's nothing illegal about using something different. If someone defined an alternate namespace prefix for "slash", existing source code based on using "$entry->{'slash:comments'}" would break. It's a much lesser point but some preemptive namespace registering would help here - there are only so many common extension out there.
Resolving Issues?
My own resolution ended up being an overhaul of how I used Zend_Feed. By adding a new interpretive layer it's possible to create an additional abstract API which both understands RSS and Atom versions, can present commonly requested data (prioritising similar elements) through a single set of accessor methods, and is invulnerable to namespace changes. It also makes internalising conditional fetches and caching simpler and standardised (whether there are meritable features is arguable but I think so). Originally I had considered building on top of Zend_Feed, but I've, to some extent, ended moving towards a parallel path where the base source is the DOMDocument Zend_Feed creates (allowing direct access to XPath and dynamic namespace registration) while maintaining access to Zend_Feed's other methods by proxy.
The point of the new proposal isn't to so much supercede Zend_Feed as extend it's API and capabilities to reduce the level of custom programming Zend_Feed needs to be surrounded with before it's useful in batch processing of RSS/Atom feeds where knowledge of any one specific feed is highly unlikely. I namespace it as Zend_Feed_Reader since it a separate class family not inheriting from Zend_Feed - rather it accepts Zend_Feed_Abstract instances through composition.
Your thoughts are welcome. Even if you write a longer email than me ;).
Best regards,
Paddy
Pádraic Brady
http://blog.astrumfutura.com
http://www.patternsforphp.com
OpenID Europe Foundation Member-Subscriber