PHP a SQL - EZ_SQL

EZ_SQL je praktická knihovna pro zpřístupnění SQL databáze z PHP.

7.2.2005 15:00 | MaReK Olšavský | přečteno 18126×

Patrně nejlepší seriál, který vycházel na tomto serveru je PHP od autora Petra Zajíce, na který si dovolím nepřímo navázat několika články o zajímavých PHP klihovnách a projektech. První z nich je EZ_Sql, která slouží ke zpřístupnění takřka libovolné běžněji používané SQL databáze, z nichž namátkou jmenujme MySQL, PostgreSQL a Firebirda. Zpřístupnění je řešeno do té míry, že nemusíte při psaní scriptu/projektu řešit to že se fce pro jednotlivé db servery liší názvem a můžete snadno převést projekt na jinou databázi. Pochopitelně neudělá Vám z MySQL PostgreSQL, protože rozdílů na úrovni databáze je více, než malé množství.

Jak jsem předestřel v předchozím odstavci, při použití základních dotazů a nedefinování db tabulek z PHP scriptu lze docílit takřka 100% přenositelnosti projektu na aplikační server, který bude napojen na jinou databázi, než kterou máte doma na svém vývojovém stroji. Já toho využívám dost často, protože vývoj jedu na PostgreSQL, ale většinou je na hostingu k dispozici "pouze" MySQL. Omezením je nepřenositelnost specifik jednotlivých serverů, na které narážím téměř jen při vytváření tabulek a nemožnosti tvořit a následně přenášet například uložené procedury.

Knihovna EZ_Sql je volně ke stažení, použití a další distribuci v souladu s LGPL licencí, což znamená, že Váš projekt již nemusí být dále šířen jako opensource, s výjimkou této knihovny. Stáhnout jí můžete zde, anglicky psaný manuál je součástí zip souboru, který stáhnete nebo jej máte dostupný na www stánkách. Rozhodně tímto článkem nechci tento manuál suplovat, ale hodlám ukázat základní funkcionalitu knihovny. V době kdy píši tento článek je ke stažení verze z řady 1, konkrétně 1.26, přižemž jsem dostal email, že se připravuje verze 2, kde asi největší změnou bude jiné načítání scriptů před použitím a očekávám přístup do MySQL i tak, jak jsou nové funkce v PHP5, další změnou bude lepší podpora SQLite, která je v PHP nově pořádně podpořena a která má dle mého poměrně velikou budoucnost. Bohužel z toho, co je momentálně k dispozici nelze moc vyčíst, protože není k dispozici nějaké readme, kde jsou popsány změny.

První krok

Dobře, měl by být krok třetí, protože za první by se dalo považovat stažení od tvůrce a za druhý rozbalení do adresáře webu. Dalším krokem by mohlo být základní nastavení, ale není nejvýše nutné. Dalším krokem dle původní dokumentace by mělo být nastavení konstant z počátku ez_sql.php příslušné k patřičnému serveru, který potřebujete používat. Jsou to po řadě EZSQL_DB_USER (uživatelské jméno), EZSQL_DB_PASSWORD (heslo uživatele), EZSQL_DB_NAME (jméno databáze) a nakonec EZSQL_DB_HOST (připojení k SQL serveru). Potom stačí do kódu vložit require_once 'ez_sql.php' z patřičného adresáře a jeden z posledních řádků, které jsou v kódu ez_sql zajistí vytvoření instance třídy a její připojení k databázi s parametry podle výše definovaných konstant.

