Monday, March 14, 2011

Custom Drupal RSS Feed with CCK

Ever needed to do a quick RSS feed one-off out of your Drupal site? This is how I do it.

Setup: Drupal 6, CCK, Views enabled.

First, create a new content type and name it rssarticle. Add three text fields named heading, text and link. Save the content type.

Now, we'll use Views as a query builder that will provide the SQL you will run to build the feed. Start out by setting up a Node View, set Style to unformatted and Row style to Fields. Select the fields you want in your feed and move on to add a node type filter to restrict the view to our newly added rssarticle content type. Keep the rest of the settings untouched.

Now, hit the Preview button. You should now see some nodes rendered and a Query field that displays the query like so:

SELECT node.nid AS nid,
   node_data_field_heading.field_heading_value AS 
   node_data_field_heading_field_heading_value,
   node.type AS node_type,
   node.vid AS node_vid,
   node_data_field_heading.field_link_value AS 
   node_data_field_heading_field_link_value,
   node_data_field_heading.field_text_value AS 
   node_data_field_heading_field_text_value
 FROM node node 
 LEFT JOIN content_type_rssarticle node_data_field_heading ON 
   node.vid = node_data_field_heading.vid
 WHERE node.type in ('rssarticle')

Copy that SQL query and fire up your favorite php editor. Create a new php file by the name of mycustomfeed.php. Start by adding the following lines.

<?php
// Load necessary Drupal parts
require_once './includes/bootstrap.inc';
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);

// XML header
echo('<?xml version="1.0" encoding="utf-8" ?>');

// Get nodes from db
$results = db_query("");

// Loop over the result
while ($result = db_fetch_object($results)) {
 print $result->nid;
}
?>

Now this won't do much on it's own, we need the SQL you just copied to go in here too. Complete the code with this, placing it within the db_query("") statement.

<?php
// Load necessary Drupal parts
require_once './includes/bootstrap.inc';
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);

// XML header
echo('<?xml version="1.0" encoding="utf-8" ?>');

// Get nodes from db
$results = db_query("SELECT node.nid AS nid, 
node_data_field_heading.field_heading_value AS 
node_data_field_heading_field_heading_value, node.type AS 
node_type, node.vid AS node_vid, 
node_data_field_heading.field_link_value AS 
node_data_field_heading_field_link_value, 
node_data_field_heading.field_text_value AS 
node_data_field_heading_field_text_value FROM node node 
LEFT JOIN content_type_rssarticle node_data_field_heading 
ON node.vid = node_data_field_heading.vid WHERE 
node.type in ('rssarticle')");

// Loop over the result
while ($result = db_fetch_object($results)) {
 print $result->nid . "\n";
}
?>

Upload the file to your Drupal root and run either from a browser or from the command line.

It should output an xml header and list of NIDs. Check error logs for any warnings or sql errors and correct your code accordingly.

Now that we have the query working it's time to finish the job, adding the xml parts required for a valid RSS 2.0 feed as well as adding a LIMIT clause and performing some ISO date conversion magic.

<?php
// Load necessary Drupal parts
require_once './includes/bootstrap.inc';
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);

// XML header
echo('<?xml version="1.0" encoding="utf-8" ?>');
?>

<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>My Custom Feed</title>
    <description>This is My Custom Feed</description>
    <link>http://www.domain.com/mycustomfeed</link>

<?php

// Get nodes from db
$results = db_query("SELECT node.nid AS nid,
node_data_field_heading.field_heading_value AS 
node_data_field_heading_field_heading_value, 
node.type AS node_type, node.vid AS node_vid, 
node_data_field_heading.field_link_value AS 
node_data_field_heading_field_link_value, 
node_data_field_heading.field_text_value AS 
node_data_field_heading_field_text_value,
node.changed AS node_changed FROM node node 
LEFT JOIN content_type_rssarticle node_data_field_heading 
ON node.vid = node_data_field_heading.vid
WHERE node.type in ('rssarticle') LIMIT 0,10");
// Execute query and loop over the result
while ($result = db_fetch_object($results)) {
?>
<item>
<title>
<?php echo $result->node_data_field_heading_field_heading_value?>
</title>
<description>
<?php echo $result->node_data_field_heading_field_text_value?>
</description>
<link>
<?php echo $result->node_data_field_heading_field_link_value?>
</link>
<author>noreply@domain.com (Corporate Inc)</author>
<dc:creator>Head.Honcho</dc:creator>
<category>CustomCategory</category>
<guid isPermaLink="false"><?php echo $node->nid?></guid>
<pubDate>
<?php echo date('D, d M Y H:i:s T',$result->node_changed)?>
</pubDate>
</item>
<?php } // End while loop ?>
</channel>
</rss>

For more on custom rss from drupal, check out my post on rss with imagecache images and media enclosures

1 comment: