2010-07-19 2 views
0

В настоящее время я использую PHP для загрузки нескольких XML-файлов со всего Интернета (нелокальных) с использованием simplexml_load_file(). Это, как вы можете себе представить, довольно неуклюжий процесс и значительно замедляет нагрузку (7 секунд для загрузки 7 файлов), и, возможно, может быть больше загружаемых файлов. Эти файлы не меняются часто, но изменения должны отображаться на странице сразу после их создания.Сравнение XML-документов для изменений в PHP

Одна из моих идей заключалась в том, чтобы кэшировать версию каждого фида и выход html, который я генерирую из этого фида в моей БД. Затем каждый раз, когда пользователь загружает страницу, каналы будут сравниваться; если они разные, я бы запустил свой существующий код, сгенерировал HTML, вывел его и сохранил в БД. Однако, если это то же самое, я могу просто вывести кэшированный HTML.

Мои две проблемы с этим являются:

безопасности: Если я храню копию файла XML, это могло представлять угрозу безопасности, видя, как я не контролирует содержимое этого файла?

Скорость: Основная цель здесь - увеличить скорость общей загрузки страницы. Описанный выше процесс увеличит скорость, или же он просто запустит сервер с большим количеством действий? Спасибо за вашу помощь!

+0

Видит все те же каналы, или же каждый пользователь имеет различные каналы? –

ответ

4

Как получить задание cron через каждый внешний источник XML, скажем, ежечасно или ежеквартально и, если необходимо, обновить его?

Это не будет в реальном времени на 100%, но вы будете снимать нагрузку со своей веб-страницы - это всегда будет использовать кешированные файлы. Я не думаю, что существует надежный способ опроса внешних источников для обновлений, отличных от фактической загрузки файла (теоретически, должно быть возможно получить правильные заголовки кеша, но я не буду полагаться на их правильную настройку).

Безопасность: Если я храню копию XML-файла, может ли это представлять угрозу безопасности, поскольку я не контролирую содержимое этого файла?

Вряд ли. Чтобы полностью убедиться, храните кешированные XML-файлы вне корня веб-сайта. Любая угроза, которая остается тогда, такая же, как если бы вы проходили поток через живое.

+0

Будет ли это по-прежнему реалистичным, если бы имелось, возможно, 100 файлов в разных URL? (Видите ли, каждый пользователь получает собственный набор файлов, поэтому их будет очень много.) – williamg

+0

@ iMaster sure! У вас будет определенное количество данных, лежащих на сервере, но пока это не занимает слишком много места, это не должно быть проблемой. – Unicron

+0

Оказывается, вы были прав насчет точности заголовков кеша. Я все еще сомневаюсь в работе cron, потому что кажется, что кто-то посещает во время работы скрипта, было бы намного хуже, потому что скрипт выполнял работу для КАЖДОГО пользователя в базе данных. Возможно, я просто не понимаю, что вы говорите. Независимо от того, можете ли вы опубликовать ссылку, где я мог бы прочитать немного больше о том, как использовать php с заданиями cron? Благодаря! – williamg

2

Одна из моих идей заключалась в том, чтобы кэшировать версию каждого фида и вывод html, который я генерирую из этого фида в моей БД. Затем каждый раз, когда пользователь загружает страницу, каналы будут сравниваться; если они разные, я бы запустил свой существующий код, сгенерировал HTML, вывел его и сохранил в БД. Однако, если это то же самое, я могу просто вывести кэшированный HTML.

Вместо кэширования XML файл самостоятельно, вы должны установить If-None-Match или If-Modified-Since поля в заголовке запроса. Таким образом, вы можете проверить, не изменились ли файлы, не загружая их.

Это можно сделать, установив контекст потока для libxml перед запуском simplexml_load_file(). Если файл не изменился, вы получите ответ 304 Not Modified, и simplexml_load_file потерпит неудачу.

Вы также можете использовать stream_context_get_default для установки общего контекста потока, а затем извлечь XML-файл в строку с помощью file_get_contents и передать ее в simplexml_load_string().

Вот пример первого способа:

Class CachedXml { 
    public $element,$url; 

    private $mod_date, $etag; 

    public function __construct($url){ 
     $this->url = $url; 
     $this->element = NULL; 
     $this->mod_date = FALSE; 
     $this->etag = FALSE; 
    } 

    public function updateXml(){ 
     if($this->mod_date || $this->etag){ 
      $opts = array(
       'http'=>array(
       'header'=>"If-Modified-Since: $this->mod_date\r\n" . 
          "If-None-Match: $this->etag\r\n" 
       ) 
      ); 
      $context = stream_context_create($opts); 
      libxml_set_streams_context($context); 
     } 
     if($attempt = @ simplexml_load_file($this->url)){ 
      $this->element = $attempt; 
      $headers = get_headers($this->url,1); 
      $this->mod_date = $headers['Last-Modified']; 
      $this->etag = $headers['ETag']; 
      return TRUE; 
     } 
     return FALSE; 
    } 
} 

$bob = new CachedXml('http://example.com/xml/test.xml'); 

if($bob->updateXml()){ 
    echo "Bob was just updated.<br />"; 
    echo " Bob's name is " . $bob->element->getName() . ".<br />"; 
} 
else{ 
    echo "Bob was not updated.<br />"; 
} 
+0

Я думаю, что я немного потуплю это и просто использую бит с get_headers, а затем сравниваю Last-Modified с датой кеша. Насколько я могу судить, это дает мне именно то, что я хочу. – williamg

+0

Оказывается, заголовки не так точны ... спасибо за это предложение! – williamg

Смежные вопросы