A PHP programozási nyelv

Szabványos könyvtárak

XML Támogatás

SimpleXML

Ez a modul csak a PHP 5 verziótól él. A nyelvben a kiterjesztés alapértelmezés szerint engedélyezett. A kiterjesztés egy alapvetően egyszerű és könnyen használható eszköz, hogy az XML dokumentumokat objektumokká konvertáljuk, és mint objektumokon tudjunk műveleteket végezni rajtuk.

Az XML dokumentumokat többféle forrásból tudjuk feldolgozni: string, file.

$xml = simplexml_load_string("string");
$xml = simplexml_load_file("file_name");
A dokumentum elemeit név szerint érhetjük el:
$xml->element1->element1_2;
Ha esetleg több azonos nevű elem létezik, akkor ezeket iterációval tudjuk bejárni:
foreach ($xml->movie as $movie){
// do something;
}
A kiterjesztés beépített XPath támogatást tartalmaz.

Természetesen az objektumstruktúra nem csak olvasható írható is. Így lehetőség nyílik XML dokumentumok módosítására is.

DOM Támogatás

DOM – Document Object Modell. Egy szabvány az XML dokumentstruktúrák kezelésére. A PHP5 nyelv része a DOM teljes és szabványos támogatása, ezzel együtt szeretnék lecserélni a PHP4 ben élő DOM XML kiterjesztést.

SOAP Támogatás

SOAP – Simple Object Access Protocol. A webszolgáltatások egyik meghatározó protokollja, mely XML formátumban szállít adatokat elosztott alkalmazások között http alapokon. Meghatározza az XML formáját, a feldolgozás módját. Az adatokat (akár tömböket és objektumokat is) átalakítja szállítható XML formátumra, majd a másik oldalon az XML-ben szállított szabályok alapján újra összerakja az adatot.

A kiterjesztés nagyrészt lefedi a SOAP1.1, SOAP1.2 és a WSDL1.1 specifikációkat.

MySQLi Kiterjesztés

A MySQL kiterjesztés az évek során túl bonyolult és átláthatatlan lett, valamint igencsak lemaradt a MySQL adatbázisszerverek képességeinek kiaknázásában. Ezért a PHP5-ben bemutatkozik a MySQLi modul, egy teljesen újraírt felület az adatbázisszerverhez, mely tartalmaz procedurális és objektumorientált interfészt is, ugyanakkor egy-két funkciót nem találunk a régihez képest, vagy azért mert biztonsági aggályokat vet fel a használatuk, vagy mert hatékonysági szempontból teljesen hasztalannak bizonyulnak. Nem teljesen kompatibilis a régivel, de igencsak ajánlott ezt az új modult használni, mellesleg alapértelmezésben a nyelv része.

Az új kiterjesztés végre elérhetővé teszi az MySQL C könyvtár által kínált funkciókat. Többek között kiegészítő támogatást nyújt nyomkövetéshez, hibakereséshez, terheléselosztáshoz valamint többszörözéshez.

A procedurális interfész:

$link = MySQLi_connect( 'host', 'user',  'password','world');

if (!$link){
printf("Can't connect to MySQL Server. Errorcode: %s\n", MySQLi_connect_error());
exit;
}
/* Send a query to the server */
if ($result = MySQLi_query($link, 'SELECT Name, Population FROM City ORDER BY Population DESC LIMIT 5')){
print("Very large cities are:\n");
/* Fetch the results of the query */
while( $row = MySQLi_fetch_assoc($result) ){
printf("%s (%s)\n", $row['Name'], $row['Population']);
}
MySQLi_free_result($result);
}
MySQLi_close($link);
Az objektumorientált interfész:
/* Connect to a MySQL server */
$MySQLi = new MySQLi('localhost', 'user', 'password', 'world');
if (MySQLi_connect_errno()){
printf("Can't connect to MySQL Server. Errorcode: %s\n", MySQLi_connect_error());
exit;
}
/* Send a query to the server */
if ($result = $MySQLi->query('SELECT Name, Population FROM City ORDER BY Population DESC LIMIT 5')){
print("Very large cities are:\n");
/* Fetch the results of the query */
while( $row = $result->fetch_assoc() ){
printf("%s (%s)\n", $row['Name'], $row['Population']);
}
/* Destroy the result set and free the memory used for it */
$result->close();
}
/* Close the connection */
$MySQLi->close();
Az új modul lehetőséget ad úgynevezett előkészített utasítások végrehajtására is. Ezeknek két típusa van.

