Využití OOP v praxi -- Knihovna PHP -- Interval.cz
Page 1 of 6
Knihovna PHP Využití OOP v praxi Po dlouhé teorii přichází na řadu praxe. V následujícím textu si vysvětlíme možnosti přístupu k databázi pomocí různých vzorů objektově orientovaného programování v PHP. Představme si například internetový obchod, který pracuje s MySQL. Běžný e-shop může mít i několik desítek tisíc řádků kódu. Pokud se změní syntaxe jazyka nebo budete chtít změnit typ databáze, znamená to, že musíte projít všechny řádky kódu a zápis změnit. S OOP tento problém vyřešíte během několika málo minut. Funkce pracující se syntaxí SQL totiž nejsou součástí procedurálního uspořádání kódu, jsou vázány v objektech, a tak změna jednoho zápisu ovlivní chování celého kódu, který tuto třídu využívá.
Zadání Naším cílem bude vytvořit kód rozhraní, které umožní komunikaci s databází MySQL i SQLite (případně dalších) s tím, že výběr typu databáze umožníme pouhou změnou jedné hodnoty proměnné. Při tvorbě aplikace využijeme abstraktní třídu, implementace rozhraní, dereference objektů a podobně.
Přípravy Nejprve je třeba vytvořit databáze v SQLite i MySQL, vytvořit tabulky a databázi naplnit daty. Stáhněte si proto pomocný skript, který za vás vytvoří stejnou tabulku v MySQL i SQLite a naplní ji 150 náhodnými záznamy (v phpMyAdmin je třeba vytvořit databázi "oop").
Vytvoření proměnných a vzoru Factory Nejprve si vytvoříme několik proměnných, které budou obsahovat informace o připojení a typ databáze. Pak pomocí vzoru factory zavoláme různou třídu podle hodnoty proměnné $type:
= = = = =
'SQLite'; 'localhost'; ''; ''; 'oop';
function Factory($typ,$host,$uzivatel,$heslo,$databaze){ if($typ == 'MySQL'){ return new MySQL($host,$uzivatel,$heslo,$databaze); }else if($typ == 'SQLite'){ return new SQLite($databaze); }else{ return FALSE; } } ?>
http://php.interval.cz/clanky/vyuziti-oop-v-praxi/
12.10.2008
Využití OOP v praxi -- Knihovna PHP -- Interval.cz
Page 2 of 6
Třídě MySQL předáváme čtyři proměnné, třídě SQLite je třeba předat pouze název databáze.
Definice tříd MySQL a SQLite a rozhraní Pro obě třídy MySQL a SQLite vytváříme stejnou strukturu, vytvoříme si tedy rozhraní, které obě třídy implementují. Funkce obou tříd je vytvoření spojení s příslušnou databází a volání další třídy, která provádí hlavní logiku operací: host = $host; $this->uzivatel = $uzivatel; $this->heslo = $heslo; $this->databaze = $databaze; } public function spojeni(){ @$this->spoj = mysql_connect($this->host,$this->uzivatel,$this->heslo) or die('Spojení se nezdařilo'); @mysql_select_db($this->databaze, $this->spoj) or die('Databáze neexistuje'); } public function dotaz($dotaz){ if(!$this->spoj){ $this->spojeni(); } return new VraceniDotazuMySQL($this->spoj,$dotaz); } } class SQLite implements Spojeni{ public $databaze; public $spoj; public function __construct($databaze){ $this->databaze = $databaze; } public function spojeni(){ $this->spoj = sqlite_open($this->databaze) or die('Spojení se nezdařilo'); } public function dotaz($dotaz){ if(!$this->spoj){
http://php.interval.cz/clanky/vyuziti-oop-v-praxi/
12.10.2008
Využití OOP v praxi -- Knihovna PHP -- Interval.cz
Page 3 of 6
$this->spojeni(); } return new VraceniDotazuSQLite($this->spoj,$dotaz); } } ?>
Definice tříd VraceniDotazuMySQL a VraceniDotazuSQLite a abstraktní třídy Nejprve vytvoříme abstraktní třídu. Proč nevytváříme rozhraní? Obsahuje totiž jednu metodu, která bude ve všech třídách stejná, a tak je jednodušší tuto metodu definovat jako abstraktní. Připomínám, že abstraktní třída se neimplementuje, ale dědí (nemůže sama vytvářet instance). VratPole()){ $pole[] = $radek; } return $pole; } } ?> Dále vytváříme třídy VraceniDotazuMySQL a VraceniDotazuSQLite. Konstruktor přiřazuje hodnoty předaným vlastnostem. Metoda Vlozeni() nejprve vytváří pole z argumentů, které metodě byly přiřazeny. Pak pomocí cyklu foreach připravíme dotaz pro databázi. Metoda VratPole() už následně vytváří pole hodnot, které jsme získali z databáze. K syntaxi dotazů se ještě později vrátíme. spojeni = $spojeni; $this->dotaz = $dotaz; } public function Vlozeni(){ $argumenty = func_get_args(); foreach ($argumenty as $index => $hodnota){ $this->argumenty[$index + 1] = $hodnota; } $pocet_argumentu = count($argumenty); $dotaz = $this->dotaz; foreach($this->argumenty as $index => $hodnota){ $dotaz = str_replace(":$index","'".mysql_escape_string($hodnota)."'", $dotaz); }
http://php.interval.cz/clanky/vyuziti-oop-v-praxi/
12.10.2008
Využití OOP v praxi -- Knihovna PHP -- Interval.cz
Page 4 of 6
$this->vysledek = mysql_query($dotaz); if(!$this->vysledek){ return FALSE; } return $this; } public function VratPole(){ return mysql_fetch_array($this->vysledek); } } class VraceniDotazuSQLite extends VraceniDotazu{ protected $spojeni; protected $dotaz; protected $argumenty; protected $vysledek; public function __construct($spojeni, $dotaz){ $this->spojeni = $spojeni; $this->dotaz = $dotaz; } public function Vlozeni(){ $argumenty = func_get_args(); foreach ($argumenty as $index => $hodnota){ $this->argumenty[$index + 1] = $hodnota; } $pocet_argumentu = count($argumenty); $dotaz = $this->dotaz; foreach($this->argumenty as $index => $hodnota){ $dotaz = str_replace(":$index","'".sqlite_escape_string ($hodnota)."'", $dotaz); } $this->vysledek = sqlite_query($this->spojeni, $dotaz); if(!$this->vysledek){ return FALSE; } return $this; } public function VratPole(){ return sqlite_fetch_array($this->vysledek); } } ?>
Dotazy na databázi Když máme rozhraní připravené, můžeme zadávat dotazy a výsledky vypisovat:
http://php.interval.cz/clanky/vyuziti-oop-v-praxi/
12.10.2008
Využití OOP v praxi -- Knihovna PHP -- Interval.cz
Page 5 of 6
$d = $ins->dotaz($dotaz)->Vlozeni($jm)->Pole(); echo '
'; for($i = 0; $i < count($d);$i++){ echo ''.$d[$i][id].' | '.$d[$i][jmeno].' | '.$d[$i][prijmeni].' |
'; } echo '
'; ?> Proč mají dotazy syntaxi SELECT * FROM tab WHERE jmeno = :1? Takový dotaz stačí použít jednou a pak už jen měníme argumenty, tedy další dotazy by například mohly vypadat takto: dotaz($dotaz)->Vlozeni('Nějaké jméno')->Pole(); ?> Jelikož metoda Vlozeni() umožňuje přeměnu libovolného počtu předaných argumentů, můžeme používat dotazy typu: dotaz($dotaz)->Vlozeni('Nějaké jméno','Nějaké prijmeni')->Pole(); ?> Díky takovému zápisu rovněž můžeme dotazy přizpůsobovat libovolnému typu databáze. Pro další studium a testování si stáhněte podklady k příkladu. Pozn. red.: Zdůrazňujeme, že tento text se týká PHP 5. zpracoval: Mrozek, Jakub (5. 9. 2007)
Komentáře k článku Od: Drath IP: 89.235.29.155 Datum: 2007-12-27 10:32:16 Díky za článek, ale moc ho nechápu. S OOP jsem začal teprve nedávno a např. abstraktním třídám vůbec nerozumím. Nevíte o nějaké publikaci, kde by bylo OOP do podrobna, avšak pro laika srozumitelně, vše vysvětleno? Na jednu jsem narazil, ale příklady v ní byly v jazyku java(script) a C, raději bych příklady přímo v PHP. Od: Marek IP: 91.127.115.13 Datum: 2008-02-01 14:05:55 no co sa tyka abstraktnych tried zjednodusene povedane Ti sluzia na to aby si vedel nastavit nejake vlastnosti, vars a pod pre vsetky triedy ktore dedia abstraktnu, z abstraktnej triedy nemozes vytvorit instanciu. Ale to je len velmi jednoducho povedane
http://php.interval.cz/clanky/vyuziti-oop-v-praxi/
12.10.2008
Využití OOP v praxi -- Knihovna PHP -- Interval.cz
Page 6 of 6
Od: Gisat IP: 82.100.14.181 Datum: 2008-08-28 23:57:28 docela dobře je popsaná pokročilá práce v knížce pokročilé programování v php5 Od: Mastodont IP: 85.132.169.34 Datum: 2008-09-11 22:00:30 $d = $ins->dotaz($dotaz)->Vlozeni($jm)-&g… Hm, a co když Vlozeni vrátí false, jak se s tím kód vypořádá? Od: Mastodont IP: 85.132.169.34 Datum: 2008-09-11 22:09:03 No a pak bych se třeba ještě zeptal, proč tento kód: foreach ($argumenty as $index => $hodnota){ $this->argumenty[$index + 1] = $hodnota; } když s $argumenty se pracuje jen v rámci metody Vlozeni, takže je není nutné ukládat do vlastnosti.
Přidejte svůj názor! . ISSN 1212-8651 . © Zoner software, s.r.o., všechna práva vyhrazena, tento server dodržuje právní předpisy o ochraně osobních údajů.
http://php.interval.cz/clanky/vyuziti-oop-v-praxi/
12.10.2008