PHP:DOMDocument::load(): I/O警告:未能加载外部实体(外部rss提要和缓存文件)

时间:2022-10-10 12:43:58

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.

我需要在我的页面上显示,来自外部RSS提要的最新条目。我做了一个简单的rss阅读器,它使用一个缓存文件。

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

警告:DOMDocument::load(): I/O警告:未能加载外部实体“…/rssRadio.xml”。“在……/索引缓存。php在45行

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

这是页面的代码。第45行是最后一个:

      $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?

看起来,在file_put_contents调用结束之前,它正在尝试读取缓存文件。但这是不可能的,因为这是一个阻塞的I/O调用…对吧?什么好主意吗?

Cheers

干杯

1 个解决方案

#1


1  

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

问题可能存在于服务器延迟更新索引树中。您可以解决它添加usleep(100);在写入之后。

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.

通过这种方式,您将加载字符串而不是文件,您的脚本将正常工作。

#1


1  

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

问题可能存在于服务器延迟更新索引树中。您可以解决它添加usleep(100);在写入之后。

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.

通过这种方式,您将加载字符串而不是文件,您的脚本将正常工作。