Parsing tags with Zend Feed
Consuming a feed with Zend Feed is quite simple if you don’t want to do something fancy. It could look something like this:
$cur_headlines = Zend_Feed::import("http://localhost/dailydev/dzone_new_links.xml");
foreach($cur_headlines as $item){
$arr = array(
"title" => $item->title(),
"link" => $item->link(),
"description" => $item->description()
);
}
Easy enough, the array above could be inserted in a database for example. But what if we want to save tag information? An item in the Dzone feed we use in this example could look like this:
.
.
.
<title>Good Unix Tutorials</title>
<link>http://feeds.dzone.com/~r/dzone/upcoming/~3/188060046/good_unix_tutorials.html</link>
<description>I have compiled a list of the best unix tutorials. If you know any good one you can add them to the list.</description>
<category>books</category>
<category>how-to</category>
<category>tools</category>
<category>unix-linux</category>
.
.
.
Zend Feed makes use of the DOM functions in PHP5, calling $item->category() above will not generate the proper results, we will get an array with DOMElements back instead of an array of strings, the same goes for $item->category. However, using getDOM() and getElementsByTagName() will give us a DOMNodeList which we can loop through:
function getTags(&$item){
$tag_obj = Common::loadModel('tag');
$item_cat = is_array($item->category()) ? $item->getDOM()->getElementsByTagName('category') : $item->category();
$tags = ",";
if(is_object($item_cat)){
foreach($item_cat as $cat){
$tags .= "{$cat->nodeValue},";
$tag_obj->insertTag($cat->nodeValue);
}
}else if(!empty($item_cat)){
$tags .= "$item_cat,";
$tag_obj->insertTag($item_cat);
}
return $tags;
}
This example uses functionality covered in the series on writing a cms/community with the Zend Framework and Smarty, so I won’t explain it.
Let’s check out our tag model:
class Tag extends ExtModel{
protected $_name = 'tags';
protected $_primary = 'id';
function insertTag($value){
$row = $this->createRow();
$row->value = $value;
$row->popularity = 1;
try{
$new_id = $row->save();
}catch(Zend_Db_Statement_Exception $e){}
if(empty($new_id)){
$old_data = $this->fetchRow("value = '$value'");
$old_data->popularity += 1;
$old_data->save();
}
}
}
The above might be a little confusing without the SQL:
CREATE TABLE `tags` (
`id` bigint(12) NOT NULL auto_increment,
`value` varchar(250) character set utf8 NOT NULL,
`popularity` bigint(12) NOT NULL default '1',
PRIMARY KEY (`id`),
UNIQUE KEY `value` (`value`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
Now the try catch statement makes more sense, as you can see we have a unique key on value which contains the tag itself. This makes the save function fail which generates an exception that we have to catch – if the tag is already in the database. If we haven’t got a new id as the result we know that the insert failed. We will update the old info instead.