require és include fajtái, különbségei php-ben

Az egyik gyakran felmerülő kérdés, hogy PHP-ben mi a különbség a require, include és ezek "_once" -ra végződő verziói között. Ráadásul én is emlékszem olyan írásra, ahol valótlant is írtak. Vagy a könyv szerzője tudta, mire gondol, csak nem volt megfejthető. Erről próbálok írni és ezzel most nem vállalkozom egy nagy szakmai jelentőséggel bíró bejegyzés írására.

Alapvetően ugye mind arra való, hogy egy másik fájlra hivatkozzunk vele és az abban levő forráskódot ott hajtsuk végre, ahol hivatkoztunk rá. Mégis érezhető néha a bőség zavara. Nézzük sorjában csak a lényeget!

Jellemzők

include

Az include egyszerűen csak fogja az adott fájlt és lefuttatja annak a tartalmát. Persze csak ha a fájl létezik. Mert ha nem, akkor jön az E_WARNING szintű hibaüzenet. Majd a program folytatódik. Azaz: Ez nem jött össze, de azért próbálkozom a program további részével.

require

Na ez már szigorúbb. Ha létezik a fájl, akkor szintén lefuttatja annak tartalmát. De ha nem létezik, akkor már egy E_FATAL szintű hibaüzenet érkezik, ami azt jelenti: Hoppáá... Ez a fájl sehol sincs. Pedig olyan fontos, hogy enélkül nem is folytatom a program többi részét. Éppen ezért "require" a neve. Azaz "igényel" vagy "követel".

require_once és include_once

A "once" jelentése: "egyszer". Azaz hiába próbálod ugyanazt a fájlt egymás után újra és újra futtatni, csak az első alkalommal fut le. Többször nem. Ezt javasolt használni osztályok, függvények betöltésére. Minden olyan esetben, amikor a kétszeri futtatás hiba. Ha pedig éppen az a cél, hogy valamit többször lefuttass, vagy több helyen megjeleníts, akkor csak a "once" nélküli verziók használhatók.

A különbség

Az egyetlen lényeges különbség tehát, hogy amíg az include csak figyelmeztet egy elnyomható hibaüzenettel a nem létező fájlra, addig a require nem is engedi tovább futni a programot. Ami pedig "_once" -ra végződik, ugyanúgy működik, de csak akkor illesztik be a fájt, ha előtte még nem volt.

Egyéb érdekesség, következmények

Meglehetősen szegényesen és felületesen írtam le a jellemzőket és a különbséget, de ez a lényeg. A lényeges funkciókon kívül viszont többnyire vannak rejtett vagy kevésbé rejtett képességek. Kevésbé hasznos, ritkábban kihasznált lehetőségek, illetve következmények, valamint tévhitek. Most ezek következnek.

Tévedés: require nem ágyazható feltételbe

Valamikor én is olvastam egy ilyen állítást. Már rég elfeledtem, de újra eszembe juttatta valaki. Utána is néztem, hol olvashattam. Ez pedig a "PHP feketekönyv" 43. oldalán volt. Az állítás így hangzik:

A require()-utasítás veszi a fájl nevét, és rögtön a PHP-feldolgozás kezdetén, a szintaktikai ellenőrzés alatt, de még a szkript végrehajtása előtt beágyazza a fájlt. így a require()-t nem lehet az if () vagy a hozzá hasonló logikai ellenőrző utasításokkal kontrollálni, emiatt a require() gyorsabb, de kevésbé rugalmas. Az állandóan beágyazott fájlokhoz ezért a require() jobban használható, mint a csupán alkalmanként használt fájlokhoz.

A könyv a PHP 4 idejében íródott. Akkoriban csatlakoztam be én is a nyelv világába. De ez az állítás már akkor sem volt igaz. Ha valaki netán tudná, hogy miért állította a könyv mégis ezt, az kérem, ossza meg itt hozzászólásban!

Tehát fontos: Bármelyik, bárhol használható. Függvényben, feltételben, ciklusban. Ahogy tetszik. A különbség a hibaszintben van.

Visszatérési érték, feltételek

