Moderní tvorba webových aplikací

O webu

File_get_contents a timeout

Jak omezit maximální čas získávání obsahu stránky z URL.

3 minuty

V případě, že je potřeba stáhnout obsah z nějaké cizí stránky, hodí se k tomu PHP funkce file_get_contents.

Čekání na odpověď

Problém tohoto postupu nastane ve chvíli, kdy cílová stránka nebude odpovídat. V takovém případě se PHP bude marně snažit až do vyčerpání časového limitu (Maximum execution time), což může být třeba 30 vteřin.

Většinou to ale je tak, že když stránka nevrátí obsah do několika stovek milisekund, nejspíš ho nevrátí vůbec (má výpadek a podobně).

Proto u akcí, které vyvolává běžný návštěvník, je dobré nastavit časový limit. Běžný uživatel často nebude ochotný čekat déle než řádově několik vteřin.

Doporučený postup

Získávání obsahu, které by mohlo blokovat vykreslení stránky, nastavit s nízkým časovým limitem a v případě neúspěchu zkusit data donačíst později AJAXem.

A nebo použít cache.

Nastavení timeoutu

$context = stream_context_create(
  array('http' =>
    array(
      'timeout' => 1 // Timeout ve vteřinách
    )
  )
);
$soubor = @file_get_contents(
  "http://example.com", 
  false, 
  $context
);

Timeout se funkci file_get_contents dá nastavit přes tzv. context, jenž se předá jako třetí argument.

Zajímavé chování má časová jednotka pro timeout, která v praxi trvá dvakrát víc sekund, než se nastaví. Uvedená ukázka má tedy skutečný timeout 2 sekundy.

V případě, že časový limit znemožní stažení stránky, vrátí file_get_contents varování:

Warning: file_get_contents(…): 
  failed to open stream: HTTP request failed!

To je proto potlačeno zavináčem. V případě chyby bude v proměnné $soubor hodnota false (jinak získaný obsah).

HTTPS

Přestože se v poli při vytváření kontextu (stream_context_create) píše http, získání obsahu včetně nastavení limitu může fungovat i na HTTPS.

cURL

S využitím cURL se timeout nastavuje takto:

function curlObsah($url) {
  $c = curl_init();
  curl_setopt($c, CURLOPT_TIMEOUT, 1);
  curl_setopt($c, CURLOPT_URL, $url);
  $result = curl_exec($c);
  curl_close($c);
  return $result;
}

Existuje i nastavení CURLOPT_TIMEOUT_MS pro zadávání času v milisekundách. Nicméně často nižší timeout než 1 vteřinu není možné nastavit (nastavení v milisekundách by mělo fungovat od cURL 7.16.2 – od PHP 5.2.3).

Test obou postupů je na GitHubu.

Související články

Výpis náhodného textu

Jak na stránce náhodně vypsat obrázek, odkaz, reklamu, text nebo cokoliv jiného.

5 minut

Instalace Apache, PHP a MySQL za 30 vteřin

Jak si ve Windows spustit vlastní Apache, PHP a MySQL na svém PC za půl minuty.

7 minut

MySQL přes PDO

PDO je PHP rozhraní pro pohodlnější práci s SQL databásí. Jaké přináší výhody a jak ho používat.

7 minut

Upload obrovských souborů v JS/PHP

Jak umožnit návštěvníkům nahrát soubory jako videa v řádech MB/GB s progress barem.

7 minut

Web jecas.cz píše Bohumil Jahoda, kontakt
Seznam všech článků
2013–2025