Metody magiczne

Metody magiczne są nowością w PHP5. Są to metody, które wywoływane są niejawnie:
  • __construct(): wywoływana w momencie tworzenia egzemplarza obiektu
  • __destruct(): wywoływana w momencie usuwania obiektu
  • __get(): wywoływana w momencie odczytywania wartości z nieistniejącej właściwości
  • __set(): wywoływana w momencie zapisywania wartości w nieistniejącej właściwości
  • __call(): wywoływana w momencie wywoływania nieistniejącej metody
  • __toString(): wywoływana w momencie wyświetlania obiektu
  • __clone: wywoływana w momencie klonowania obiektu.
  • __autoload: nie jest metodą magiczną lecz działa podobnie... ładuje plik z klasą.

__construct() i __destruct() to odpowiednio konstruktor i destruktor. Pierwszy zazwyczaj wykorzystywany jest do przygotowania wszystko potrzebnego przez nowo powstały egzemplarz obiektu a destruktor kończy działanie egzemplarza zwalniając zasoby, kończąc połączenia z bazami danych itd. Prosty przykład:
<?php
class foo
{
function __construct()
	{
	$this->text = 'Cześć, jestem klasa';
	echo 'Konstruktor wywołany<br />';
	}
function __destruct()
	{
	unset($this->text);
	echo 'Destruktor wywołany';
	}
}
$x = new foo();
Stworzenie egzemplarza obiektu poprzez $x = new foo(); wywoła konstruktor oraz, oraz destruktor (gdy egzemplarz nie będzie już potrzebny, zazwyczaj "na końcu" skryptu, lecz nie zawsze).

__get() i __set() ułatwią nam stworzenie mechanizmów dostępowych, co ilustrują przykłady:
<?php
class foo
{
private $dane = array('test' => 'testujemy', 'foo' => 'bar');
public function __get($wlasciwosc)
	{
	return $this->dane[$wlasciwosc];
	}
}
$x = new foo();
echo $x->test;
Wewnątrz klasy mamy prywatną zmienną/tablicę i by uzyskać dostęp do danych zawartych w tej tablicy zastosowaliśmy metodę __get(), która oczekuje jednego parametru - nazwy właściwości. Jak widać wywołaliśmy $x->test co wyświetli tekst "testujemy". Niejawnie wywołana metoda __get przekazała wartość z tablicy.
<?php
class foo
{
private $dane = array('test' => 'testujemy', 'foo' => 'bar');
public function __get($wlasciwosc)
	{
	return $this->dane[$wlasciwosc];
	}
public function __set($wlasciwosc, $wartosc)
	{
	$this->dane[$wlasciwosc] = $wartosc;
	}
}
$x = new foo();
$x->nowe = 'To jest nowa wartość';
echo $x->nowe;
Oto przykład z __set, która oczekuje dwóch parametrów - nazwy właściwości i jej wartości.

Metoda __call pozwoli nam tworzyć klasy robiące za np. przekierowania do innych klas - np. mamy zbiór klas obsługujących różne bazy danych mające określone metody. Możemy zrobić klasę nadrzędną, która będzie "przekierowywała" do odpowiedniej klasy obsługującej wybraną przez nas bazę danych. Prosty przykład:
<?php
class bar
{
public function show_bar()
	{
	return 'To jest z klasy bar';
	}
}

class foo
{
public function __construct()
	{
	$this->bar = new bar();
	}
public function __call($metoda, $argumenty)
	{
	IF(method_exists($this->bar, $metoda))
		{
		return call_user_func_array(array($this->bar, $metoda), $argumenty);
		}
	}
}

$x = new foo();
echo $x->show_bar();
Metoda show_bar() została wywołana jako metoda klasy foo. W klasie tej ona nie istnieje więc niejawnie została wywołana metoda _call oczekująca dwóch argumentów - nazwy metody oraz tablicy z parametrami przekazywanymi do tej metody. Funkcja call_user_func_array pozwala na wywołanie funkcji użytkownika i przekazania do niej argumentów z tablicy. W powyższym przykładzie call_user_func_array wywołuje metodę obiektu a nie zwykłą funkcję.

PHP5 kopiuje obiekty przez odwołanie, a nie przez wartości, dlatego by skopiować zawartość obiektu należy użyć słowa clone. W przeciwnym razie drugi obiekt będzie po prostu odwołaniem do pierwszego.
<?php
class foo
{
function set_tekst($tekst)
	{
	$this->text = $tekst;
	}
function show_tekst()
	{
	return $this->text;
	}
}

$x = new foo();
$x->set_tekst('test 1');
echo $x->show_tekst();

echo '<br /><br />';
$y = clone $x;
$y->set_tekst('test 2');
echo $y->show_tekst();

echo'<br />';
echo $x->show_tekst();
Klonujemy obiekt $x. Jak zauważymy ponowne wywołanie na końcu $x->show_tekst(); zwróci pierwszy łańcuch. Gdyby w wierszy $y = clone $x; nie byłoby "clone" to $x->show_tekst(); zwróciłoby ostatnią wartość jako że $y byłoby "aliasem" do $x.

Funkcja __autoload ułatwi nam życie. Jeżeli mamy klasy w jednym katalogu to możemy zautomatyzować proces ich inkludowania:
<?php
function __autoload($class)
	{
	IF(is_file('classes/'.$class.'.class.php'))
		{
		include_once 'classes/'.$class.'.class.php';
		}
	}
$foo = new KLASA();
Funkcja (nie metoda klasy) ta oczekuje jednego parametru - nazwy klasy ("KLASA"). Jeżeli nie ma dostępnej klasy o podanej nazwie to niejawnie wywołana zostanie funkcja __autoload, która załaduje (jeżeli może) plik z klasą.
Jeżeli ścieżka katalogów, w których PHP szuka plików jest długa to funkcja __autoload może działać dość wolno jako że interpreter będzie przeszukiwał wszystkie katalogi z listy zanim wywoła tą funkcję.
RkBlog

Podstawy PHP, 14 July 2008

Comment article
Comment article RkBlog main page Search RSS Contact