Reklama

zonerbooks.cz | zoner.cz | czechia.com | regzone.cz | inshop.cz | inmail.cz | zonerpress.cz | zonerantivirus.com | zonerama.cz

interval.cz

PHP pro pokročilé - znovu třídy a objekty

16. 04. 2004 | Petr Heller | PHP | Komentáře: 0

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.


Reklama


Další aktuální články na interval.cz

Tematicky související články

Dejte vědět i ostatním o článku

Diskuse (počet komentářů: 0)

Buďte prvním návštěvníkem, který přidá nový komentář.

Přidat nový komentář

Jméno a e-mail jsou nepovinné. Příspěvky obsahující odkaz jsou moderovány.

Zoner AntiVirus Free pro Android
zabezpečte si svůj smartphone, zdarma
Profesionální eshop Zoner inShop od 990 Kč.
Reklama
Reklama

Syndikace

hledáme nové autory | redakce interval.cz | reklama na interval.cz

© ZONER software, a.s., všechna práva vyhrazena, interval.cz dodržuje právní předpisy o ochraně osobních údajů. Powered by WordPress.