SQL réteg

A muPortal egyik alapvető rétege az SQL réteg. Az SQL rétegek feladata, hogy az adatbázis és a rendszer közötti kommunkációt megvalósítsa. Ennek előnye, hogy az SQL réteg lecserélésével (vagy újabb hozzáadásával) a rendszer más DBMS támogatására is képes lesz.

A muPortal jelenleg csak a MySQL-t támogatja, de az adatbázis-struktúra konvertálásával és pl. egy PostgreSQL réteg hozzáadásával akár PostgreSQL-ből is meg lehetne hajtani a muPortalt (létezett PostgreSQL-s kísérleti verzió).

Másik előnye, hogy nem kell mindent külön lekezelni, sokat segít például a hibakezelésben.

Tartalom

  1. sql_db felépítése
  2. Az osztály által definiált konstansok
  3. sql_fetch_array() konstansai
  4. Csatlakozáshoz szükséges adatok
  5. Az SQL réteg elérése
  6. Az osztály változói
  7. Az osztály függvényei
  8. Példák az SQL réteg használatára

sql_db felépítése

Az osztály által definiált konstansok

Konstans Megjegyzés
SQL Az SQL réteg mögött álló adatbáziskezelő rendszer típusa. (Jelen esetben MySQL)

sql_fetch_array() konstansai

Konstans Megjegyzés
SQL_ASSOC A tömb kulcsai az eredményben szereplő mezőnevek. (Lásd pl. MYSQL_ASSOC)
SQL_BOTH Az eredményt mezőnevek valamint az eredmény oszlopszáma alapján érheted el. (Lásd pl. MYSQL_BOTH)
SQL_NUM Az eredmény oszlopai egy számmal indexelt tömb formájában állnak rendelkezésre. Az első oszlop indexe 0. (Lásd pl. MYSQL_NUM)

Csatlakozáshoz szükséges adatok

A csatlakozáshoz szükséges adatokat a config.php tárolja. A fájl a következő konstansokat definiálja:

Konstans Megjegyzés
DBPREFIX prefixum a tábla neve előtt. (Ha például több programot kell ugyanabból az adatbázisból meghajtani, elkerülhető, hogy összeakadjanak egymással az azonos nevű táblák.)
FONTOS! A DBPREFIX konstansot mindig kézzel kell beírni a tábla neve elé!
SQLHANDLER definiálja az SQL réteg típusát. (pl: mysql, postgresql, mssql, sqlite...)

Az adatbázis-beállításokat a $cfg nevű tömb tárolja. A tömb a következő adatokat tárolja:

index Megjegyzés
db_server Az adatbázis-szerver IP címe vagy host neve.
db_user Az adatbázis eléréséhez szükséges felhasználónév...
db_pasw ...és jelszó.
db_name Az adatbázis neve, melyet a muPortal használ.
db_persistency perzisztens kapcsolattal kapcsolódjon-e a DBMS-hez a rendszer. (Perzisztens kapcsolatról részletesebben: http://hu2.php.net/manual/hu/features.persistent-connections.php)

Biztonsági okokból ez a tömb az adatbázis-kapcsolat létrehozása után már nem elérhető!

Az SQL réteg elérése

Az SQL réteget a rendszer automatikusan létrehozza, bárhonnan használható a globális $db objektummal. Az objektum létrehozása a common.php elején történik.

Példa:
global $db;

Az osztály változói

private connect

Ez a resource típusú változó tartalmazza a kapcsolatot a DBMS-sel. A konstructor hozza létre.

protected res

Az sql_query() által visszaadott eredményt tartalmazza ez a változó.

Megjegyzés: Az újabb kérés felülírja a régi kérés eredményét (ha van), ezért ha erre szükségünk van, azt menteni kell!

protected querys

Eddigi lekérdezések száma.

protected debug

A végrehajtott lekérdezéseket tárolja a rendszer. Csak akkor van jelentősége, ha a hibakereső mód be van kapcsolva.

Ha nem a config.php-ből a DEBUG konstanssal kapcsoljuk be a hibakereső módot, hanem az adminisztrációs felületről, akkor az első lekérdezés (rendszerint a beállítások lekérdezése) nem kerül naplózásra!

Az osztály függvényei

public sql_db( array dbcfg )

Létrehozza az adatbázis-kapcsolatot, és definiálja a megfelelelő konstansokat. Ha nem adjuk meg a $dbcfg tömböt (a $cfg tömb a config.php-ben), akkor kritikus hibával leállítja az alkalmazás futását.

Ha nem tud csatlakozni, a _connect_error() függvényt hívja meg

public sql_close()

Lezárja az adatbázis-kapcsolatot. Perzisztens kapcsolatnál nincs jelentősége (lásd PHP Manual ide vonatkozó részét.)

public sql_query( string query )

Végrehajt egy SQL kérést és az eredményét a res változóban letárolja. Ha a kérés során hiba történt, meghívja az _query_error() függvényt.

public sql_num_rows()

A SELECT esetén a visszaadott sorok számát adja vissza.

public sql_affected_rows()

UPDATE esetén a frissített sorok számát adja vissza.

public sql_insert_id()

Az előző INSERT műveletben szereplő AUTO_INCREMENT tulajdonságú mező számára generált értéket adja meg, ha van ilyen mező

public sql_fetch_array( [resource res], int type = SQL_ASSOC )

Feldolgoz és visszaad egy sort a lekérdezés eredményéből. Ha nem adunk meg res -hez semmit, az objektum belső eredményváltozóját fogja használni.

Alapbeállítás szerint csak asszociatív tömböt ad vissza, de a type paraméterrel negadható, hogy milyen módon adja vissza a sort. (Lásd sql_fetch_array() konstansai táblázat.)

public sql_escape( string msg )

Elvégez egy escapelést a megadott sztringen.

private sql_query_debug( string query )

Ha be van kapcsolva a hibakereső mód, ezzel a függvénnyel menti a sql_query() függvény az SQL kérést. Lásd még debug változó.

private _connect_error()

Hibakezelő csatlakozási hibák lekezelésére. Konstruktor hívja meg.

private _dbselect_error()

Hibakezelő adatbázis-megnyitási hibák lekezelésére. Konstruktor hívja meg.

private _query_error( string query )

SQL hiba lekezelésére szolgáló függvény. Hibakereső módban kiírja az SQL kérést, és a szerver által visszaadott hibakódot és ahhoz tartozó üzenetet. sql_query() hívja meg.

Példák az SQL réteg használatára

Egyszerű lekérdezés

global $db, $template;

// Az utóbbi egy héten regisztáltak lekérdezése
$db->sql_query('SELECT id, name FROM '.DBPREFIX.'users
	LIMIT regdate > '.(time() - 86400*7).'
	ORDER BY name ASC');
	
// a $row változóba visszakapjuk soronként az eredményt,
// majd ezt a mintarendszeren keresztül kiíratjuk
while ($row = $db->sql_fetch_array()) {
	$template->UseTpl('userlist', array(
		'ID'	=> $row['id'],
		'NAME'	=> $row['name'],
	));
}

Példa az eredménytömb mentésére

A következő példában megszámoljuk, hogy egy kategória hány elemet tartalmaz. Természetesen a példát meg lehetne oldani GROUP BY záradékkal (sőt, úgy kell!), csak a példa kedvéért használtam ezt a módszert.

global $db;
	
// Lekérdezzük a kategória-id-ket a képzeletbeli táblánkból
$db->sql_query('SELECT cid, csoportnev FROM '.DBPREFIX.'kategoriak');

// Mentjük az eredményt, hiszen a cikluson belüli kérések fellülírnák.
$result = $db->res;

$csoportok = array();

// Itt megadjuk, hogy nem az osztály belső változójából dolgozzon a függvény
while ($row = $db->sql_fetch_array($result)) {
	
	// Itt a belső lekérdezés, mely fellülírja a $db->res -t
	$db->sql_query('SELECT COUNT(*) AS count FROM '.DBPREFIX.'elemek
		WHERE cid='.$row['cid']);
	
	// Itt nem kell megadni eredménytömbböt, használhatja a legutolsót
	$row_belso = $db->sql_fetch_array();
	
	$csoportok[$row['csoportnev']] = $row_belso['count'];
}	

// Végeredmény kiíratása
print_r($csoportok);

Példa az sql_num_rows() függvényre

global $db;
	
$db->sql_query('SELECT elet, univerzum, mindenseg FROM '.DBPREFIX.'valahonnan');

// 42 sort kaptunk vissza
echo $db->sql_num_rows().' sort kaptunk vissza';

Példa az sql_insert_id() és az sql_affected_rows()

global $db;
	
/* A példatábla szerkezete

CREATE TABLE '.DBPREFIX.'nevek (
	id INT(10) NOT NULL AUTO_INCREMENT,
	nev VARCHAR(32),
	nem VARCHAR(5),
	PRIMARY KEY (id)
)*/

// Beszúrunk egy sort a táblázatba
$db->sql_query('INSERT INTO '.DBPREFIX.'nevek (nev, nem) VALUES 
	(\'Anikó\', \'férfi\')');

// Beszúrunk mégegyet
$db->sql_query('INSERT INTO '.DBPREFIX.'nevek (nev, nem) VALUES 
	(\'Sándor\', \'férfi\')');

// Visszaadja az id mező értékét (AUTO_INCREMENT tulajdonság miatt)
$sorszam = $db->sql_insert_id();

// Átírjuk előzőleg beszúrt sorban a nevet
$db->sql_query('UPDATE '.DBPREFIX.'nevek SET nev = \'Nikolett\'
	WHERE id = '.$sorszam);
	
// Kiírja, hogy 1, mert csak egy sornak volt $sorszam azonosítója
echo $db->sql_affected_rows();

// Frissítjük nemet, ahol Nikolett van.
$db->sql_query('UPDATE '.DBPREFIX.'nevek SET nem = \'nő\'');
	
// kiírja, hogy 2
echo $db->sql_affected_rows();