Egyik a kötött paraméterekkel előkészített utasítások. Ezek lehetőséget adjanak egy SQL kérés sablon létrehozására, amit az adatbázisszerver tárol. Majd ha szükség lesz egy ilyen kérésre csak a sablont töltjük fel aktuális változókkal, majd az adatbázis a feltöltött sablont hajtja végre. Ez elsősorban a kérések feldolgozási idejét szűkíti le, mivel az adatbázisszerver reakcióidejében elég jelentős szerepet játszik a kérés ellenőrzése és szintaktikai elemzése. Erre csak egyszer van szükség, a sablon megadásánál. Nyilván ez sok egymáshoz hasonló kérésnél hasznos segédeszköz.

$stmt = $MySQLi->prepare("INSERT INTO CountryLanguage VALUES (?, ?, ?, ?)");
$stmt->bind_param('sssd', $code, $language, $official, $percent);
$code = 'DEU';
$language = 'Bavarian';
$official = "F";
$percent = 11.2; 
$stmt->execute();
$stmt->close();
A bind_param() metódus első paramétere egy sztring ami az előkészített utasításban álló kötött paraméterek típusát határozza meg. Ezek jelentése:
i mindenféle szám típus
d double vagy float típus
b Blob
s minden más típus

Majd meghívva az execute() metódust, az előzőleg megadott paraméterek értékeivel kérést indít.

A másik előkészített utasítás típus a kötött eredményekkel előkészített utasítás. Ez lehetőséget teremt, hogy a PHP változóit egy MySQL lekérdezés eredményének soraihoz kössük.

if ($stmt = $MySQLi->prepare("SELECT Code, Name FROM Country ORDER BY Name LIMIT 5")){
$stmt->execute();
$stmt->bind_result($col1, $col2);
while ($stmt->fetch()){
printf("%s %s\n", $col1, $col2);
}
$stmt->close();
}

PDO

A PDO (PHP Data Objects) a MySQLi-vel együtt a PHP5-ben került be a PHP-s világba. Ugyan úgy használható MySQL adatbázishoz való kapcsolódáshoz, ugyanakkor a MySQLi-vel ellentétben a PDO még számos egyéb driverrel is rendelkezik. Ezek közül a legismertebbek a PostgreSQL, Oracle, MS SQL, SQLite.
Itt már nem tartották meg a procedurális függvényhívási lehetőségeket, kizárólag az OOP-s formában használható, cserébe az ezzel készített PHP-s rendszerek mögött könnyedén cserélhető az adatbázis rendszer.

A rugalmasságnak viszont ára van, egyes mérések szerint ha nem használunk prepared statementeket, akkor 2.5%, ha használunk akkor pedig 6.7%-os sebesség veszteséggel számolhatunk a MySQLi-vel szemben.
Bár ez a szám soknak tűnhet, bizonyos esetekben ennél többet lehet nyerni magán az adatbáziskezelő rendszeren.

PDO esetén egy kapcsolódás az adatbázishoz a következőképpen adható meg:

$dbh = new PDO('mysql:host=localhost;dbname=test', $user, $pass);

Az első paraméter az úgynevezett "connection string", mint látható itt a "mysql" rész jelzi, hogy épp egy MySQL adatbázishoz próbálunk kapcsolódni, benne van még a hosztnév és az adatbázis név.
Kicsit részletesebben erről az alábbi wikipedia cikkben található információ: http://en.wikipedia.org/wiki/Connection_string

A másik két paraméter a kapcsolódáshoz használt felhasználó név és a jelszó.

A különböző hibák PDO esetén egy PDOException-t váltanak ki, ezeket el tudjuk kapni.

try {
$dbh = new PDO('mysql:host=localhost;dbname=test', $user, $pass);
foreach($dbh->query('SELECT * from FOO') as $row) {
print_r($row);
}
$dbh = null;
} catch (PDOException $e) {
print "Error!: " . $e->getMessage();
die();
}

A kapcsolódáskor fellépő esetleges hibát mindenképpen érdemes elkapni, ugyanis amennyiben be van kapcsolva a szerveren a hibák kiírása, akkor sikertelenség esetén az összes adatbázid kapcsolódási információ, beleérte a felhasználó név és jelszó párost is, kiírásra kerül!

