Programowanie w języku PHP

Serializacja danych w PHP

Serializacja danych w PHP">Serializacja danych w PHP


Spis treści

     Serializacja danych w PHP">1 Serializacja danych w PHP
          1.1 Serializacja obiektów
               1.1.1 Metody sleep i wakeup
          1.2 Serializacja a sesje
          1.3 Gdzie możemy wykorzystać serializację?


Na początku standardowa, książkowa definicja serializacji (oczywiście z Wikipedii):

Serializacja - w programowaniu komputerów proces przekształcania obiektów, tj. instancji określonych klas, do postaci szeregowej, czyli w strumień bajtów, z zachowaniem aktualnego stanu obiektu. Serializowany obiekt może zostać utrwalony w pliku dyskowym, przesłany do innego procesu lub innego komputera poprzez sieć. Procesem odwrotnym do serializacji jest deserializacja. Proces ten polega na odczytaniu wcześniej zapisanego strumienia danych i odtworzeniu na tej podstawie obiektu klasy wraz z jego stanem bezpośrednio sprzed serializacji.


Serializacja jest bardzo przydatna - dzięki niej możemy zapisać stan obiektu, tablicy czy innej zmiennej do specjalnego ciagu , a następnie przykładowo do bazy danych, czy pliku, lub nawet sesji - a w przyszłości z ów zmiennej skorzystać, co przydaje się np. przy cachowaniu.

Dzięki temu zapisowi możemy w innym skrypcie za pomocą deserializacji  wczytać ten obiekt, posiadający wszystkie właściwości, które nadaliśmy mu przed zapisem do zmiennej tekstowej.

Funkcjami za to odpowiedzialnymi są serialize oraz unserialize, ich użycie prezentuje przykład:

$array= array ( 'value1', 'value2');
$serializedArray= serialize($array); #serializacja tablicy
$unserializedArray= unserialize($serializedArray); #deserializaja
print_r($unserializedArray);


Na początku deklarujemy tablicę posiadającą dwa elementy. Następnie serializujemy tablicę funkcją <em>serialize</em> i przypisujemy do zmiennej <em>$serializedArray</em>. Gdybyśmy ją wyświetlili, ujrzelibyśmy:

a:2:{i:0;s:6:"value1";i:1;s:6:"value2";}


Deserializacja nastepuje za pomocą funkcji <em>unserialize</em>. Odzyskaną tablicę wyświetlamy i oto co widzimy:

Array
(
    [0] => value1
    [1] => value2
)


Struktura zmiennej się nie zmieniła - jest to praktycznie ta sama zmienna!

Serializacja obiektów


Serializacja obiektów nie różni się w zasadzie od serializacji innych zmiennych:

class Serialization {
    private $field;
 
    /**
     * Zapisuje zmienna
     */
    public function setField($value) {
        $this->field= $value;
    }
 
    /**
     * Zwraca zmienna
     */
    public function getField() {
        return $this->field;
    }
}
 
$serialization= new Serialization(); #tworzymy obiekt
$serialization->setField('value'); #przypisujemy polu wartość value
$serializedObject= serialize($serialization); #serializujemy
$unserializedObject= unserialize($serializedObject); #deserializujemy

echo $unserializedObject->getField(); #wyswietlamy pole deserializowanego obiektu


Jak widzimy mamy tu klasę Serialization, z polem $field. Po utworzeniu obiektu zapisujemy polu wartosc value, następnie poddajemy serializacji i deserializacji i wyświetlamy pole - jest to ta sama wartość!

Jednak gdy chcemy użyć serializowanej zmiennej w innym skrypcie należy pamiętać, że musi być w nim zawarty kod klasy tego obiektu!

Metody sleep i wakeup


Obiekty mają tą dogodność, że mogą dowolnie zmieniać własne dane  podczas serializacji  i deserializacji, za pomocą metod magicznych.

Pierwszą z nich jest metoda o nazwie __sleep. Wywoływana jest ona automatycznie podczas serializacji obiektu i może służyć do manipulowania danymi, które muszą zostać zmodyfikowane przed poddaniem obiektu serializacji. Funkcja powinna zwrócić tablicę, której elementy będą nazwami pól obiektu, które mają zostać w nim zachowane.