Já osobně volím trochu jiný postup. Tyto řádky mám zakomentovány a veškeré definice konstant a natažení potřebných knihoven (nebo chcete-li jinak scriptů) řeším dvojicí init.php a config.php. Napřed requirnu init.php, který první co obsahuje je require_once 'configure.php', kromě toho init obsahuje natažení všech potřebných knihoven a vytvoření instancí tříd, které běžně používám, jako je právě zde popisované ez_sql a Smarty. Soubor configure.php obsahuje definice všech konstant, které používám. Vím, že to asi není nejrychlejší řešení pro server, ale milisekundy už většinou nic neřeší. Naopak, protože se webovým programováním zabývám více, šetří mi to práci a do nového projektu jen překopíruji adresáře lib, smarty, plugins a init. Adresář (nebo název databáze), ze kterého používám si také dávám do konstanty. V knihovně init.php vytvořím i instanci knihovny pomocí db(DBUSER, DBPWD, DBNAME, DBSERVER), takže v důsledku vypadá začátek init.php nějak takto:

//requires
require_once './../init/configure.php';
require_once './../lib/'.DBTYPE.'/ez_sql.php';
require_once './../Smarty/smarty.php';

//inits
$db=new db(DBUSER, DBPASSWORD, DBNAME, DBSERVER);
$page=new Smarty();
...

Další užitečnou radou, kterou mě v mých PHP začátcích kamarád počastoval je používat proměnnou DBPREFIX (pochopitelně definovanou v config.php), přes kterou si zadávám části názvů tabulek. Toto oceňuji zejména v testovacím provozu, kdy několik projektů stílí jednu databázi, ale potřebují stejně pojmenované tabulky (například pro projekt fotovideo budu mít předponu "fo_" a pro kucharske potreby "ku_") a když testovací projekt skončí a na server dám tabulky bez těchto předpon, jednoduše v config.php tuto konstantu nastavím na prásdná řetězec.

Práce s daty

Knihovnu máme nataženu, vytvořenu její instanci a můžeme (se) vrhnout na práci s daty na SQL serveru. Vím, že Petr Zajíc do svého seriálo objektově orientované programování zahrnul relativně zběžně, ale není to chyba, protože většina začínajících má s objekty docela potíže. Knihovna Ez_sql je objektová, což se vám může nelíbit, můžete s tím nesouhlasit, ale to je asi tak vše, co s tím můžete dělat. No ještě ji můžete nepoužívat, napsat si něco podobného sami a bez objektů, ale jaká bude Vaše efektivita, když budete tvořit již hotové tedy opravdu nevím.

Výhodou při práci s touto knihovnou je to, že už nebudete nuceni psát neustále sekvence, kdy zadáte databázi příkaz pro manipulaci s daty a potom "pěšky" testujete, zda-li proběhl v pořádku a pakliže ne, řešíte nějaké ošetření chyby. Toto z velké části odpadá.

"Dolování" dat z databáze

Získávání dat z databáze je určitě nejkomplexněji řešená část tohoto projektu. Pomocí třech funkcí můžete získat jednu proměnnou, jeden řádek, nebo pole řádků z databáze.

Začneme získáním jedné proměnné z databáze. Dejme tomu, že potřebujete získat počet řádek v tabulce zákazníci, u nichž je nastaven příznak restricted='no', to znamená, že nemají zakázán přístup na náš webshop. Při použití klasického postupu (připojen už jsem) to vypadalo třeba takto:

$result=pg_query($pgconnection,'SELECT COUNT(*) AS cnt FROM '.
  DBPREFIX.'consumers WHERE restricted=\'no\'');
if(!$result){
  //osetreni chyby
} else {
  $record=pg_fetch_array($result, NULL, PGSQL_ASSOC);
};
...
...

a někde v programu později zobrazíte pomocí $record['cnt']. Omlouvám se všem, kteří preferují MySQL, ale vše je skoro stejné až na to, že pg nahradíte za mysql, nebude te mít za proměnnou s výsledkem, který odchytáváme do pole, konstanty a budete mít extra funkce pro odchycení do asociativního a indexovaného pole. Já osobně preferuji spíš používání asociativních polí, než indexovaných, přeci jen názvy sloupců v tabulce si pamatuji, ale abych si pamatoval jejich pořadí v dotazu považuji za kontraproduktivní.

