ignore_user_abort

Školení, která pořádám

Často potřebujeme zajistit, aby se posloupnost operací vykonala buď celá nebo aby se nevykonala vůbec. Pokud se jedná výhradně o databázové operace, dají se k tomu použít transakce, v obecném případě je ale situace obtížnější. Vzhledem k tomu, že uživatel může vykonávání skriptu kdykoliv jednoduše ukončit zastavením načítání stránky (v prohlížečích k tomu obvykle slouží klávesa Esc a ikona na liště), nejedná se zdaleka o problém pouze teoretický. Operacemi, které chceme vykonat vždy spolu, je např. uložení objednávky a odeslání notifikace o jejím vzniku e-mailem. Pokud se objednávka jenom uloží a nepošle se o ní notifikace, může to znamenat ušlý zisk a naštvaného klienta, opačný případ je ještě horší.

K zabránění zastavení skriptu uživatelem slouží funkce ignore_user_abort. Nepokrývá pochopitelně např. násilné ukončení skriptu příkazem kill, ani v případě přerušení operací nevrátí již provedené změny, ale proti největšímu riziku obranu poskytuje.

<?php
// zde bude příprava dat pro vložení
ignore_user_abort(true); // zakázání přerušení skriptu uživatelem
mysql_query("INSERT INTO objednavky (" . implode(", ", array_keys($set)) . ") VALUES (" . implode(", ", $set) . ")");
$root = "http://$_SERVER[SERVER_NAME]" . substr($_SERVER["PHP_SELF"], 0, strrpos($_SERVER["PHP_SELF"], "/"));
mail($notify_email, "Nova objednavka", "$root/admin/objednavky_1.php?select=" . mysql_insert_id());
?>

Jakýkoliv výstup poslaný po zastavení přenášení stránky se samozřejmě zahodí.

Jakub Vrána, Výuka, 6.3.2006, diskuse: 15 (nové: 0)

Diskuse

lukas:

To jsem ani nevedel, ze uzivatel muze ukoncit skript... skvely clanek...

SQi:

Já zas myslel, že tomu nejde zabránit:-0

johno:

Takéto prasárne by som najradšej defaultne vypol. Viete si živo predstaviť kedy sa to dá využiť v kladnom slova zmysle?

ikona Jakub Vrána OpenID:

Nevím, jakou prasárnu máš na mysli, ale smysl funkce ignore_user_abort() je popsán v článku, takže bych řekl, že ti bude vadit výchozí chování "při zastavení požadavku se skript ukončí". To ve většině případů dává dobrý smysl - pokud už uživatel o výstup skriptu nemá zájem, je zbytečné plýtvat procesorovým časem na jeho další běh.

ikona llook:

Já bych zase řekl, že ingorováním uživatelského přerušení tam, kde to není potřeba, lze nadělat mnohem méně škody, než naopak.
Málokterá stránka, u které přerušení nevadí, využívá tolik systémových zdrojů, aby se povolením přerušení něco získalo. Takže bych byl spíš pro to, aby naopak programátor PHP sděloval, že "zrovna tento skript se klidně stopnout může".
Čím víc PHP znám, na tím víc věcí mám odlišný názor než PHP Group...

johno:

Presne to som tým myslel.

Jakub Podhorský:

Jakube nedá se tohodle efektu docílit i uvedením ob_start() na začátku skriptu? (vím že je to prasárna a ta funkce k tomu neslouží, ale neudělá to podobný efekt?)

ikona Jakub Vrána OpenID:

Neřekl bych, ale můžeš to vyzkoušet.

24k:

Jakube trim(); :)

Tibor:

..tak toto by mi v zivote nenapadlo ze sa moze stat... Vdaka a rozsirenie obzorov...

ikona dgx:

OT: ignoruj uživatelův potrat?

ikona spaze:

Já bych jen doplnil connection_status() a "When a PHP script is running normally the NORMAL state, is active. If the remote client disconnects the ABORTED state flag is turned on. A remote client disconnect is usually caused by the user hitting his STOP button. If the PHP-imposed time limit (see set_time_limit()) is hit, the TIMEOUT state flag is turned on."

paranoiq:

s pomocí connection_status() lze i ušetřit nějaký ten výkon ztracený povolením ignore_user_abort. v případě že se již user odpojil není třeba vytvářet výstup. pouze doděláte co je třeba (uložení dat do db apod.) a ukončíte script.

Honza Odvárko:

Jenom doplním, že podle mého testování, jakmile jednou zavoláte ignore_user_abort(true), už to nelze odvolat voláním ignore_user_abort(false)

nedik:

no, tak jsem to vyzkoušel a nefunguje mi to, že když dám stop v prohlížeči, tak se zastaví skript. Skript si prostě běží dál, ať udělám, co udělám. Můžu klidně zavřít prohlížeč, a skript to nijak neovlivní. Tak opravdu nechápu, o čem je vlastně tady řeč.

Vložit komentář

Používejte diakritiku. Vstup se chápe jako čistý text, ale URL budou převedeny na odkazy a PHP kód uzavřený do <?php ?> bude zvýrazněn. Pokud máte dotaz, který nesouvisí s článkem, zkuste raději diskusi o PHP, zde se odpovědi pravděpodobně nedočkáte.

Jméno: URL:

avatar © 2005-2018 Jakub Vrána. Publikované texty můžete přetiskovat pouze se svolením autora. Ukázky kódu smíte používat s uvedením autora a URL tohoto webu bez dalších omezení Creative Commons. Můžeme si tykat. Skripty předpokládají nastavení: magic_quotes_gpc=Off, magic_quotes_runtime=Off, error_reporting=E_ALL & ~E_NOTICE a očekávají předchozí zavolání mysql_set_charset. Skripty by měly být funkční v PHP >= 4.3 a PHP >= 5.0.