A különböző adatbázis műveletekhez a MySQLi-hez hasonlóan célszerű a prepared statementeket használni. Itt a paraméter kötést kétféleképpen is megadhatjuk, vagy nevesítve, vagy név nélkül, az üres helyekre kérdőjeleket téve.

Nevesített megoldás:


$stmt = $dbh->prepare("INSERT INTO REGISTRY (name, value) VALUES (:name, :value)");
$stmt->bindParam(':name', $name);
$stmt->bindParam(':value', $value);
$stmt->execute();

Mint látható, előbb elkezdünk egy lekérdezést előkészíteni, majd a :name és :value párokat cseréljük változókra és végül futtatjuk a lekérdezést.

Név nélküli megoldás:


$stmt = $dbh->prepare("INSERT INTO REGISTRY (name, value) VALUES (?, ?)");
$stmt->bindParam(1, $name);
$stmt->bindParam(2, $value);
$stmt->execute();

Ennél a megoldásnál szintén elkezdünk egy kérést készíteni, majd megadjuk benne a kötendő paramétereket. Ezekhez a paraméterekhez a bindParam utasítással kötjük hozzá a változókat, majd futtatjuk a lekérdezést.


Magukat a paramétereket a bindParam helyett akár az execute() függvénynek is paraméterül adhattuk volna, például a következő módon:

$stmt = $dbh->prepare("INSERT INTO REGISTRY (name, value) VALUES (?, ?)");
$stmt->execute(array("param1", "param2"));

Ez természetesen kulcs-érték párok formájában is működik, a nevesített paraméterekkel.


Egy lekérdezés eredményét szintén a készített statement-ből lehet visszanyerni a fetchAll() függvénnyel tömbös formában, vagy a fetch() hívogatásával soronként egy ciklusban.

$stmt = $dbh->prepare("SELECT * FROM REGISTRY where name = ?");
if ($stmt->execute(array($_GET['name']))) {
while ($row = $stmt->fetch()) {
print_r($row);
}
}

Amennyiben csak egy egyszerű lekérdezést szeretnénk végrehajtani, akkor az exec() parancsot is használhatjuk közvetlenül a PDO objektumon.

$count = $dbh->exec("DELETE FROM fruit WHERE colour = 'red'");

Van lehetőség tranzakciók használatára is, de fontos odafigyelni, hogy ezeknek a lehetőségét csak driver szinten ellenőrzi a rendszer és tér vissza igaz vagy hamis értékkel. Azaz, ha egy MyISAM-os táblán próbálunk tranzakciókat végrehajtani, akkor nem fog hibát jelezni, de mégsem fogunk tudni rollback-e visszapörgetni semmit!

try {
$dbh->beginTransaction();
$dbh->exec("insert into staff (id, first, last) values (23, 'Joe', 'Bloggs')");
$dbh->exec("insert into salarychange (id, amount, changedate) values (23, 50000, NOW())");
$dbh->commit();

} catch (Exception $e) {
$dbh->rollBack();
echo "Failed: " . $e->getMessage();
}

Nagyméretű (>4kb) tárolt adatok, például képek esetén hasznos lehet, ha azokhoz egy stream formájában férünk hozzá és nem közvetlenül változókba pakoljuk. A PDO erre is nyújt egy lehetőséget a visszatérési értékek egy speciális kötésével.

$db = new PDO('odbc:SAMPLE', 'db2inst1', 'ibmdb2');
$stmt = $db->prepare("select contenttype, imagedata from images where id=?");
$stmt->execute(array($_GET['id']));
$stmt->bindColumn(1, $type, PDO::PARAM_STR, 256);
$stmt->bindColumn(2, $lob, PDO::PARAM_LOB);
$stmt->fetch(PDO::FETCH_BOUND);

header("Content-Type: $type");
fpassthru($lob);

A fenti példakód bemutatja, hogy miként lehet a visszatérési értékeket kötni változókhoz.
A $lob változó fogja tárolni a stram formájában érkező adatokat, majd itt az fpassthru segítségével tovább is adja a böngészőnek.

Bár a lehetőség maga adaott, nem szokás ilyen formában nagyobb mennyiségű adatot az adatbázis kezelőbe tölteni. Célszerűbb a feltöltés után a szervern található elérhetőségét rögzíteni csak.