Autoload megoldások akkor és most
Az objektumorientáltság a PHP nyelvben is magával hordozta azt a tényt, hogy webalkalmazásaink egyre nagyobbra nőnek, és ahogy több és több könyvtárat használunk programunkhoz, az
1
require(), include()
blokkok is gyarapodnak.
Ennek orvoslására
a PHP nyelvben az 5.0-ás verzió hozta magával az __autoload() mágikus függvényt.
Ezzel a függvénnyel és a beleprogramozott logikával könnyebbé tudtuk tenni az életünket, de persze csak egy bizonyos fokig. A függvény akkor hívódik meg, mikor futásidőben olyan osztályt, interfészt használtunk fel, amit előzőleg nem deklaráltunk. Ez egyfajta utolsó esély volt, hogy ne szálljon el hibával a program.
1
2
3
4
5
6
function __autoload($className) {
$className = $className . ".php";
if (file_readable($className) {
include($className);
}
}
Ez akkoriban egy nagy segítség volt, ellenben ennek is megvan a hátránya. Mégpedig az, hogy csupán egyetlen autoloadert lehet definiálni, így vagy annak kell univerzálisnak lennie, vagy egy adott szisztéma szerint kellett elrendezni a fájljainkat (pl. minden osztályt egy class.{osztálynév}.php-fájlban tároltunk a classes mappában). Ez kis projektek esetében járható út, ellenben egy komoly framework esetében nehezebben kivitelezhető, ráadásul nem tudhatjuk, hogy a könyvtárak amikat használunk, milyen szisztémát követnek.
Az 5.1.2-es verzióban
az SPL könyvtárral jöttek az
1
spl_autoload(), spl_autoload_register()
függvények. Ez utóbbival lehetőségünk nyílt arra, hogy több, különböző autoloader függvényt regisztráljunk, melyeket azok regisztrációjának sorrendjében (paraméterekkel lehet változtatni) hív meg a program. A szintaxisa roppant egyszerű:
1
2
spl_autoload_register("autoloadController"); // először az autoloadController nevű függvényt hívja meg
spl_autoload_register("autoloadModel"); // utána pedig az autoloadModel nevűt
Vigyázat, amint regisztráltunk egy autoloader függvényt, vagy akár csak paraméterek nélkül meghívtuk a register-t, onnan kezdve a beépített __autoload
függvény nem hívódik meg.
Mielőtt a PHP 5.3-as verziójával bevezették a névtereket, a fejlesztők különféle módszerekkel próbálták áthidalni az osztályok/függvények ütközését. A PEAR Coding Standard például aláhúzásokat alkalmazott, hogy osztályaik eléréséi útját prefixként hozzáfűzze azok nevéhez. Így a Zend_Adapter osztályt a Zend/Adapter.php-ben találtuk. Az autoloader egyszerűen lecserélte az aláhúzásokat és úgy fűzte hozzá a fájlt a kódhoz.
A PSR-0 szabvány
2009-ben egy csapat a PHP közösségből megalakította a PHP Standards Working Group-ot és megalkották a PSR-0 szabványt, aminek a célja az volt, hogy lefektesse azokat a szabályokat, amik a különböző könyvtárak autoloaderjei közti inkompatibilitást hivatottak áthidalni.
Alább álljanak a PSR-0 feltételei:
- Egy névtérnek és osztálynak a következő struktúrát kell követnie:
( )\* - Minden névtérnek kell lennie egy legfelső szintű névtere (“Gyártó”).
- Minden névtér-elválasztót könyvtár elválasztóvá alakítanak, mikor a rendszerbe betöltik azt.
- Az osztály nevében szereplő aláhúzásokat szintén könyvtár elválasztóvá alakítják, ellenben ez nincs kihatással a névterekre.
- A névtér és osztály struktúrája “.php”-végződésű, mikor a rendszerbe betöltik azt.
- A kis és nagybetűk bármilyen kombinációban előfordulhatnak a gyártó, a névtér és az osztályok nevében.
Mit is jelent mindez? Azt, hogyha a jövőben a saját kis könyvtárunkon dolgozunk, akkor érdemes figyelembe venni a fent leírtakat, írni rá egy autoloadert, amit aztán a komolyabb framework-ökbe való implementálás esetén el is lehet hagyni, hisz azoknak ez már részét képezi. Ezzel megkönnyíthetjük a saját dolgunkat, hiszen elkerülhetetlen, hogy ne dolgozzunk Zend/Symfony vagy a többi nagy keretrendszer valamelyikével a jövőben és ott már csak bemásoljuk a megfelelő fájlokat a könyvtárstruktúrából, az adott fájlok elejére írjuk a
1
use SajatKonyvtar\SajatCsomag\SajatOsztaly;
sorokat és máris kész vagyunk, mert a PSR-0 szabványt követő autoload megoldja a többit helyettünk.