Při použití Ez_sql si vystačíte s jediným příkazem - $cnt=$db->get_var('SELECT COUNT(*) FROM '.DBPREFIX.'consumers WHERE restricted=\'no\'');, máte počet přímo v proměnné a nemusíte řešit přístup přes pole.

Získání jedné proměnné budeme potřebovat rozhodně méně často, než získání jednoho, či několika řádků z databáze. Zatímco pro výběr dat klasickým způsobem používáme stále stejné funkce ve stálém pořadí, zde nám přibyde napřed funkce pro výběr jednoho řádku, která se použije příkazem: $db->get_row(dotaz[,OBJECT/ARRAY_A/ARRAY_N[,offset]]). Nejprve si vysvětlíme konstanty, které jsem napsal za slovo dotaz:

Jak jsem psal o něco výše, preferuji použití asociativního pole. Pokud by podmínkám dotazu odpovídalo více záznamů, návratovou hodnotou funkce bude první z nich.

Pojďme si ukázat alespoň dva příklady, potom bude vše jasné.

$user=$db->get_row('SELECT * FROM '.DBPREFIX.'users WHERE login=\''.$_POST['login'].'\' AND pwdhash=\''.sha1($_POST['login'].$_POST['pwd']).'\'',OBJECT);

Vám vrátí všechna data uživatele, jestli-že jste napsali správné jméno a hesla. Pro tabulku s autorizacemi je rozumný výchozí předpoklad, že máte kombinaci login a pwdhash jedinečnou. Přístup k jednotlivým položkám pak máte přes objekt $user, takže hodnoty id, email a další získáte pomocí $user->id, $user->email.

Pro asociativní pole použiji:

$user=$db->get_row('SELECT * FROM '.DBPREFIX.'users WHERE login=\''.$_POST['login'].'\' AND pwdhash=\''.sha1($_POST['login'].$_POST['pwd']).'\'',ARRAY_A);

a data potom budete mít v poli, ze kterého je získáte pomocí $user['id'], $user['email'], ... Z hlediska toho, co si programátor musí při vývoji pamatovat považuji tyto dva přístupy za rovnocenné.

Pro získání pole záznamů je vytvořena další funkce $db->get_results(dotaz[,OBJECT/ARRAY_A/ARRAY_N]), kde význam konstant je stejný jako v předchozím případě, jen nemůžete nastavit offset.

$articles=$db->get_results('SELECT id, title, lastedit, visible FROM '.DBPREFIX.'articles WHERE editor=\''.$_POST['userid'].'\'',ARRAY_A);

Vám do asociativního pole vrátí vybrané údaje o článcích příslušných k uživateli, kterého jste vybrali někde ve formuláři.

Použil jsem asociativní pole, které můžete "projet" pomocí cyklu foreach, takže bychom data mohli zobrazit pomocí:

$articles=$db->get_results('SELECT id, title, lastedit FROM '.
  DBPREFIX.'articles WHERE editor=\''.$_POST['userid'].'\'',ARRAY_A);
foreach($articles as $oneart)
  echo $oneart['id'].' - '.$oneart['title'].' -> '.$oneart['lastedit'];

Pokud bychom použili jako výstup OBJECT, bude Vám vráceno pole objektů, takže k "projetí" celého pole můžete použít zase cyklu foreach, jen jednotlivé položky budete zobrazovat pomocí $oneart->id, ...

Upozornění: Defaultně je výstup nastaven jako OBJECT, takže chcete-li něco jiného, musíte to ez_sql sdělit.

Závěrem

V tomto díle jsem Vám provedl základní představení Ez_sql, včetně získávání dat z databázového serveru. Protože věřím, že se Vám tato knihovnička zalíbí a budete jí používat, přečtete si i další díl, kde si řekneme něco o obecných dotazech, podíváme se jak na chyby a případně co s nimi...

Online verze článku: http://www.linuxsoft.cz/article.php?id_article=664