fetch_feed()WP 2.8.0

Build SimplePie object based on RSS or Atom feed from URL.

Return

SimplePie\SimplePie|WP_Error. SimplePie object on success or WP_Error object on failure.

Usage

fetch_feed( $url );
$url(string|string[]) (required)
URL of feed to retrieve. If an array of URLs, the feeds are merged using SimplePie's multifeed feature. See also http://simplepie.org/wiki/faq/typical_multifeed_gotchas

Examples

0

#1 Get the last 5 posts of the feed from the external site

An example that gets and displays links to an existing RSS feed. In the example we limit the output to the last 5 posts in the feed.

<h2>Latest news from blog.ru</h2>

<?php
// make fetch_feed() available, usually this (string) is not needed
include_once ABSPATH . WPINC . '/feed.php';

// Get a feed and create a SimplePie object from it.
$rss = fetch_feed( 'http://blog.ru/feed' );

// Check that the object was successfully created
if ( ! is_wp_error( $rss ) ) {

	// Specify that we want to output a maximum of 5 feed posts
	$maxitems = $rss->get_item_quantity( 5 );

	// create an array of all feed posts, starting from the first post (0 is the beginning)
	$rss_items = $rss->get_items( 0, $maxitems );
}
?>

<ul>
	<?php
	if ( $maxitems == 0 ) {
		echo '<li>No posts.</li>';
	}
	// Run through the array and display a link to each post
	else { 
		foreach ( $rss_items as $item ) { 
			?>
			<li>
				<a href='<?php echo esc_url( $item->get_permalink() ); ?>'
				   title='<?php echo 'Posted ' . $item->get_date( 'j F Y | g:i a' ); ?>'
				>
					<?php echo esc_html( $item->get_title() ); ?>
				</a>
			</li>
			<?php
		}
	}
	?>
</ul>
0

#2 Get 5 feed posts from a third-party site

Let's read the feed http://mysite.com/feed/ and get the first 5 posts from it.

include_once ABSPATH . WPINC . '/feed.php';

$rss = fetch_feed( 'http://mysite.com/feed/' );

$rss_items = $rss->get_items( 0, $rss->get_item_quantity(5) );

if ( ! $rss_items ) {
	echo 'no items';
}
else {
	foreach ( $rss_items as $item ) {
		echo '<p><a href="' . $item->get_permalink() . '">' . $item->get_title() . '</a></p>';
	}
}
0

#3 Managing the lifetime of the feed cache

The result of fetching a feed is cached for 12 hours. To change cache time for this function, you can use hook wp_feed_cache_transient_lifetime.

add_filter( 'wp_feed_cache_transient_lifetime', 'speed_up_feed', 10, 2 );

function speed_up_feed( $interval, $url ) {

	if( 'http://myexample.com/feed/' === $url ){
		return 3600; // 1 hour
	}

	return $interval;
}
0

#4 Disabling caching during development

In the process of manipulating the feed, it is necessary to disable the caching, otherwise it will interfere a lot. This can be done through the hook wp_feed_options.

// disable feeds caching. Only if WP_DEBUG development mode is enabled
if( defined('WP_DEBUG') && WP_DEBUG ){

	add_action( 'wp_feed_options', function( &$feed ){
		$feed->enable_cache(false);
	} );
}

IMPORTANT: Be sure to disable this code on the working site. Because it can increase the speed of loading pages of the site at times!

Feed caching does not work with constant WP_DEBUG enabled

Keep in mind that if constant WP_DEBUG is enabled, the feed is not cached. This is the kernel code that works:

function do_not_cache_feeds(&$feed) {
	$feed->enable_cache(false);
}

if ( defined('WP_DEBUG') && WP_DEBUG ) {
	add_action( 'wp_feed_options', 'do_not_cache_feeds' );
}
Browser caching

Also note that the caching can occur in the browser, to bypass it, refresh the page via ctrl + F5. Or you can add such a hook:

// disable caching in the baruser for feed queries
add_filter( 'wp_headers', function( $headers ){

	if( !empty( $GLOBALS['wp']->query_vars['feed'] ) ){
		unset( $headers['ETag'], $headers['Last-Modified'] );
	}

	return $headers;
} );
0

#5 Cleaning the cache of all feeds in WordPress

To run the code, add the parameter ?clear_feeds_cache to the URL.

// Cleaning the cache of all feeds in WordPress
if( isset( $_GET['clear_feeds_cache'] ) ){

	global $wpdb;

	$cleared = $wpdb->query( "DELETE FROM $wpdb->options WHERE option_name LIKE '\_transient%\_feed\_%'" );

	die( var_dump( $cleared ) );
}

