PHP pro pokročilé – znovu třídy a objekty
V tomto článku o třídách a objektech si ukážeme další zajímavé možnosti při práci s OOP v PHP. Budeme se zabývat využitím takzvané serializace a magických funkcí __sleep() a __wakeup() – vytvoříme instanci třídy, uložíme ji do souboru a nakonec celý objekt předáme v session.
Serializace a unserializace
Vše zajišťují funkce serialize()
a unserialize()
, které převedou do takzvaného byte řetězce proměnné objektu. Proces tohoto „převodu“ se nazývá serializace a opačný postup unserializace. Na vstupu funkce serialize()
je objekt a na výstupu již zmiňovaný byte řetězec, u funkce unserialize()
je tomu naopak.
Pro další experimentování si nadefinujeme pokusnou třídu do souboru „trida.php“ se kterou budeme dále pracovat:
<?
/*
Soubor trida.php ve kterém je definice pokusné třídy
*/
class clsTrida {
//pomocí konstruktoru nastavíme hodnoty vlastností
function clsTrida($vl1, $vl2) {
$this->vlastnost1=$vl1;
$this->vlastnost1=$vl2;
}
//funkce vypis() vypíše hodnoty obou vlastností
function vypis() {
echo „1. vlastnost: „.$this->vlastnost1.“<br />“;
echo „2. vlastnost: „.$this->vlastnost2.“<br />“;
}
}
?>
Nejprve si ukážeme postup uložení objektu do souboru:
<?
/*
Soubor „a.php“
V prvním souboru náš objekt zeserializujeme a uložíme ho do souboru „data“
*/
//naincludujeme soubor s pokusnou třídou
include (‚trida.php‘);
//vytvoříme instanci pokusné třídy a nastavíme vlastností, které se zeserializují
$objekt = new clsTrida („Vlastnost 1“, „Vlastnost 2“);
//zde vytvoříme byte řetězec
$bytestring=serialize($objekt);
//otevřeme soubor a byte řetězec do něj uložíme
$f = fopen(„data“, „w“); //vytvoření a otevření souboru pro zápis
fputs($f, $bytestring); //uložení bytestringu do souboru
fclose($f); //zavření souboru
?>
V souboru s unserializací se již nevytváří žádná instance, protože unserializovaný objekt je schopen sám poznat svoji třídu. Ta ale ve skriptu definována být musí.
<?
/*
Soubor „b.php“
V druhém souboru otevřeme soubor „data“, kde je serializovaný objekt a unserializujeme ho
*/
//naincludujeme soubor s pokusnou třídou
include („trida.php“);
//otevření souboru a přečtení jeho obsahu
$bytestring = implode(„“, @file(„data“));
$UnserializovanyObjekt=unserialize($bytestring);
//necháme si vlastnosti objektu vypsat, abyste viděli, že uložení do souboru „přežili“
$UnserializovanyObjekt->Vypis();
?>
Předání objektu pomocí session je v podstatě stejné jako při ukládání do souboru, jen zde místo funkcí pro uložení souboru použijeme funkce pro předávání session:
<?
/*
Soubor „sesstrida1.php“
*/
session_start(); //nastartovani session
//naincludujeme soubor s pokusnou třídou
include („trida.php“);
//vytvoříme instanci pokusné třídy
$objekt = new clsTrida („Vlastnost 1“, „Vlastnost 2“);
//zde vytvoříme byte řetězec
$bytestring=serialize($objekt);
//vytvoření session
$_SESSION[„serializovanyobjekt“]=$bytestring;
//napíšeme odkaz na další stránku
echo ‚<a href=“sesstrida2.php“>Další stránka</a>‘;
?>
<?
/*
Soubor „sesstrida2.php“
*/
session_start(); //nastartovani session
//naincludujeme soubor s pokusnou třídou
include („trida.php“);
//zde unserializujeme byte řetězec
$UnserializovanyObjekt=unserialize($_SESSION[„serializovanyobjekt“]);
//opět si vypíšeme hodnoty obou vlastností
$UnserializovanyObjekt->vypis();
?>
Magické funkce __sleep() and __wakeup()
Při (un)serializaci mohou být velmi užitečné „magické“ funkce __sleep()
a __wakeup()
, které se umisťují do definice třídy. Funkce __sleep()
se spustí na začátku serializace. Můžeme do ní vložit kód například pro ukončení spojení s databází. Důležité je, aby funkce __sleep()
vrátila pole, které obsahuje proměnné objektu, ze kterých se vytvoří byte řetězec. Naproti tomu funkce __wakeup()
se spustí na začátku unserializace. Lze ji využít například pro obnovení spojení s databází.
V následujícím příkladu si vytvoříme třídu, která si pamatuje datum své serializace a při unserializaci tuto hodnotu vypíše. Byte řetězec v tomto příkladu budeme ukládat do souboru. Funkce get_object_vars()
byla popsána v předchozím článku.
<?
/*
Soubor trida.php ve kterém je definice pokusné třídy
*/
class clsTrida {
//funkce vypis() vypíše hodnoty obou vlastností
function vypis() {
echo „1. vlastnost: „.$this->vlastnost1.“<br />“;
echo „2. vlastnost: „.$this->vlastnost2.“<br />“;
}
function __sleep() {
//do vlastnosti „datum“ uložíme aktuální datum = datum serializace
$this->datum=Date(„Y-m-d“);
//vytvoříme pole vlastností objektu. Jestliže nějakou vlastnost vynecháme, nebude serializovaná.
$vlastnosti = get_object_vars($this);
foreach ($vlastnosti as $klic => $hodnota) {
$pole[] = $klic;
}
//vrácení pole vlastností třídy
return $pole;
}
function __wakeup() {
//jestliže jsme uložili datum, tak ho vypíšeme
if (isset($this->datum)) {
echo „Datum serializace: „.$this->datum.“<br />“;
}
}
}
?>
Výše uvedený příklad je pouze jednoduchou ukázkou magických funkcí a velké praktické využití asi nemá. V následujícím příkladu si tedy vytvoříme třídu, která využívá databázi. Funkce __sleep()
v tomto případě spojení s ní ukončí a vrátí údaje potřebné k přihlášení do databáze, funkce __wakeup()
spojení opětovně naváže. Výhody tohoto postupu jsou zřejmé.
<?
/*
Soubor trida.php ve kterém je definice pokusné třídy
*/
class clsTrida {
//konstruktor třídy
function clsTrida($server,$uzivatel,$heslo,$databaze){
$this->datserver=$server;
$this->datuzivatel=$uzivatel;
$this->datheslo=$heslo;
$this->datjmeno=$databaze;
$this->Pripojeni();
}
//naváže spojeni s databází
function Pripojeni() {
MySQL_Connect($this->datserver,$this->datuzivatel,$this->datheslo);
MySQL_Select_DB($this->datjmeno); //vybrání databáze
}
//funkce vypis() vypíše obsah tabulky; je zde samozřejmě pouze pro demonstraci práce s databází
function Vypis() {
$dotaz=MySQL_Query(„SELECT sloupec1, sloupec2 FROM tabulka“) or Die(MySQL_Error());
while ($data = MySQL_Fetch_Array($dotaz)){
echo $data[sloupec1].“ „.$data[sloupec2];
echo „<br />“;
}
}
//ukončíme spojení s databází a vrátíme přihlašovací údaje
function __sleep() {
MySQL_Close();
//vytvoříme pole vlastností objektu
$vlastnosti = get_object_vars($this);
foreach ($vlastnosti as $klic => $hodnota) {
$pole[] = $klic;
}
//vrácení pole vlastností třídy
return $pole;
}
//opět navážeme spojení s databází
function __wakeup() {
$this->Pripojeni();
}
}
?>
<?
/*
Soubor databaze1.php, kde dochází k serializaci
*/
include(„trida.php“);
$objekt = new clsTrida(„Localhost“, „MojeJmeno“, „TajneHeslo“, „PokusnaDAT“);
//vypíšeme obsah tabulky
$objekt->vypis();
$bytestring=serialize($objekt);
//otevřeme soubor a byte řetězec do něj uložíme
$f = fopen(„data“, „w“); //vytvoření a otevření souboru pro zápis
fputs($f, $bytestring); //uložení bytestringu do souboru
fclose($f); //zavření souboru
?>
<?
/*
Soubor databaze2.php, kde dochází k unserializaci
*/
//naincludujeme soubor s pokusnou třídou
include („trida.php“);
//otevření souboru a přečtení jeho obsahu
$bytestring = implode(„“, @file(„data“));
$UnserializovanyObjekt=unserialize($bytestring);
//vypíšeme obsah tabulky
$UnserializovanyObjekt->Vypis();
?>
Ještě se musím zmínit o jednom bezpečnostním nedostatku zmíněného příkladu. Pokud předáváte byte řetězec v session, data jsou zde v nezašifrované formě, takže je může případný útočník velmi jednoduše odchytit a pokud zná strukturu byte řetězce (která není nijak složitá, zkuste si otevřít soubor, do kterého ukládáte byte řetězec, v libovolném textovém editoru), nebude problém si je přečíst a dostat se tak do naší databáze. Podmínkou je tedy použití například zabezpečeného protokolu SSL.
Všechny příklady z článku si můžete stáhnout. Až na příklad s databází, kde si musíte upravit přihlašovací údaje, budou fungovat bez problémů.
Starší komentáře ke článku
Pokud máte zájem o starší komentáře k tomuto článku, naleznete je zde.
Mohlo by vás také zajímat
-
Jak lze snadno upravovat soubory v PDF?
14. září 2023 -
AI na dosah ruky: Jak je to s AI v osobních zařízeních?
22. ledna 2024
Nejnovější
-
Jak rozšířit úložiště Macu za pětinovou cenu?
16. prosince 2024 -
Nové trendy v doménách pro osobní projekty – DIY, LIVING a LIFESTYLE
9. prosince 2024 -
Jak chránit webové stránky před Web/AI Scrapingem
27. listopadu 2024 -
Jaký monitor je nejlepší k novému Macu Mini?
25. listopadu 2024