0

I need to show on my page, the latest entries from an external RSS feed. I made a simple rss reader which uses a cache file.

It perfectly works on my test environment but when I put it on my website, I got an error every time the cache file has to be written:

Warning: DOMDocument::load(): I/O warning : failed to load external entity ".../rssRadio.xml.cache" in .../index.php on line 45

This is the code of the page. The line 45 it's the last one:

      $cacheName = 'cache/rss.xml.cache';
        $ageInSeconds = (3600*2); // two hour
        if(!file_exists($cacheName) || filemtime($cacheName) < time() - $ageInSeconds ) {
          $contents = file_get_contents($RSSURL);
          file_put_contents($cacheName, $contents);
        }
        $rss = new DOMDocument();
        if (!$rss->load($cacheName)) {
            throw new Exception('Impossibile caricare i podcast');
         }
        $feed = array();
        foreach ($rss->getElementsByTagName('item') as $node) {

...

If I reload the page, the error is gone and the content it's shown, so the cache file works fine.

Looks like the script it's trying to read the cache file before the file_put_contents call is ended. But this is impossible, because this is a blocking I/O call... right? Any ideas?

Cheers

Fabio Maccari
  • 57
  • 1
  • 2
  • 7

1 Answers1

1

The problem probably reside in a server delay updating index tree. You can resolve it adding a usleep(100); after file_put_contents.

But, in my opinion, the best solution is something like this:

if(!file_exists($cacheName) || filemtime($cacheName) < time() - $ageInSeconds ) 
{
    $contents = file_get_contents( $RSSURL );
    file_put_contents( $cacheName, $contents );
}
else
{
    $contents = file_get_contents( $cacheName );
}
$rss = new DOMDocument();
if( !$rss->loadXML( $contents ) ) 
{
    throw new Exception( 'Impossibile caricare i podcast' );
}

By this way, you load the string instead of file, and your script will work fine.

fusion3k
  • 11,568
  • 4
  • 25
  • 47