There is actually quite an easy approach to accomplish this particular task.
METHOD ONE
Follow these steps to easily create a custom RSS feed in your WordPress website:
- Create a custom page template. Name it your_custom_feed.php
- Paste the code in the first code block into your_custom_feed.php
- Upload your_custom_feed.php to your currently active WordPress
theme directory.
- Paste the second code block into your currently active WordPress functions.php file.
- Deactivate and reactivate your theme for it to take effect.
You can now access your Custom Feed at: your-domain.com/custom-feed/user-slug/
Credits go to Joost de Valk for publishing an excellent article. However, I slightly modified his code from the original article.
<?php
/*
Template Name: Custom Feed
*/
//----------------------------------------
// CONFIGURE THIS
//----------------------------------------
$contentType = 'excerpt';// Enter 'excerpt' or 'content'
$numposts = 5;// Enter number of posts to display for each author
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// NO MORE CONFIGURATION NECESSARY
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
function custom_rss_date( $timestamp = null ) {
$timestamp = ($timestamp==null) ? time() : $timestamp;
echo date(DATE_RSS, $timestamp);
}
function custom_rss_text_limit($string, $length, $replacer = '...') {
$string = strip_tags($string);
if(strlen($string) > $length)
return (preg_match('/^(.*)\W.*$/', substr($string, 0, $length+1), $matches) ? $matches[1] : substr($string, 0, $length)) . $replacer;
return $string;
}
function custom_rss_post_id() {
global $wp_query;
$thePostID = $wp_query->post->ID;
return $thePostID;
}
$thePage = get_page(custom_rss_post_id());
$posts = query_posts('showposts='.$numposts.'&author_name='.$thePage->post_name);
$lastpost = $numposts - 1;
header('Content-Type: ' . feed_content_type('rss-http') . '; charset=' . get_option('blog_charset'), true);
echo '<?xml version="1.0" encoding="'.get_option('blog_charset').'"?'.'>';
?>
<rss version="2.0"
xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:wfw="http://wellformedweb.org/CommentAPI/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
<?php do_action('rss2_ns'); ?>
>
<channel>
<title>
<?php bloginfo_rss('name'); wp_title_rss(); ?>
</title>
<atom:link href="<?php self_link(); ?>" rel="self" type="application/rss+xml" />
<link>
<?php bloginfo_rss('url') ?>
</link>
<description>
<?php bloginfo_rss("description") ?>
</description>
<lastBuildDate><?php echo mysql2date('D, d M Y H:i:s +0000', get_lastpostmodified('GMT'), false); ?></lastBuildDate>
<language>
<?php bloginfo_rss( 'language' ); ?>
</language>
<sy:updatePeriod><?php echo apply_filters( 'rss_update_period', 'hourly' ); ?></sy:updatePeriod>
<sy:updateFrequency><?php echo apply_filters( 'rss_update_frequency', '1' ); ?></sy:updateFrequency>
<?php foreach ($posts as $post) { ?>
<item>
<title><?php echo get_the_title($post->ID); ?></title>
<link>
<?php echo get_permalink($post->ID); ?>
</link>
<description>
<?php
if(!empty($contentType) && $contentType == 'excerpt'){
echo '<![CDATA['.custom_rss_text_limit($post->post_content, 500).']]>';
} elseif(!empty($contentType) && $contentType == 'content'){
echo '<![CDATA['.apply_filters('the_content', $post->post_content).']]>';
}
?>
</description>
<pubDate>
<?php custom_rss_date( strtotime($post->post_date_gmt) ); ?>
</pubDate>
<guid><?php echo get_permalink($post->ID); ?></guid>
</item>
<?php } ?>
</channel>
</rss>
You could place this in your current active WordPress theme functions.php file:
// Tell the hourly cronjob what operation it needs to perform.
add_action('update_custom_user_feeds', 'create_custom_user_feeds');
// Create a cronjob to update our custom feeds hourly.
function cron_custom_user_feeds(){
if(!wp_next_scheduled('update_custom_user_feeds')){
wp_schedule_event(current_time('timestamp'), 'hourly', 'update_custom_user_feeds');
}
}
add_action('init', 'cron_custom_user_feeds');
// Delete our hourly cronjob when the theme is changed.
function clear_custom_user_feeds(){
wp_clear_scheduled_hook('update_custom_user_feeds');
}
add_action('switch_theme', 'clear_custom_user_feeds');
// Generate the custom user feeds
function create_custom_user_feeds(){
// "Custom Feed" is the main feed page.
$feedParent = get_page_by_title('Custom Feed', 'OBJECT', 'page');
if(!$feedParent){
$pageData = array(
'post_title' => 'Custom Feed',
'post_name' => 'custom-feed',
'post_status' => 'publish',
'post_type' => 'page'
);
// Create custom user feed.
$parentID = wp_insert_post($pageData);
} else{
$parentID = $feedParent->ID;
}
$wpUsers = get_users();
for($i = 0; $i < count($wpUsers); $i++){
// Check if the custom user feed already exists.
$userFeed = get_page_by_title($wpUsers[$i]->user_nicename, 'OBJECT', 'page');
if(!$userFeed){
$pageData = array(
'post_title' => $wpUsers[$i]->user_nicename,
'post_name' => $wpUsers[$i]->user_nicename,
'post_status' => 'publish',
'post_type' => 'page',
'post_parent' => $parentID
);
// Create custom user feed.
$insertPage = wp_insert_post($pageData);
if($insertPage){
// Assign our custom feed template.
update_post_meta($insertPage, '_wp_page_template', 'your_custom_feed.php');
}
}
}
// Attempt to flush caches
wp_cache_flush();
if(function_exists('w3tc_objectcache_flush')){
w3tc_objectcache_flush();
}
if(function_exists('w3tc_pgcache_flush')){
w3tc_pgcache_flush();
}
if(function_exists('w3tc_minify_flush')){
w3tc_minify_flush();
}
if(function_exists('w3tc_dbcache_flush')){
w3tc_dbcache_flush();
}
}
Now, I'm not saying this solution is practical, but it works.
Alternatively, you can possibly make some usage from this class I made which uses add_feed();
METHOD TWO
Directions for using this class method within your theme. (Note: This class could easily be integrated into a plugin.)
- Create a sub-directory in your currently active WordPress theme.
Name it: "inc". (Directory structure should look like:
./wp-content/themes/your_theme/inc/)
- Create a PHP file and place the code block below (Third/last code
block in this answer) in the file. Save it as custom-feeds.php
- Upload custom-feeds.php into your "inc" directory.
- May need to deactivate and reactivate your theme for it to take
effect.
You can now access your Custom Feed at: your-domain.com/feed/custom-user-slug/
Note: you can change the prefix "custom-" to anything you want. Just configure the settings in the class constructor.
<?php
if(!class_exists('custom_feeds')){
class custom_feeds{
private $feed_settings;
private $feed_data;
public function __construct(){
// Configure the Feed
$this->feed_settings['number_posts'] = -1;// # of feed items, -1 means all posts
$this->feed_settings['content_type'] = 'excerpt';// Excerpt or Content
$this->feed_settings['excerpt_length'] = 500;// if excerpt, display how many characters?
$this->feed_settings['offset_posts'] = 0;// Skip # of recent posts
$this->feed_settings['custom_prefix'] = 'custom';// domain.com/feed/{prefix}-feed-name/
$this->feed_settings['signature_link'] = false;// add link back to your site after the content.
// Specify what type of feed you want to create.
$this->prepare_feed('user');// All users, nice names
//$this->prepare_feed('user', 'some-user');// Specific user's nice name
// Prepare the feed
add_action('init', array($this, 'setup_custom_feeds'));
}
public function setup_custom_feeds(){
global $wp_rewrite;
// Add a feed for each type.
foreach($this->feed_data as $type => $posts){
add_feed($this->feed_settings['custom_prefix'].'-'.$type, call_user_func_array(array($this, 'display_feed'), array($type, $posts)));
}
// Flush rewrite rules.
$wp_rewrite->flush_rules();
// Attempt to flush caches.
$this->flush_all_caches();
}
public function prepare_feed($type, $nice_name=NULL){
if($type == 'user'){
if(!is_null($nice_name)){
// Get specified user.
$data[] = get_user_by('slug', $nice_name);
} else{
// Get all users.
$data = get_users();
}
// Find posts for our request.
for($i = 0; $i < count($data); $i++){
$userPosts = new WP_Query(array('posts_per_page' => intval($this->feed_settings['number_posts']), 'author_name' => $data[$i]->user_nicename, 'offset' => intval($this->feed_settings['offset_posts'])));
wp_reset_postdata();
if(!empty($userPosts->posts)){
$theData[$data[$i]->user_nicename] = $userPosts->posts;
}
}
}
$this->feed_data = $theData;
}
public function display_feed($type, $posts){
$current_feed = explode('/feed/', $this->self_link());
if($this->feed_settings['custom_prefix'].'-'.$type == $current_feed[1]){
header('Content-Type: '.feed_content_type('rss-http').'; charset='.get_option('blog_charset'), true);
echo '<?xml version="1.0" encoding="'.get_option('blog_charset').'"?'.'>'.PHP_EOL;
echo '<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"';
do_action('rss2_ns');
echo '>'.PHP_EOL;
echo '<channel>'.PHP_EOL;
echo '<title>';
bloginfo_rss('name');
wp_title_rss();
echo '</title>'.PHP_EOL;
echo '<atom:link href="'.$this->self_link().'" rel="self" type="application/rss+xml" />'.PHP_EOL;
echo '<link>'.get_bloginfo_rss('url').'</link>'.PHP_EOL;
echo '<description>'.get_bloginfo_rss('description').'</description>'.PHP_EOL;
echo '<lastBuildDate>'.mysql2date('D, d M Y H:i:s +0000', get_lastpostmodified('GMT'), false).'</lastBuildDate>'.PHP_EOL;
echo '<language>'.get_bloginfo_rss('language').'</language>'.PHP_EOL;
echo '<sy:updatePeriod>'.apply_filters('rss_update_period', 'hourly').'</sy:updatePeriod>'.PHP_EOL;
echo '<sy:updateFrequency>'.apply_filters('rss_update_frequency', '1').'></sy:updateFrequency>'.PHP_EOL;
// Begin displaying posts in our feed.
foreach($posts as $post){
echo '<item>'.PHP_EOL;
echo '<title>'.$post->post_title.'</title>'.PHP_EOL;
echo '<link>'.get_permalink($post->ID).'</link>'.PHP_EOL;
echo '<description>'.PHP_EOL;
if($this->feed_settings['signature_link']){
$feed_signature = '<h3>Original Post:<br /> <a title="'.$post->post_title.'" href="'.get_permalink($post->ID).'">'.$post->post_title.'</a></h3>';
} else{
$feed_signature = '';
}
if(!empty($this->feed_settings['content_type']) && $this->feed_settings['content_type'] == 'excerpt'){
echo '<![CDATA['.$this->custom_rss_text_limit($post->post_content, intval($this->feed_settings['excerpt_length'])).$feed_signature.']]>'.PHP_EOL;
} elseif(!empty($this->feed_settings['content_type']) && $this->feed_settings['content_type'] == 'content'){
echo '<![CDATA['.apply_filters('the_content', $post->post_content).$feed_signature.']]>'.PHP_EOL;
}
echo '</description>'.PHP_EOL;
echo '<pubDate>'.$this->custom_rss_date(strtotime($post->post_date_gmt)).'</pubDate>'.PHP_EOL;
echo '<guid>'.$post->guid.'</guid>'.PHP_EOL;
echo '</item>'.PHP_EOL;
}
echo '</channel>'.PHP_EOL;
echo '</rss>'.PHP_EOL;
}
}
private function custom_rss_date($timestamp = null){
$timestamp = ($timestamp==null) ? time() : $timestamp;
return date(DATE_RSS, $timestamp);
}
private function custom_rss_text_limit($string, $length, $replacer = '...'){
$string = strip_tags($string);
if(strlen($string) > $length)
return (preg_match('/^(.*)\W.*$/', substr($string, 0, $length+1), $matches) ? $matches[1] : substr($string, 0, $length)) . $replacer;
return $string;
}
private function self_link(){
$host = @parse_url(home_url());
$host = $host['host'];
$return = esc_url(
'http'
. ( (isset($_SERVER['https']) && $_SERVER['https'] == 'on') ? 's' : '' ) . '://'
. $host
. stripslashes($_SERVER['REQUEST_URI'])
);
return $return;
}
private function flush_all_caches(){
wp_cache_flush();
if(function_exists('w3tc_objectcache_flush')){
w3tc_objectcache_flush();
}
if(function_exists('w3tc_pgcache_flush')){
w3tc_pgcache_flush();
}
if(function_exists('w3tc_minify_flush')){
w3tc_minify_flush();
}
if(function_exists('w3tc_dbcache_flush')){
w3tc_dbcache_flush();
}
}
}// END custom_feeds class.
// Instantiate the class.
$custom_feeds = new custom_feeds();
}// END custom_feeds class exists.
?>
Note: I don't know how well it would perform on large scale websites. Although, the way I have setup this class, allows for easy manipulation. You could use this same class for generating feeds of a custom post type, or custom taxonomy as well. My Custom Feeds class has been tested on WordPress 3.4.1 and works correctly.
If you wanted to use it the way I have it currently setup, all you would need to do is configure the feed settings in the class constructor.