Funkcja __wakeup jest wywoływana przy deserializacji obiektu. Może być przydatna np. do ponownego połączenia z bazą, otwarcia pliku itd.


class Serialization {
    private $time;
 
    public function __sleep() {
        $this->time= time(); #zapis aktualnego czasu
        return array_keys(get_object_vars($this));
    }
 
    public function __wakeup(){
        echo $this->time; #wyswietlamy czas serializacji
    }
}
 
$serialization= new Serialization(); #tworzymy obiekt
$serializedObject= serialize($serialization); #serializujemy
$unserializedObject= unserialize($serializedObject); #deserializujemy



Efektem kodu jest wyświetlenie uniksowego znacznika czasu, w którym nastąpiła serializacja. W przykładzie podczas serializacji zapisujemy czas, w którym obiekt został jej poddany, a podczas deserializacji jest on wyświetlany.

Warto zwrócić uwagę na linię

return array_keys(get_object_vars($this));


<em>get_object_vars</em> zwraca nam tablice składająca sie z nazw pól obiektu i ich wartości, a <em>array_keys</em> zwraca tejże tablicy indeksy, przez co dostajemy nazwy wszystkich pól obiektu - są one niezbedne do poprawnej serializacji.

Serializacja a sesje


Sesje są ściśle związane z serializacją - podczas zapisu zmiennej do sesji, jest ona przechowywana właśnie jako serializowany string. Podczas rozpoczecia sesji obiekty są deserializowane, a podczas zakończenia parsowania kodu zmienne sesyjne są poddawane serializacji.

Najlepiej zobrazuje to przykład, który w końcu zaprezentuje praktyczne wykorzystanie serializacji:

session_start();
 
class DBConnector {
    public $connection, $user, $pass, $host;
 
    public function connect() {
        if (!$this->connected)
            $this->db= new mysqli($this->host, $this->user, $this->pass); #polaczenie sie z baza danych
    }
    /**
     * Stwier    dza czy jestesmy juz polaczeni z baza danych
     */
    public function connected() {
        return $this->db instanceof mysqli; #jezeli zmienna jest implementacja klasy mysqli
    }
 
    public function __sleep() {
        $this->db->close(); #rozlaczenie
        $this->db= null; #wyczyszczenie zmiennej
        echo 'Rozłączono z bazą danych';
        return array_keys(get_object_vars($this));
    }
 
    public function __wakeup() {
        echo $this->connect(); #laczymy
    }
}
 
$connector= new DBConnector();
$connector->host= 'localhost';
$connector->user= 'user';
$connector->pass= 'password';
$connector->connect();
 
$_SESSION['connector']=$connector;


W przykładzie mamy klasę łączącą się z bazą danych, oraz przechowującą identyfikator połączenia. Po zapisie jej do zmiennej sesyjnej oraz zakończeniu skryptu zostaje ona poddana serializacji, czego efektem będzie rozłączenie się z bazą danych oraz wyświetlenie komunikatu.

Teraz gdy odpalimy inny plik, będziemy mogli skorzystać z tych danych i  korzystać z bazy danych:

require_once('DBConnector.class.php');
session_start();
if($_SESSION['connector']->connected()) echo 'Jest połączenie z bazą danych';


Pamiętajmy by załączyć klasę, której implementacją jest obiekt przed rozpoczęciem sesji - inaczej wyświetli nam się błąd.

Gdzie możemy wykorzystać serializację?


Serializacja przydaje się między innymi podczas cachowania danych - wielokrotny pobór danych z bazy danych,a następnie ich przetwarzanie jest powolne, a wraz z obciążeniem skryptu przez użytkowników wzrasta jeszcze bardziej. Zapisując serializowane dane do pliku i korzystanie z nich znacznie usprawni prace skryptu. Serializacja przyda się pewnie też przy rozbudowanych formularzach, składających się z kilku stron - wtedy korzystamy z obiektów w sesji.

Autor: Mateusz 'MatheW' Wójcik
Adres URL pierwotnej wersji: http://blog.mwojcik.pl/2007/08/04/serializacja-w-php/
Kopiowanie bez podania pierwotnego źródła zabronione.