Note: if object caching is enabled on the site, this code will not work.

0

#6 How to parse a feed from a local file

In general, the SimplePie library allows you to pass a local file with feed data to parse this feed. However, WordPress has somehow disabled this feature by rewriting the constructor of the SimplePie_File class, extending this class with its own class WP_SimplePie_File.

Therefore, if you specify the path to a local file in fetch_feed(), nothing will work.

This can be fixed using the wp_feed_options hook:

$feed_path = PROJECT_ROOT_DIR . '/_tmp/feed.xml';

add_action( 'wp_feed_options', 'change_simple_pie_options', 10, 2 );
function change_simple_pie_options( $simplepie, $url ){
	/**
	 * INFO: We need to create the TEMP_SimplePie_File class to fetch the feed
	 * from a local file (not HTTP). To do that, we need to use the native {@see SimplePie_File} class,
	 * but it is overridden by WP with the {@see WP_SimplePie_File} class, and we cannot change it
	 * by simply passing the {@see SimplePie_File} class to the {@see SimplePie::set_file_class()} method,
	 * because the {@see SimplePie_Registry::register()} method has an `is_subclass_of()`
	 * check, and this check does not pass like: is_subclass_of('SimplePie_File', 'SimplePie_File').
	 */
	class TEMP_SimplePie_File extends SimplePie_File {}

	$simplepie->set_file_class( TEMP_SimplePie_File::class );
	$simplepie->set_cache_duration( 0 );
}

$simplepie = fetch_feed( $feed_path );

$items = $simplepie->get_items( 0, 10 );
foreach( $items as $item ){
	echo $item->get_title() ."\n";
}

Why might this be necessary? For example:

  • You have a separate service that collects feeds and saves them to files, which then need to be parsed through WP.
  • You need to parse a feed, but this feed is blocked (protected) in such a way that it cannot be obtained through PHP (cookie support is checked — there is similar protection on Cloudflare that cannot be bypassed with a standard curl request). In this case, you can download such a feed using some headless browser and save it to a file, and then parse the feed from the file.

Changelog

Since 2.8.0 Introduced.

fetch_feed() code WP 6.7.1

function fetch_feed( $url ) {
	if ( ! class_exists( 'SimplePie\SimplePie', false ) ) {
		require_once ABSPATH . WPINC . '/class-simplepie.php';
	}

	require_once ABSPATH . WPINC . '/class-wp-feed-cache-transient.php';
	require_once ABSPATH . WPINC . '/class-wp-simplepie-file.php';
	require_once ABSPATH . WPINC . '/class-wp-simplepie-sanitize-kses.php';

	$feed = new SimplePie\SimplePie();

	$feed->set_sanitize_class( 'WP_SimplePie_Sanitize_KSES' );
	/*
	 * We must manually overwrite $feed->sanitize because SimplePie's constructor
	 * sets it before we have a chance to set the sanitization class.
	 */
	$feed->sanitize = new WP_SimplePie_Sanitize_KSES();

	// Register the cache handler using the recommended method for SimplePie 1.3 or later.
	if ( method_exists( 'SimplePie_Cache', 'register' ) ) {
		SimplePie_Cache::register( 'wp_transient', 'WP_Feed_Cache_Transient' );
		$feed->set_cache_location( 'wp_transient' );
	} else {
		// Back-compat for SimplePie 1.2.x.
		require_once ABSPATH . WPINC . '/class-wp-feed-cache.php';
		$feed->set_cache_class( 'WP_Feed_Cache' );
	}

	$feed->set_file_class( 'WP_SimplePie_File' );

	$feed->set_feed_url( $url );
	/** This filter is documented in wp-includes/class-wp-feed-cache-transient.php */
	$feed->set_cache_duration( apply_filters( 'wp_feed_cache_transient_lifetime', 12 * HOUR_IN_SECONDS, $url ) );

	/**
	 * Fires just before processing the SimplePie feed object.
	 *
	 * @since 3.0.0
	 *
	 * @param SimplePie\SimplePie $feed SimplePie feed object (passed by reference).
	 * @param string|string[]     $url  URL of feed or array of URLs of feeds to retrieve.
	 */
	do_action_ref_array( 'wp_feed_options', array( &$feed, $url ) );

	$feed->init();
	$feed->set_output_encoding( get_bloginfo( 'charset' ) );

	if ( $feed->error() ) {
		return new WP_Error( 'simplepie-error', $feed->error() );
	}

	return $feed;
}