1
CodeIgniter keretrendszer 1.1. Bemutatása A készítéskor kitűzött cél az volt, hogy létrehozzanak egy olyan eszközt, amivel lényegesen gyorsabb egy PHP oldalt elkészíteni, mint a nyers PHP-val, mindezt úgy, hogy a programozó szinte észre se vegye, hogy egy keretrendszerben dolgozik, mégis számos szolgáltatás álljon a rendelkezésére. A CodeIgniter egy egyszerű, hatékony, gyors és mégis kezelhető és könnyen használható keretrendszer, ami közel áll a szimpla PHP nyelvhez, viszont birtokolja a keretrendszerek nyújtotta előnyöket is. Letöltés és dokumentáció: http://codeigniter.com/
Előnyei:
Gyors, hatékony
Egyszerűen elsajátítható, gyorsan tanulható, jól dokumentált
Támogatja az MVC fejlesztési modellt (ugyanakkor nem erőlteti rá a programozót annak használatára)
Kiterjeszthető, könnyen bővíthető
Támogatja a keresőbarát URL címek használatát
PHP 4.3.2-n és PHP5 alatt egyaránt működik
Széleskörű adatbázis támogatottsággal rendelkezik: MySQL (4.1+), MySQLi, MS SQL, Postgres, Oracle, SQLite, ODBC.
Biztonságos
Számos jól használható és hasznos kiegészítővel rendelkezik, pl.: e-mail, képmanipuláció, űrlap ellenőrzés, fájl feltöltés, sessionkezelés.
A Librarie-k betöltése csak használatukkor történik meg, így spórolva az erőforrásokat
1.2. Telepítés Használatához szükség van egy szerverre, ami képes PHP 4.3.2., vagy újabb verziójú scriptek futtatására. CodeIgniter letöltése (http://codeigniter.com/downloads/), majd kicsomagolása után rögtön használható.
Kaszab Gábor, Tarcsi Ádám: CodeIgniter PHP Framework
2 A másolás után az /application/config/config.php fájl használatával konfigurálhatjuk a rendszert. Az adatbázis elérés az /application/config/database.php fájlban állítható be. Mindezekről részletesebben később.
1.3. Könyvtárstruktúra A többi keretrendszerhez hasonlóan a CodeIgniter is megkötéseket tesz az elkészített fájlok elhelyezését illetően. A letöltött rendszer a használati utasítást és a licensz dokumentumot leszámítva, tartalmaz egy system könyvtárat és egy index.php fájlt. Az alkalmazásunk és maga a keretrendszer mind ebben a system könyvtárban fog helyet foglalni, aminek a belső szerkezete a következőképp néz ki: application config controllers errors helpers hooks
// konfigurációs állományok // vezérlők // hiba template oldalak // alkalmazás szintű helperek //hook fájlok, melyekkel a CodeIgniter core fájlait módosíthatjuk language // nyelvi fájlok libraries // segéd könyvtárak models // modellek views // nézet állományok cache // cache tárolása codeigniter // a keretrendszer magja database // adatbázis driverek fonts // betűtípusok helpers // beépített segítők, minden alkalmazás számára elérhetőek language // külső nyelvi fájlok libraries // beépített class fájlok, minden alkalmazás számára elérhetőek logs // log fájlok kerülnek ide plugins // plugin-ok scaffolding // scaffolding adatok fejlesztéskori adatbázismanipulációhoz A könyvtárszerkezetet természetesen mi magunk is bővíthetjük olyan mappákkal, mint pl.: css, js, images, stb.
1.4. A CodeIgniter felépítése és működése A CodeIgniter támogatja az MVC, Model-View-Controll modellt. Fontos hozzátenni, hogy a keretrendszer csak támogatja a modellt, de nem kötelezi a fejlesztőt a használatára, azaz megteremti a környezetet a modell használatára, de a programozó feladata eldönteni, hogy alkalmazza-e azt, vagy sem. A továbbiakban feltesszük, hogy az alkalmazásokat az MVC Kaszab Gábor, Tarcsi Ádám: CodeIgniter PHP Framework
3 modellnek megfelelően készítjük el. Egy CodeIgniter oldal főbb alkotóelemei a Controller, View és Model elemek, amik működését a Helper, Plugin, Core osztályok támogatják. Ezeknek az elemeknek a kapcsolatát és a működésben való szerepét a következő példa szemlélteti:
Egy
felhasználó
a
böngészője
segítségével
megpróbálja
elérni
a
http://www.inf.elte.hu/blog/olvas/12 címen lévő oldalt.
6. ábra: Egy CodeIgniter lekérés
A kérések alapértelmezetten a keretrendszer gyökérkönyvtárában található index.php
fájlhoz (FrontController) irányítódnak, ami betölti a működéshez szükséges erőforrásokat.
A Routing szolgáltatás feldarabolja a megadott URL-t és megállapítja, melyik
controller, melyik függvényét kell működésbe hozni, és mik azok a paraméterek, amiket át kell neki adni. A példánál maradva, a „blog” nevű controller, „olvas” nevű függvényét fogja keresni, amit a ’12’ értékkel, mint paraméterrel fog meghívni.
Mielőtt a controller működésbe lép, a felhasználó által megadott adatokon és a HTTP
kérésen lefut egy biztonsági elemzés.
Az üzleti logika a vezérlőben van megvalósítva, ami igény szerint felhasználhat
modelleket, könyvtárakat, Helper osztályokat, plugin-okat és script-eket a kérés eredményének elkészítéséhez.
A vezérlő által generált adatok továbbítódnak a megfelelő nézet fájlhoz, ami
megjeleníti azokat.
Ha be van kapcsolva az oldal cache-elése, akkor először eltárolódik a lekérdezés
eredménye, hogy egy hasonló kérés esetén gyorsabban elő lehessen állítani a választ, és ezután az eredmény egy HTML oldal formájában továbbítódik a felhasználó böngészője felé, ami megjeleníti azt.
1.5. CodeIgniter konfiguráció A keretrendszer konfigurációs állományai a system/application/config/ könyvtárban találhatóak: Kaszab Gábor, Tarcsi Ádám: CodeIgniter PHP Framework
4 -
autoload.php: az automatikusan betöltendő könyvtárakat, helpereket, plugineket, konfigurációs állományokat, nyelvi fájlokat és modelleket adhatjuk meg. Az erőforrások legjobb kihasználása érdekében érdemes azonban csak a legfontosabbakat betölteni, a többit pedig csak használatkor. A leggyakrabban a default adatbázist szokás automatikusan betölteni az alábbi formában: $autoload['libraries'] = array('database');
-
config.php: Általános konfigurációs beállítások. A legfontosabbak az alábbiak: o $config['base_url']: Az alkalmazás elérhetősége, az a könyvtár, ahová a CodeIgniter-t telepítettük. pl.: $config['base_url'] = "http://localhost/ci/"; vagy $config['base_url']= "http://webprogramozas.inf.elte.hu/~ade/albumok/"; o $config['index_page']: A FrontController megadása. Értéke jellemzően: index.php o $config['charset']: default karakterkészlet megadása. Pl.: $config['charset'] = "UTF-8"; o $config['enable_hooks']:
hook
használatának
engedélyezése
pl.:
$config['enable_hooks'] = TRUE; o $config['subclass_prefix']: saját könyvtárak írása esetén az osztályok prefixe. pl.: $config['subclass_prefix'] = 'MY_'; -
constants.php: Rendszer-konstansok definiálása. Alapértelmezés szerint fájl- és könyvtár kezeléshez tartalmaz konstansokat.
-
database.php: Adatbázisok beállításai. Több csoportot is meg lehet adni. Az $active_group = "nev"; beállítással adhatjuk meg az alapértelmezés szerint használatos adatbázist. Alapértelmezés szerint a CodeIgniter egy ’default’ nevű csoportot tartalmaz. Az adatbázis lehetséges beállításai, például: o $db['default']['hostname'] = "localhost"; - az adatbáziskezelő host neve. o $db['default']['username'] = "user"; - a csatlakozáshoz használatos felhasználói név. o $db['default']['password'] = "jelszo"; - a csatlakozáshoz szükséges jelszó. o $db['default']['db'] = "wabp3"; - adatbázis neve, melyhez csatlakozni szeretnénk. o $db['default']['dbdriver'] = "mysqli"; - adatbáziskezelő rendszer típusa. Lehetséges értékei: mysql, mysqli, postgre, odbc, mssql, sqlite, oci8 o $db['default']['dbprefix'] = ""; Prefixek az adatbázis-táblákhoz, amennyiben szükséges.
Kaszab Gábor, Tarcsi Ádám: CodeIgniter PHP Framework
5 o $db['default']['pconnect'] = TRUE; - Folyamatos, perzisztens legyen-e a kapcsolat. o $db['default']['db_debug'] = TRUE; - Adatbázisbeli hiba esetén a hiba megjelenítése vagy annak elnyelése. o $db['default']['cache_on'] = FALSE; - Query cachelés be/kikapcsolása. o $db['default']['cachedir'] = ""; - Cache könyvtár elérési útja o $db['default']['char_set'] = "utf8"; - Az adatbázis kommunikációhoz szükséges karakterkészlet. o $db['default']['dbcollat'] = "utf8_general_ci"; - Karakter egybevetés az adatbázissal történő kommunikációhoz. -
doctypes.php: HTML doctype definíciók.
-
hooks.php: Hook-ok használatának beállítása, melynek segítségével átírhatjuk a CodeIgniter keretrendszer magját, annak hackelése nélkül. Az alkalmazás templatejének hook-al történő beállításához az alábbi két hook lenne szükséges. Lásd később, a Template leírásakor: $hook['post_controller_constructor'] = array( 'class'
=> 'Template',
'function' => 'set_template', 'filename' => 'Template.php', 'filepath' => 'libraries', 'params' => array() );
$hook['post_controller'] = array( 'class'
=> 'Template',
'function' => 'display_template', 'filename' => 'Template.php', 'filepath' => 'libraries', 'params' => array() ); -
mimes.php: Lehetséges mime típusok megadása az Upload osztály számára.
-
routes.php: URI route-k megadása. Két foglalt név van a CodeIgniter-ben. ’default_controller’, mely akkor hívódik meg, amennyiben az URI nem tartalmaz egyéb vezérlő megadást. A másik pedig a ’scaffolding_trigger’ névvel ellátott ún.
Kaszab Gábor, Tarcsi Ádám: CodeIgniter PHP Framework
6 biztonsági szó, melyet biztonsági okokból a scaffolding használata esetén kell megadnunk. Ezek közül a ’default_controller’ érték beállítása a fontos, ellenkező esetben az alapértelmezés szerinti ’welcome’ nevű vezérlő fog meghívódni. pl.: $route['default_controller'] = "auth"; -
smileys.php: Smiley-k megadása a smiley nevű helper számára.
-
user_agents.php: Kliensek definiálása a User Agent Class számára, amennyiben alkalmazásunkat eltérő böngészőtípusokra, platformokra vagy mobil eszközökre szeretnénk optimalizálni.
1.6. Linkek felépítése és Routing Az alábbiakban áttekintjük, hogy hogyan működik a keretrendszer Routing szolgáltatása. Egy alapértelmezett beállításokkal rendelkező, frissen telepített CodeIgniter a következő formában megadott linkeket dolgozza fel: domain/index.php/controller/function/param1/param2 Látható, hogy itt még szerepel az index.php az URL-ben, viszont ez eltüntethető a programot futtató szerver .htacces konfigurációs fájljának módosításával. Ezután ilyenek lesznek az alapértelmezett URL-ek: domain/controller/function/param1/param2 A megadott URL-ben az első paraméter a vezérlő nevét, a második a vezérlő egy függvényének a nevét, a többi pedig a függvénynek átadandó paramétereket határozza meg. Megoldható az is, hogy minden URL végéhez ugyanaz a karaktersorozat legyen hozzáfűzve, amit persze csak a böngészőben látunk, a program működését nem fogja módosítani. Ehhez az application/config/config.php fájlban kell a $config[’url_suffix’] változónak egy értéket megadni. Ha például beállítjuk, hogy ez az url_suffix a „.html” legyen, akkor az URL-ek például az alábbi formában jelennek meg a böngészőben: domain/controller/function.html Arra is lehetőség van, hogy a Routing által generált „szép URL”-eket kikapcsoljuk, amit ugyanebben a fájlban a $config[’enable_query_strings’] = TRUE; értékadással tehetünk meg. Ezután teljesen más formában fognak az URL-ek megjelenni: domain/index.php?c=controllername&m=methodname&id=123 A példában a c lesz a vezérlő neve, az m a vezérlő egy függvényének a neve, az id pedig az átadandó paraméter. Természetesen az alapértelmezett Routing beállítások tetszőlegesen átszabhatók. Az /application/config/routes.php fájlban kezdetben két ilyen routing szabály található, amikhez Kaszab Gábor, Tarcsi Ádám: CodeIgniter PHP Framework
7 tetszőleges számú saját szabályt adhatunk. Az egyik megadott szabály megmondja, melyik vezérlő hívódjon meg, ha megnyitják az alkalmazásunk minden paraméter nélkül, azaz mi legyen az alapértelmezett vezérlő, a másik pedig a scaffolding oldal nevét állítja be. Ezek után a $route[’URL’] = „vezérlő/függvény” formában megadhatók saját szabályok. Az URL megadásához felhasználhatók helyettesítő jelek (wildcard) és reguláris kifejezések. A helyettesítő jelek a „:num” vagy a „:any” azonosítók lehetnek. A szemléltetés kedvéért következzen pár példa: $route[’blog/admin’] = „blog/users/13”: Ha a böngészőben a blog/admin paramétereket adjuk meg, a háttérben a blog vezérlő users függvénye hívódik meg ’13’ paraméterrel. $route[’article/(:num)’] = „article/read/$1”: Az URL-ben az article karaktersorozat után egy számot vár paraméterként, és az article vezérlő read függvényét hívja ezzel a számmal, mint paraméter. $route[’article/:any’] = „welcome”: Az article után bármit megadhatunk, a welcome controller index metódusát hívja meg paraméter nélkül. $route[’product/([a-z]+)’] = „product/$1”: A product azonosító után csak kisbetűket tartalmazó sztringet fogad el, és a product vezérlő paraméterként megadott függvényét hajtja végre.
1.7. Telepítés utáni első tesztelés Kicsomagolás és a böngészőből történő teszteléskor az alábbi kép fogad bennünket, amennyiben a system/application/config/config.php állományban átírtuk a ’base_url’-t, valahogy így: $config['base_url'] = "http://localhost/ci/";
Kaszab Gábor, Tarcsi Ádám: CodeIgniter PHP Framework
8
1.8. Controller osztályok Az MVC modell vezérlő rétegét hivatottak megvalósítani a Controller osztályok. Az MVC szerint ez a réteg hozzáfér az adatokat reprezentáló modell réteghez, azokon műveleteket hajthat végre, és a kívánt adatokat továbbítja a view rétegnek, ami megjeleníti azokat. Így működik ez a CodeIgniter esetében is, azzal a különbséggel, hogy a keretrendszer nem kötelezi a fejlesztőt az MVC modell alkalmazására, azaz az adatbázisban tárolt adatok elérhetők a modell réteget megkerülve, direkt SQL lekérdezések formájában, és a megjeleníteni szánt adatokat nem feltétlenül kell továbbküldeni a nézet rétegnek, mivel azokat ki lehet íratni a vezérlőn keresztül is. Mindenesetre az MVC modell megkönnyíti a programozók dolgát, átláthatóbb, strukturáltabb kódot eredményez, mely . Egy vezérlő osztálynak követnie kell bizonyos minimális konvenciókat, melyek szerint a vezérlő és az őt tartalmazó fájl nevének egyeznie kell, úgy hogy a fájlnév kisbetűvel, az osztálynév pedig nagybetűvel írandó. Ezt a fájlt az /application/controllers könyvtárba kell elhelyezni .php kiterjesztéssel úgy, hogy egy fájl csak egy vezérlő osztályt tartalmazhat és ez az osztály a keretrendszer magjához tartozó Controller osztályból kell, hogy származzon:
9 class Albums extends MY_Controller { Mint minden más osztálynak, így a vezérlő osztálynak is lehet konstruktora. Ennek a konstruktornak kötelező meghívnia a beépített Controller osztály konstruktorát a parent::Controller() paranccsal. Ezen kívül a vezérlő tetszőleges függvényeket tartalmazhat, amik között van pár speciális viselkedésű is. Ilyen például az index() nevű, ami a vezérlő alapértelmezett függvényét jelenti, vagy a _remap($param) függvény, amivel felüldefiniálhatók a Routing-nál megadott szabályok. Ez ennyit jelent, hogy ha egy vezérlőhöz kerül az irányítás, akkor attól függetlenül, hogy melyik függvényét hívták meg, ez a _remap() metódus fog végrehajtódni úgy, hogy paraméterként megkapja az URL controller utáni részét. Ez alapján hozhat döntést arról, hogy melyik függvény legyen az, ami ténylegesen lefut. Speciális funkcionalitást megvalósító függvény még az _output($output) is, ami paraméterként megkapja azokat az adatokat, amiket a vezérlő tovább küldött kiíratásra, és ezeken utómunkálatok végezhetők el még a megjelenítés előtt. Létrehozhatóak private metódusok is, amik nem érhetők el böngésző segítségével, csak a vezérlőn belül. Ahhoz, hogy egy metódust private-té tegyünk, egyszerűen csak egy aláhúzást kell tenni a neve elé.
1.9. View fájlok A megjelenítésért felelősek a yiew fájlok, amik tartalmazhatnak komplett HTML oldalakat, vagy csak egyszerű kódrészleteket, mint például egy fejléc, egy menü stb, vagy templateket is. A CodeIgniter motorja nem jelenít meg automatikusan nézeteket, az csak azért felelős, hogy az URL-nek megfelelő vezérlőt működésre bírja. Ez annyit jelent, hogy a view fájlokat a programozónak kell meghívnia a vezérlőn belül, amire a $this->load->view(’name’) függvény használható. Ahhoz, hogy egy nézetet meg lehessen hívni, először el kell menteni az /application/views/ könyvtárba .php kiterjesztéssel. Az adatok átadását a vezérlőből a nézetbe, szintén ez a view függvény végzi úgy, hogy a második paraméterének átadunk egy $data változót, ami lehet egy sima változó, egy összetett tömb, vagy akár egy objektum is. Az átadás után ez a változó elérhető lesz a nézeten belülről is. Ugyanez a metódus elfogad egy boolean típusú harmadik paramétert is, ami igaz érték esetén nem küldi el a view fájl által generált oldalt a felhasználónak, hanem visszatérési értékként visszaadja azt a vezérlőnek. Alapértelmezett beállítása false, ami azt jelent, hogy az oldal küldésre kerül, amint elkészül.
Kaszab Gábor, Tarcsi Ádám: CodeIgniter PHP Framework
10 A HTML kód olvashatóbbá tétele miatt lehetővé tettek egy a megszokottól eltérő PHP szintaxis használatát. Ennek lényege, hogy a megjelenítéskor használt, if, foreach, for, és while nyitó- illetve csukó zárójeleit el lehet hagyni és helyettük sokkal átláthatóbb módon endif, endforeach, endfor, és endwile kulcsszavak használhatók, valamint a kiíró echo parancsok egy =változónév?> utasítással helyettesíthetők. Egy példa kód:
=$item?> Előfordulhat, hogy a szerver, amin a program fut, nem támogatja ezeket a jelöléseket. Ilyenkor a CodeIgniter átírja a kódot a hagyományos formára. A megjelenítő réteg, Helper osztályok formájában számos segítséget használhat az oldal egységesítésére, mindkezekről később a Helper részben lehet bővebben olvasni.
1.10. Model osztályok A model osztályok feladata az adatokat tároló adatbázis és az üzleti logikát megvalósító vezérlő réteg közötti kapcsolat megteremtése. A modell fájlokat az /application/models könyvtárba kell tenni úgy, hogy a fájlnév megegyezzen a benne tárolt modell nevével, azzal a különbséggel, hogy a modell neve nagybetűvel kezdődik, a fájlé pedig kicsivel. Egy modell minden esetben az ős Model osztályból származik, és ha van konstruktora, akkor meghívja az ősosztály konstruktorát is a parent::Model() paranccsal. Mivel a CodeIgniter nem használ ORM technológiát, ezért egy modell osztály nem kötődik össze automatikusan a neki szánt adatbázis táblával, vagyis a programozó feladata a tábla mezőinek megfelelő változók létrehozása az osztályon belül, valamint ezen változók értékének a karbantartása is a fejlesztők felelőssége. Egy modellen belül tetszőleges függvény megvalósítható, általában ezeket a metódusokat az adatbázis adatok lekérdezésére, módosítására és törlésére szokták használni. Ha létrehoztuk a szükséges modelleket, akkor lehetőségünk van azokat a vezérlőben is felhasználni,
amihez
első
lépésként
meg kell
hívni
őket,
amit
a
$this->load-
>model(’modellnév’) paranccsal tehetünk meg. Ha már meghívtuk, akkor a $this>modellnév->függvénynév() paranccsal érhetjük el a modellen belüli szolgáltatásokat. A következő példához tegyük fel, hogy van egy Albums nevű modell, amiben egy get_albums() metódus kérdezi le az összes albumot. A vezérlő, ami az MVC modellnek megfelelően kiíratja ezeket a bejegyzéseket, így néz ki: Kaszab Gábor, Tarcsi Ádám: CodeIgniter PHP Framework
11 $this->load->model(’albums’); $data[’result’] = $this->albums->get_albums(); $this->load->view(’nézetnév’, $data);
1.10.1.
Adatbázis lekérdezések és az Active Record Pattern
Ahhoz, hogy a modellen belül hozzáférjünk az adatbázishoz, két lehetőséget biztosít a CodeIgniter. Az első a saját SQL lekérdezések írása, a második pedig az Active Record osztály használata. Ahhoz, hogy ezeket a szolgáltatásokat igénybe vegyük, a keretrendszerbe épített Database osztályt kell használnunk, ami db néven mindenhol elérhető egy projekteken belül. Saját SQL parancsok végrehajtása a $this->db->query(„SQL prancs”) metódussal megtehető, és egy eredmény objektumot ad vissza, amiből kinyerhetők az eredményül kapott sorok. Az adatbázis védelme érdekében ajánlatos az SQL parancsunkat biztonságossá tenni, azaz escape-elni, amit a Database osztály escape(), escape_str() és escape_like_str() metódusokkal érhetünk el. Van lehetőség BIND használatára is: a query metódusnak átadott SQL parancsban a behelyettesítendő változók helyére egy kérdőjelet teszünk, és a függvénnyel a második paraméterben átadott tömbben közöljük ezeket az értékeket. Ilyenkor a beillesztendő értékek automatikusan escape-elődnek. Például: $this->db->query(„SELECT * FROM tábla WHERE name = ?”, array(’alma’)); A keretrendszer által nyújtott Active Record szolgáltatás szerint SQL lekérdezések helyett, CodeIgniter parancsok egymás után fűzésével generálhatók a platformfüggetlen lekérdezések. Például a $this->db->get(’táblanév’) parancs a háttérben egy „SELECT * FROM táblanév” SQL lekérdezést generál. Amennyiben kiadunk az említett get parancs előtt egy where(’mezőnév operátor’, ’érték’) utasítást, akkor két függvény eredménye összefűződik, azaz lekérdezésként a „SELECT * FROM táblanév WHERE mezőnév operátor érték” utasítás hajtódik végre. Ugyanígy egymás után fűzhetők a select(), from(), select_min(), select_max(), select_avg(), select_sum(), or_where(), join(), where_in(), or_where_in(), where_not_in(), or_where_not_in(), like(), or_like(), not_like(), or_not_like(), group_by(), distinct(), having(), or_having(), order_by(), limit(), parancsok, amikből tetszőleges bonyolultságú SQL lekérdezés generálható. PHP 5 alatt ezeket összefűzhetjük a következő módon: $this->db->select(’author’)->from(’books’)->where(’price <’, 5000); Ez a „SELECT author FROM books WHERE price < 5000” lekérdezést készíti el a háttérben. Hasonlóan használható az adatok beszúrására szolgáló insert(’tábla’, $data), és a módosítást végző update(’tábla’, $data) függvények, ahol a $data lehet egy adatokat tartalmazó tömb, Kaszab Gábor, Tarcsi Ádám: CodeIgniter PHP Framework
12 vagy objektum. A törlést a delete(’tábla’, feltételek) paranccsal lehet végrehajtani, ahol a feltételek változó, egy olyan asszociatív tömb, amely mező, érték párokat tartalmaz. Mivel a lekérdezést végző függvények visszatérési értékként a lekérdezés eredményét adják, célszerű azt az eredményt egy változónak átadni, amiből később hasznos adatokat nyerhetünk ki. Egy sornak megfelelő objektumot a $result() paranccsal tudunk lekérdezni, míg a $result_array() ugyanezt végzi, csak objektum helyett tömbben adja vissza az eredményt. A $num_rows() és $num_fields() metódusok értelemszerűen a lekérdezés eredményében szereplő sorok, illetve oszlopok számát adják meg. Példa: function get_albums($id = '', $nev = '', $leiras = '') { $sql = "select id, nev, leiras from albums where id like ? and nev like ? and leiras like ? order by nev"; $result = $this->db->query($sql, array( "%$id%", "%$nev%", "%$leiras%" )); return $result->result_array(); } Az eddig említett szolgáltatásokon kívül számos lehetőséget kínál a beépített Database osztály, például adatokat kérdezhetünk le a táblákról és mezőikről, a műveleteinket tranzakciókba zárhatjuk, a lekérdezéseket eltárolhatjuk egy cache-objektumban, adatbázisokat hozhatunk létre, törölhetünk ki.
1.11. Hook osztályok A CodeIgniter működésébe van lehetőségünk belenyúlni a hook fájlok segítségével, azaz az egyes munkafázisok elé vagy után szúrhatunk be tetszőleges logikát. Kezdésnek engedélyezni kell a hook-ok használatát az /application/config/config.php-ban a $config['enable_hooks'] = TRUE; beállításával, majd az ugyanebben a könyvtárban Kaszab Gábor, Tarcsi Ádám: CodeIgniter PHP Framework
13 található hooks.php fájlba elhelyezett deklaráció segítségével hozzá is rendelhetjük a kívánt függvényt az alkalmazás végrehajtási menetének egy lépéséhez. A deklaráció így néz ki: $hook['hook_point'] = array( 'class' => 'MyClass', 'function' => 'Myfunction', 'filename' => 'Myclass.php', 'filepath' => 'hooks', 'params' => array('param1', 'param2') ); A hook_point mondja meg, a végrehajtás során, mikor hajtódjon végre a beszúrandó logika. Ez az alábbi értékeket veheti fel: pre_system: A végrehajtás legelején fut le, amikor még a Routing szolgáltatás sem indult el.
pre_controller: A Routing és a biztonsági ellenőrzés után, de a vezérlő működése előtt
fut le.
post_controller_constructor: A vezérlő létrejötte után, de a működése megkezdése
előtt hajtódik végre.
post_controller: Akkor fut le, amikor a vezérlő befejezte a működését.
display_override: A keretrendszer beépített _display() metódusát írja felül, ami
alapértelmezetten az elkészített weblapot küldi ki a böngészőnek.
cache_override: Felülírja a rendszer _display_cache() függvényét. Lehetővé teszi,
hogy saját cache logikát valósítsunk meg.
scaffolding_override: Egy scaffolding request ezt a függvényt fogja meghívni.
post_system: A weboldal renderelése után fut le, miután a böngészőnek küldött válasz
kiküldésre került. A deklarálás során használt class, function, és filename paraméterek mondják meg, melyik osztály, melyik függvényét szeretnénk futtatni, és ez melyik fájlban található. A filepath határozza meg, melyik könyvtárban helyezkedik el a keresendő fájl, és a params segítségével adhatók át paraméterek a függvénynek.
1.12. Core osztályok A CodeIgniter rendelkezik számos olyan beépített osztállyal, amelyek hatalmas segítséget nyújtanak a háttér logika megvalósításában. Az ilyen osztályokat a libraries könyvtárban találjuk és könyvtáraknak, vagy Core osztályoknak nevezzük. Egy meglévő könyvtárat a $this->load->library(’név’) módon lehet importálni egy vezérlőbe.
Kaszab Gábor, Tarcsi Ádám: CodeIgniter PHP Framework
14 Amellett, hogy a beépített könyvtárakat használjuk, arra is van lehetőség, hogy saját könyvtárakat hozzunk létre, vagy kibővítsünk, sőt felülírjunk meglévőket. Saját könyvtár készítése nem jelent mást, mint egy osztály létrehozását és az /application/libraries könyvtárban való elhelyezését úgy, hogy mind az osztály neve, mind az őt tároló fájl neve nagybetűvel kell, hogy kezdődjön, és meg kell, hogy egyezzen. Ezután bármelyik vezérlőben meghívható és felhasználható a kisbetűs példánya segítségével. Paraméterek is átadhatók a saját Core osztály konstruktorának úgy, hogy az őt importáló függvény második paraméterének megadjuk az átadni kívánt változókat. Fontos különbség egy könyvtár és egy vezérlő között, hogy egy könyvtárban nem használható a $this változó. Helyette egy másolatot kell készíteni a fő CodeIgniter objektumból a $CI = &get_instance() használatával, amivel ugyanazok a műveletek végezhetők el, mint a $this objektummal. Mint már írtam, a beépített könyvtárak tetszőlegesen kiegészíthetők. Ehhez létre kell hozni egy olyan osztályt, aminek a neve a kiegészítendő osztály nevével megegyezik, azzal a különbséggel, hogy kap egy „MY_” prefixet is. A bővítésben, ha használjuk a konstruktorát, kötelezően meg kell hívni a szülő könyvtár konstruktorát is, valamint a fájlnévnek meg kell egyeznie a kiegészítendő Core osztály fájlnevével, plusz az említett „MY_” prefix. A gyakorlatban ez az Email könyvtár frissítésénél a következőt jelenti: class MY_Email extends CI_Email { function My_Email() { parent::CI_Email(); } } Ezt az osztályt az /application/libraries/MY_Email.php fájlban kell elhelyezni. Ha helyesen végeztük az elnevezéseket, akkor a sima Email könyvtár importálásakor a saját, kiegészített Email könyvtárunk fog importálódni. Egy meglévő könyvtár felüldefiniálása még ennél is egyszerűbb. A felülírandó osztály és fájl elnevezéseit használva el kell készíteni egy saját osztályt, amit ezután be kell másolni a libraries könyvtárba, ahol felül kell írni a meglévő fájlt és már kész is. A Database és Loader osztályok azok, amikhez nem lehet ilyen módon hozzányúlni, viszont az összes többi libraries-ben megtalálható szolgáltatás tetszőlegesen kiegészíthető és felülírható. A beépített könyvtárak között van olyan, amivel az oldal teljesítményét lehet mérni (Benchmarking), amivel testre szabható naptárat lehet készíteni (Calendar), amivel üzeneteket lehet titkosítani (Encrypt), ami a fájl feltöltést támogatja (Upload), amivel egyszerűen hozható létre HTML táblázat (Table). Ezeken kívül támogatott a képek szerkesztése (Image_lib), az Kaszab Gábor, Tarcsi Ádám: CodeIgniter PHP Framework
15 oldalak többnyelvűsítése (Language), Email-ek küldése (Email) és a lekérdezések lapozhatóvá tétele (Pagination). Az említettek mellett még számos további funkciót kézhez kapunk a keretrendszer használatával. A következő részekben a Session, Cart és Validation osztályokkal fogok részletesebben is foglalkozni.
1.12.1.
Session osztály
Bizonyára minden webfejlesztő használt már session-t a weblapjai elkészítése során arra, hogy adatokat tároljon, így nem meglepetés az, hogy a CodeIgniter is rendelkezik egy Session műveleteket támogató beépített osztállyal. Ez az osztály azonban nem egyezik meg a PHP nyelv által felkínált session szolgáltatással. Az adatok tárolásának két módja van: Alapértelmezés szerint a session-ben tárolni kívánt adatokat, tömb formájában, sorosítva fogja elraktározni az alkalmazás sütijei között úgy, hogy ezek az adatok opcionálisan még titkosíthatók is. Továbbá a nagyobb biztonság érdekében a session adatok eltárolhatók adatbázisban is. Ebben az esetben, az oldal betöltésekor, ha van a sütik között tárolt session adat, akkor lekérdezi az azonosítóját (Session ID) és megnézi, hogy van-e az adatbázisban hozzá tartozó bejegyzés. Ha nincs, a session lerombolódik és egy teljesen új indul. Ahhoz, hogy adatbázisban tudjuk eltárolni a session adatainkat, létre kell hozni az ehhez szükséges adattáblát az alábbi struktúra szerint: Táblanév: ci_sessions session_id: varchar(40) DEFAULT '0' NOT NULL, PRIMARY KEY ip_address: varchar(16) DEFAULT '0' NOT NULL user_agent: varchar(50) NOT NULL last_activity: int(10) unsigned DEFAULT 0 NOT NULL user_data: text NOT NULL Egy CodeIgniter-ben készített session minimum négy értéket tartalmaz. Ezek a session azonosító, az IP cím, adatok a felhasználóról (User Agent Data), és az utolsó aktivitás ideje. Ezek mellé lehet még saját adatokat is eltárolni, amihez a session->set_userdata($array) műveletet használva nyílik lehetőség. Paraméterként egy tömböt vár, ami azonosító-érték párokat tartalmaz. A tárolt értékeket kiolvasni a userdata(’azonosító’) paranccsal lehet. Az adatok törlését a Session osztály unset_userdata(’azonosító’) metódusa végzi, az egész session pedig a sess_destroy() paranccsal törölhető. Általában olyan adatok kerülnek egy session-be, amikre huzamosabb ideig szükség van, mint például a bejelentkezett felhasználó azonosítója vagy, hogy be van-e egyáltalán jelentkezve valaki. A beépített Session osztállyal olyan adatok is tárolhatók, amik csak a következő oldalletöltésig maradnak meg. Tipikusan ilyenek azok az üzenetek, amik a Kaszab Gábor, Tarcsi Ádám: CodeIgniter PHP Framework
16 felhasználót értesítik valamilyen tevékenység sikerességéről, például sikeres belépés, kilépés, vásárlás esetén kiírni szánt üzenetek. Ezeket Flash adatoknak hívjuk és az említett osztály set_flashdata(’azonosító’,’érték’) művelettel lehet őket elmenteni, a flashdata(’azonosító’) szolgál az elérésükre és a keep_flashdata(’azonosító’) hívása után a megadott adat még egy oldalbetöltésig tárolva marad.
1.12.2.
Cart osztály
A session-ök egy tipikus felhasználása az, amikor a felhasználó egy webáruházban a kosárba teszi azokat a termékeket, amiket majd később meg szeretne venni, és a háttérben ezek a termékek egy session változóban kerülnek eltárolásra. Mivel egyre több webáruház elkészítésére van igény, így egy nagyon praktikus eszközt nyújt a fejlesztők számára a CodeIgniter Cart osztálya, ami pont ezt a bevásárlókocsi szolgáltatást valósítja meg. A Cart osztály az előző pontban részletezett Session osztály segítségével kezeli és tárolja el az adatokat egy adattáblában, tehát a használatához létre kell hozni a szintén az előző pontban említett módon a ci_sessions adattáblát. Hacsak nem használjuk másra a Session osztályt, akkor nem szükséges meghívni a vezérlőbe, ugyanis a Cart osztály, ezt automatikusan megteszi. Adatok elhelyezéséhez a Cart osztály insert($data) metódusát kell használni, ahol a paraméterre bizonyos szerkezeti kritériumoknak teljesülniük kell: $data = array( 'id' => 'azonosító', 'qty' => 1, 'price' => 2590, 'name' => 'Póló', 'options' => array('Méret' => 'L', 'Szín' => 'Piros') ); A paraméterként átadott adatok között kötelezően szerepelnie kell egy id, egy qty, egy price és egy name mezőnek, amik az egyedi azonosítót, mennyiséget, árat és termék nevet határozzák meg, továbbá opcionálisan megadhatók különböző tulajdonságok a tárolandó termékről. Ez utóbbi az options tömb feltöltésével tehető meg, ami tetszőleges számú adatot tartalmazhat kulcs-érték párok formájában. A kosárban tárolt elemek módosításához az update($data) függvény használható, ahol a $data tömbnek így kell kinéznie: array( 'rowid' => 'b99ccdf16028f015540f341130b6d8ec', 'qty' => 3 );
Kaszab Gábor, Tarcsi Ádám: CodeIgniter PHP Framework
17 A megadott adatnak tartalmaznia kell egy sor azonosítót (Row ID), ami egyértelműen meghatározza, melyik termékről van szó, és egy mennyiséget. Ha a mennyiség nulla, akkor a kívánt termék eltávolításra kerül a kosáról. Az említett sor azonosító egy olyan azonosító, amit a Cart osztály generál akkor, amikor egy új termék kerül a kosárba. Erre azért van szükség, hogy azonos termékek, de különböző tulajdonságokkal is a kosárba kerülhessenek, például két ugyanolyan azonosítóval rendelkező póló, de az egyik piros, a másik kék színben. Már volt szó a kosárba tételről, módosításról és törlésről, most nézzük a kosár megjelenítését. Ez egy tetszőleges view fájlban megtehető, ahol a kosár kinézete a fejlesztőre van bízva. A létrehozáshoz felhasználhatja a Cart osztály metódusait, azaz lekérdezheti egy lista formájában a kosár tartalmát a contents() függvénnyel, hozzáfér egy termék tetszőleges adatához, így a módosításhoz szükséges Row ID-hez is, kiírhatja a kosárban lévő termékek árának összegét a total() metódussal vagy akár az áruhoz megadott tulajdonságokat is lekérdezheti a product_options() segítségével.
1.12.3.
Validaton osztály és adatellenőrzés
Az űrlapokon keresztül megadott felhasználói adatok ellenőrzése az a művelet, amit weblap típustól függetlenül mindig el kell végezni, ellenkező esetben hibás működés következhet be. A CodeIgniter célja, a bemenő adatok egyszerű ellenőrzése úgy, hogy ne kelljen hosszú, átláthatatlan kódot írni a feladat elvégzéséhez. Első lépésként egy nézet fájlban létre kell hozni az ellenőrizni kívánt form-ot, ahol az űrlap fejlécének elkészítéséhez célszerű a Form Helper segítségét igénybe venni. Ha megvan a nézet fájl, létre kell hozni az ezt kiszolgáló vezérlő osztályt, úgy hogy a vezérlő neve a nagybetűs változata legyen a form nevének. A szükséges fájlok létrehozása után a vezérlőben, a form_validation osztály importálását követően, meg kell adni az űrlap mezőire vonatkozó szabályokat a form_validation>set_rule(’mezőnév’,’név’,’szabály’) módon. Itt a mezőnév, értelemszerűen a form-nál megadott imput mező nevét jelenti, a név viszont az a név, amit egy esetleges hibaüzenetben szeretnénk, hogy megjelenjen. Ha megadtuk a mezőkre vonatkozó szabályokat, a form_validator->run() paranccsal ellenőrizhetjük le, hogy helyesen lettek-e megadva a bemenő adatok. Az említett függvény igaz értékkel tér vissza, ha az adatok helyesek, különben hamissal. A megadható szabályok a következők lehetnek:
required: A mezőt kötelezően meg kell adni.
matches[]: A mező értékének meg kell egyeznie egy másik mező értékével
min_length[]: A megadott érték minimum hossza.
Kaszab Gábor, Tarcsi Ádám: CodeIgniter PHP Framework
18
max_length[]: A megadott érték maximum hossza.
exact_length[]: A megadott érték pontos hossza.
alpha: A mező csak betűket tartalmazhat.
alpha_numeric: A mező alfanumerikus karaktereket tartalmazhat.
alpha_dash: A mező csak alfanumerikus karaktereket, aláhúzást és idézőjelet
tartalmazhat.
numeric: A mező csak számot tartalmazhat.
integer: A mező csak integer értéket tartalmazhat.
is_natural: A mező csak természetes számokat tartalmazhat.
is_natural_no_zero: A mező csak nullától különböző természetes számokat
tartalmazhat.
valid_email: A mező csak helyes email címet tartalmazhat.
valid_emails: Ugyanaz, mint az előző, csak lehet benne több email cím is.
valid_ip: Csak érvényes IP cím adható meg.
Ha egy mezőhöz több szabályt szeretnénk megadni, akkor a szabályokat a „|” jellel kell egymás után fűzni. Arra is van lehetőség, hogy az ellenőrzéshez ne a beépített szabályokat, hanem egy saját függvényt rendeljünk. Ilyenkor meg kell írni az ellenőrző függvényt úgy, hogy egy paramétere legyen, aminek majd a mező tartalma fog átadódni, és a mezőhöz a set_rule metódus harmadik paraméterének a ’callback_függvénynév’ értéket kell megadni. A set_rule függvény nem csak szabályok mezőkhöz rendelésére jó, hanem elő is készíthetjük vele a felhasználó által megadott értéket a feldolgozásra. Erre bármilyen, olyan alap PHP függvény használható, ami egy paramétert fogad el (például md5, htmlentities stb.). Nézzünk egy példát: Van két beviteli mező, egy password és egy password2, nevű és azt szeretnénk, hogy a password mező ne legyen üres, tartalma megegyezzen a password2 mezőével és az ellenőrzés után az md5 függvénnyel kódolt értékét szeretnénk használni. Ebben az esetben a password mezőhöz tartozó szabály így néz ki: set_rules('password', ’Jelszó’, 'required|matches[password2]|md5'); Természetesen, hibás mező esetén hibaüzenetet kell küldeni a felhasználónak, amik alapértelmezetten az /application/language/english/form_validation_lang.php fájlban vannak eltárolva. Minden hibaüzenetnek van egy neve, és ha azt szeretnénk, hogy egy szabály meghiúsulása
esetén
valamelyik
hibaüzenet
jelenjen
meg,
akkor
a
set_message(’szabály’,’hibanév’) metódust kell használni, ahol a hibaüzenetben a megfelelő helyre automatikusan beillesztődik a szükséges mező neve. Ez csak beállítja a hibaüzeneteket, Kaszab Gábor, Tarcsi Ádám: CodeIgniter PHP Framework
19 de nem jeleníti meg. A megjelenítéshez el kell helyezni egy ’echo validation_errors()’ PHP sort a nézet fájlon belül.
1.13. Helper osztályok A CodeIgniter alkalmazások utolsó építőkövét jelentik a Helper, azaz segítő osztályok. Feladatuk valamilyen kisebb részproblémák megoldásának könnyebbé tétele. A továbbiakban áttekintő leírást adok arról, milyen Helper osztályok vannak és ezek mire valók. Nézzük a rendelkezésre álló segítőket: Array Helper: Két függvényt ad, amivel a tömbökben tárolt adatok érhetők el. Az element(’kulcs’, $tömb) visszaadja a megadott asszociatív tömbben lévő, kulcshoz tartozó értéket, vagy ha nincs ilyen kulcs, akkor NULL értékkel tér vissza. Másik, random_element($tömb) metódusa egy sima tömb elemei közül ad vissza egy véletlenszerűen választottat. Compatibility Helper: Előfordulhat, hogy a weblap megvalósítása során, olyan függvények lettek felhasználva, amik csak PHP 5 alatt támogatottak, viszont az oldalt egy olyan szerverre kell feltölteni, amin csak a PHP 4-es verziója fut. A Compatibility Helper ilyenkor segítséget nyújthat, mivel PHP 4 implementációt tartalmaz a PHP 5-öt használó függvényekhez. Cookie Helper: Segítségével új sütiket készíthetünk, menthetünk és érhetünk el, valamint törölhetünk meglévőket. Függvényei a set_cookie(), get_cookie(), delete_cookie(). Date Helper: Ha dátumokat kell kezelni, akkor az ezt támogató eszközt a Date Helper nyújtja. Lekérdezhető az aktuális idő, beállítható a dátum formátuma, sőt még időzóna választó felület is generálható vele. Directory Helper: A directory_map() függvényével lehetőséget biztosít egy bizonyos könyvtár alatti könyvtárstruktúra lekérdezésére. Az eredményt egy tömbben adja vissza. Download Helper: Egyetlen függvénye a force_download($fájlnév,$adat) beállítja az oldal fejlécét úgy, hogy a megadott adatot, a megadott fájlként felkínálja letöltésre a felhasználó számára. Ez a megadott adat lehet akár egy rövid szöveg, vagy egy létező fájl is. Email Helper: A Core osztályoknál említett Email könyvtár egy leegyszerűsített változata, amivel egy email cím helyességét lehet leellenőrizni, valamint egyszerű email-eket lehet küldeni. File Helper: Használatával fájlok hozhatók létre, nyithatók meg és törölhetőek. Továbbá lekérdezhető vele egy könyvtár tartalma, és a hozzáférési jogokat is vele lehet beállítani. Kaszab Gábor, Tarcsi Ádám: CodeIgniter PHP Framework
20 Form Helper: Erről a segítőről már érintőlegesen volt szó a Validation osztály pontban, az ellenőrizni kívánt űrlap elkészítésénél. Az űrlapok nyitó és záró elemén kívül a beviteli és rejtett
mezők
is
legenerálhatók
a
használatával.
Fontosabb
függvényei
a
form_open(’URL’), form_hidden(), form_input(), form_password(), form_upload(), form_textarea(), form_dropdown(), form_multiselect(), form_checkbox(), form_radio(), form_submit() és a form_close(), amikkel elkészíthetők a kívánt elemek. HTML Helper: Jól formázott HTML elemek készítését teszi lehetővé. Ilyen elemek a br, img, link, meta, doctype HTML tag-ek, a szóközök és a listák. Inflector Helper: Ez egy olyan segítő, ami átalakítja a szavakat egyes és többes számba, a szövegeket pedig nagybetűsített, aláhúzásokkal kiegészített és normál alakra. Mivel nem beépített szótárral dolgozik, hanem merev algoritmusokkal, ezért csak angol szavakkal és azok közül is a nem rendhagyóakkal működik. Language Helper: A nyelvi fájlok használatával segít többnyelvűsíteni az oldalt. A lang(’language line’, ’item id’) metódusa a nyelvi fájl egy megadott sorából kiveszi a szükséges nyelven várt szót és ezt beleteszi egy, a megadott azonosítóval ellátott label elembe. Number Helper: Ennek a segítőnek az egyetlen metódusa arra szolgál, hogy egy paraméterként megadott számról visszaadja annak bájtban számolt méretét. A méret lehet Byte, KB, MB, GB, TB is. Path Helper: A segítővel eldönthető egy linkről, hogy valódi, létező helyre mutat-e. Security Helper: Főleg az adatok sha1 és md5 kódolására használatos. Smiley Helper: Manapság a fórumoknál, blogoknál és chat-eken nem csak szövegeket, képeket, hanem hangulatjeleket, úgynevezett smiley-t is meg lehet osztani. Az ilyen hangulatjelek generálását végzi a Smiley Helper. String Helper: Egyszerű string műveletek végzésére képes. El lehet vele távolítani idézőjeleket, egy szöveget sokszorosítani, egymás után ismétlődő karaktereket eltávolítani, és véletlenszerű string-et előállítani. Text Helper: Hosszabb szövegeken végez műveleteket. Meg lehet adni, hogy egy bizonyos számú szó után levágja a szöveg többi részét és egy megadott karaktersorozatot tegyen a helyére. Ugyanez elvégezhető bizonyos számú karakter után is. Ezeken kívül ACSII karaktereket konvertál, bekezdéseket emel ki, és tördeli a hosszabb szövegeket. URL Helper: Használatával a különböző oldalak URL-jeit lehet lekérdezni, linkeket lehet létrehozni és átirányításokat lehet alkalmazni. Kaszab Gábor, Tarcsi Ádám: CodeIgniter PHP Framework
21 XML Helper: Egyetlen függvénye az xml_convert($string) kap egy string-et paraméterként és átkonvertálja XML formátumúvá.
Kaszab Gábor, Tarcsi Ádám: CodeIgniter PHP Framework