Egy dolog jut csak eszembe a feltételek és a require vs. include témával kapcsolatban. Ez pedig a visszatérési érték használata. Mindkét ( mind a négy ) utasítás képes visszatérési értékeket kezelni. Hasonlóképpen, mint a függvények. Alapértelmezetten mindegyik 1-essel tér vissza, ha azt nem definiáljuk felül a return-nel a fájlban. Ha viszont a fájl nem létezik, akkor a require tulajdonságaiból adódóan a program leáll. Az include viszont egy logikai hamis, azaz false értéket ad vissza. A hibaüzenetet a kukac ( @ ) operátorral elnyomva így tehát a file_exists függvény nélkül ellenőrizhető a hivatkozott fájl létezése.

<?php if ( !@include "config.php" ) {
    exit("A config.php nem található. Nevezd át a config.default.php-t config.php-re és próbálkozz újra a beállítások után!");
 }

Itt kapóra jött, hogy egyszerre tudok include-olni és bár a config.php annyira fontos, hogy a program nem futhat tovább nélküle, ezt nem a require-re bíztam, hanem egy exit utasítással léptem ki és így egyedi hibaüzenetet írhattam ki. Ettől függetlenül a require is használható feltételben, ha a fájl létezése biztosított.

parosmp.php

<?php return !(intval(date('s')) % 2) ;

index.php

<?php if (require "parosmp.php") {
   echo "Igen";
} else {
   echo "Nem";
}

Nem függvények

Lényeges, hogy ezek közül egyik sem függvény. Hiába tud visszatérési értéket kezelni és bár a php.net-en a függvények között szerepel, de megjegyzésben kiemelik, hogy csak egy nyelvi konstrukció.

Note: Because this is a language construct and not a function, it cannot be called using variable functions.

Ha függvény lenne, kötelező volna a zárójel használata a nevük után. De nem az. És ahogy az idézett megjegyzésben szerepel, nem használható változóként meghívva:

$require = "require";
$require("fajl.php");

Míg a függvények igen.

Egyszer, de egyszer sem

Nem kérted előtte a fájlt, mégsem futtatja le a require_once vagy include_once. Azt kell megjegyezni, hogy ezeknek teljesen mindegy, hogy egy függvényben egy változókat tartalmazó fájlt akarsz beilleszteni, amik csak adott hatókörben érvényesek, vagy egy osztályokat tartalmazót, ami globálisan lesz hozzáférhető bárhonnan. Ha egyszer már egy másik függvényben vagy függvényen kívül kérted ugyanazt a fájlt, újra akkor sem foglalkozik vele a require_once vagy include_once, ha a tartalma adott hatókörben már nem érvényes.

Így hát ilyenkor vagy a "_once" nélküli verziókat kell használni vagy elmenteni a változókat és csak azokat visszaadni a további hívásokkor. És ez egyébként akkor is igaz, ha sehol máshol nem hívod meg azt a fájlt, kizárólag egyetlen függvényben. Mert nem a helye számít. Háromszor meghívva egy függvényt a benne levő require is háromszor fog lefutni. A következő kódban 1 másodperces késleltetéssel hívom meg többször a parosmp függvényt. Ennek következtében ha require-t használnék, egyszer igazat, egyszer hamisat adna vissza felváltva. De require_once-szal csak az első alkalommal fut le. És ahogy fentebb írtam, az alapértelmezett visszatérési érték a require-nél az 1-es. Tehát minden további alkalommal azt kapnánk. Íme a forráskód, ami 6 másodpercig fut (A parosmp.php forrását nem írom le újra):

<?php
function parosmp() {
        sleep(1);
        return (int)require_once 'parosmp.php';
}

echo parosmp().'<br />';
echo parosmp().'<br />';
echo parosmp().'<br />';
echo parosmp().'<br />';
echo parosmp().'<br />';
echo parosmp().'<br />';

Lehet próbálgatni. És ezzel a tervezett téma végére is értem. Szokás szerint hosszabb lett, mint terveztem, de remélem hasznotokra válik. Az elkövetett hibáimra, pontatlanságomra pedig bátran hívjátok fel a figyelmem!

Kategóriák: 
Megosztás/Mentés