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.

Related Posts

Tags: , , ,