indeks
co na cd
newsy
z okładki
fi rma
magazyn
programy
warsztat
97
INTERNET.luty.2004
PHP
C
zego nowego możemy się spodziewać w PHP5? Przede wszyst-
kim obiektów! Nowy model obiektowy zadziwia możliwościami.
Wprowadzono też obsługę wyjątków (błędów), wzorowaną na
takich językach jak Java czy C++. Druga wersja silnika Zend oraz nowy
menedżer pamięci powodują, że PHP5 działa szybciej, lepiej i stabilniej.
Niektóre rozwiązania zaprezentowane w artykule można zastosować
w PHP4, ale zostały one przytoczone w celu lepszego zrozumienia różnic,
jakie występują między wersjami 4 i 5. Ponadto niektóre opcje w ofi cjalnym
wydaniu PHP5 mogą wyglądać i działać trochę inaczej niż w wersji beta.
Nowy model obiektowy
Sposób obsługi obiektów w PHP5 został całkowicie przebudowany,
co zaowocowało zwiększeniem wydajności. W poprzednich wersjach
PHP obiekty traktowane były jak zwykłe typy zmiennych (np. zmienne
całkowite czy ciągi znaków). Każde odwołanie się do takiego obiektu
(przypisanie go do zmiennej czy przekazanie go jako parametru jakiejś
funkcji) skutkowało stworzeniem jego kopii. W nowym wydaniu modelu
obiektowego do każdego obiektu tworzony jest tzw. uchwyt (ang. handle),
czyli identyfi kator, przy użyciu którego odwołujemy się do niego. Sposób
tworzenia obiektów i ich obsługi jest jednakowy w PHP4 i 5.
$obiekt = new MojaKlasa();
//inicjacja obiektu
klasy MojaKlasa
$obiekt->wyswietl _ imie();
//wywołanie metody
klasy MojaKlasa
$zmienna = $obiekt->Imie;
//przypisanie do
zmiennej właściwości klasy MojaKlasa
Wielu programistów do dzisiaj nie wie o takim sposobie obsługi obiektów
w PHP4, dlatego też zmiana ta nie powinna w jakikolwiek sposób wpłynąć
na działanie aplikacji napisanych w PHP4. W najgorszym wypadku trzeba
będzie wprowadzić do istniejących już programów drobne poprawki. Aby
ułatwić przejście z PHP4
do PHP5, twórcy zaimple-
mentowali w PHP5 opcję
auto-clone, która spowo-
duje wymuszenie kopio-
wania obiektów w taki
sposób, jak to było ob-
sługiwane we wcześniej-
szych wersjach PHP.
Konstruktory i destruktory
W PHP4 sposób obsługi konstruktorów był bardzo prosty: ta metoda klasy,
która nazywała się tak samo jak klasa, traktowana była jako konstruktor.
Natomiast destruktorów nie było w ogóle. W PHP5 sytuacja ta zmienia się
diametralnie. Wprowadzono zunifi kowaną obsługę konstruktorów oraz
destruktorów poprzez stworzenie metod __construct oraz __destruct.
Konstruktor wywoływany jest przy każdym stworzeniu nowego obiek-
tu, natomiast destruktor chwilę przed jego zniszczeniem. Uruchomienie
skryptu z listingu 1 (patrz CD) spowoduje wyświetlenie komunikatów
pokazanych na rys. 2a.
Publiczne, prywatne, zastrzeżone
Na wzór takich języków jak C++, Pascal czy Java w PHP5 rozgraniczono
także dostęp do właściwości oraz metod klasy. Istnieją trzy słowa kluczo-
we, które umożliwiają określenie dostępu do danej metody czy właściwości
klasy: public, private oraz protected. Ramka obok przedstawia różnice wy-
stępujące między nimi, a listing 2 (na CD) – ich praktyczne zastosowanie.
Mimo że najnowsza wersja PHP, oznaczona numerem 5, nie jest
jeszcze dostępna, już dziś możemy poznać jej możliwości dzięki
pojawiającym się coraz częściej wersjom beta (najświeższa
to beta 3, do pobrania z serwisu http://www.php.net). Wszystko
wskazuje na to, że „piątka” odniesie wielki sukces.
Sebastian Marek
Rys. 1. PHP 5 w wersji beta 2
Dostęp do właściwości i metod klasy
Public
Private
Protected
Właściwość lub metoda klasy
Tylko metody należące do tej
Tylko metody należące do tej
jest dostępna spoza niej.
samej klasy mają dostęp do
samej klasy lub do klasy
Oznacza to, że można się do
właściwości lub metod tej
dziedziczącej mają dostęp
niej odwołać bezpośrednio.
klasy.
do właściwości lub metod
tej klasy.
Rys. 2. Tak jak w innych językach programowania, tak i w PHP5
konstruktor i destruktor są automatycznie wywoływane w momencie
stworzenia oraz zniszczenia obiektu (a), a dostęp do pól
i metod obiektu można ograniczyć (b)
Wszyst
kie listingi
z tego a
rty-
kułu zn
ajdują s
ię na do
łączo-
nej płyc
ie CD w k
atalogu
PHP5-p
rzyklad
owe list
ingi.
Co nowego
Co nowego
w piątej wersji PHP
w piątej wersji PHP
indeks
co na cd
newsy
z okładki
fi rma
magazyn
programy
warsztat
98
INTERNET.luty.2004
PHP
Wyjątki
W PHP4 programowało się łatwo, szybko i przyjemnie do momentu, gdy
w kodzie wystąpił jakiś błąd. Tragedia następowała wtedy, gdy według
nas aplikacja chodziła stabilnie, a od klienta dostawaliśmy informację, że
coś nie działa. Widzę programistów błagających o pomoc: dlaczego nie ma
obsługi wyjątków? No i są! Na wzór innych języków programowania dosta-
jemy w prezencie pętlę try…catch oraz wspomagającą obsługę wyjątków
klasę macierzystą Exception.
Na przykładzie z listingu 3 (patrz CD) przeanalizujemy zastosowanie
wyjątków. Stworzyłem prostą klasę MojaKlasa zawierającą dwie metody:
GetYear() i SetYear(), oraz jedną właściwość $Year. Naszym zadaniem jest
sprawdzenie poprawności parametru metody SetYear() – parametr ten po-
winien przyjmować wartości od 2003 do 2005.
if ( $ _ year > 2003 && $ _ year <= 2005 )
{
$this->Year = $ _ year;
}
Jeżeli będzie inaczej, poinformujemy o tym użytkownika stosownym
komunikatem. Gdy parametr tej metody przyjmie wartość mniejszą od
2003, spowodujemy stworzenie wyjątku, przypisując mu poniższy komu-
nikat oraz numer błędu:
elseif ( $ _ year < 2003 )
{
throw new Exception( ”Rok nie może być mniejszy od
2003”, 1 );
}
Podobnie zabezpieczymy się w przypadku, gdy parametr metody przyj-
mie wartość większą od 2005:
elseif( $ _ year > 2005 )
{
throw new Exception( ”Rok nie może być większy od
2005”, 2 );
}
Na koniec zabezpieczymy się przed wystąpieniem nieprzewidywalnego
błędu:
else
{
throw new Exception( ”Rok musi zawierać się między
2003 a 2005”, 0 );
}
Metody SetYear() oraz GetYear() umieszczamy w bloku kodu try. W
tym miejscu PHP5 czeka na wystąpienie błędu (a dokładnie na utworze-
nie nowego obiektu klasy Exception). Jeżeli cała operacja przebiegnie
bezbłędnie, nic się nie stanie (tzn. wykonane zostaną powyższe metody
i wyświetlona zawartość pola Year), w przeciwnym wypadku wykonane
zostaną instrukcje zawarte w bloku kodu catch. W naszym przypadku wy-
świetlimy szczegółowe informacje na temat powstałego błędu:
catch ( Exception $e )
{
echo ”Błąd nr ” . $e->getCode() . ” – ” . $e->
getMessage();
echo ” (” . $e->getFile() . ” – linia ” . $e->
getLine() . ” ) ”;
}
Zapytacie: skąd mamy wziąć informacje na temat tego błędu? Tu przy-
chodzi z pomocą wspomniana klasa Exception. Można oczywiście napisać
własną klasę obsługującą wyjątki, ale po co wyważać otwarte drzwi.
W zasadzie zaleca się do obsługi wyjątków używanie klasy Excep-
tion, a w przypadku chęci jej rozbudowy, stworzenie na jej podstawie
klasy potomnej. Nam jednak w zupełności ona wystarczy. W ramce
obok znajdują się dostępne pola oraz metody klasy Exception. Listing
3 obrazujący całość zagadnienia jest dostępny na CD.
Rys. 3. Wystąpienie wyjątku w aplikacji
Elementy wspomagające obsługę obiektów
Dodatkowo w PHP5 znalazło się kilka elementów pomocnych w ob-
słudze obiektów. Można na przykład określić, że argumentem jakiejś
metody ma być obiekt danej klasy (tzw. type hinting):
<?php
class MojaKlasa
{
//kod klasy MojaKlasa
}
Specyfikacja klasy Exception
Konstruktor
_ construct(string $message=NULL,
Tworzy nowy obiekt klasy
int code=0)
Exception generując domyślnie
komunikat „Unknown exception”
oraz kod błędu równy 0
(w naszym przykładzie
samodzielnie
określamy
przy
tworzeniu
obiektu
komunikat
oraz kod błędu).
Pola klasy
protected $message = ’Unknown
Pole przechowujące komunikat
exception’
błędu (domyślnie przyjmuje
wartość „Unknown exception”).
protected $code = 0
Pole przechowujące kod błędu
(domyślnie
przyjmuje
wartość
0).
protected $fi le
Pole przechowujące ścieżkę
dostępu
oraz
nazwę
pliku,
w którym wystąpił błąd.
protected $line
Pole przechowujące nr linii
w pliku, w którym wystąpił błąd.
Metody klasy
getMessage()
Metoda zwracająca zawartość
pola
$message;
getCode()
Metoda zwracająca zawartość
pola
$code;
getFile()
Metoda zwracająca zawartość
pola $fi le;
getLine()
Metoda zwracająca zawartość
pola $line;
indeks
co na cd
newsy
z okładki
fi rma
magazyn
programy
warsztat
99
INTERNET.luty.2004
PHP
class InnaKlasa
{
public function Konwertuj(
MojaKlasa $obiekt )
{
//kod metody Konwertuj
}
}
$obiekt1 = new InnaKlasa();
$obiekt2 = new MojaKlasa();
$obiekt1->Konwertuj( $obiekt2 );
?>
Ze względu na to, że dostęp do obiektu jest
realizowany poprzez uchwyt, straciliśmy „na-
turalną” metodę pozyskiwania kopii danego
obiektu. Dodatkowo, PHP4 nie umożliwiał
w żaden sposób użycia konstruktora kopiujące-
go. W PHP5 dostępna jest teraz metoda __clo-
ne(), która nie tylko umożliwia stworzenie du-
plikatu danego obiektu, ale dodatkowo pozwala
na zdefi niowanie wartości poszczególnych pól
tej klasy w skopiowanym obiekcie. Jeżeli taka
metoda została zdefi niowana w defi nicji klasy,
jest ona wywoływana w momencie skopiowania obiektu. Jeżeli natomiast
programista nie zdefi niował takiej metody, wywoływana jest domyślna
jej postać, która ma za zadanie skopiować do nowego obiektu zawartość
wszystkich pól. Całość ilustruje listing 4 – patrz CD.
Wprowadzono również możliwość defi niowania stałych wewnątrz
klasy:
class MojaKlasa
{
const Stala = ”Stała wartość”;
}
echo ”Wartość stałej <i>Stala</i> klasy <i>Moja
Klasa</i>: <b>” . MojaKlasa::Stala . ”</b>”;
oraz obsługę próby dostępu bądź przypisania wartości do nieistniejącego
pola klasy. W tym celu należy tylko zdefi niować następujące metody:
__get() oraz __set(). Jeśli odwołamy się do pola, które nie istnieje, zosta-
nie automatycznie wywołana metoda __get(), a gdy spróbujemy przypisać
jakąś wartość nieistniejącemu polu klasy, wywołana zostanie metoda
__set(). Do obsługi nieistniejących metod klasy wykorzystać można
metodę __call():
<?php
echo ”<center><h1>Obsługa nieistniejących pól
i metod w PHP5 – metody <i> _ _ set(), _ _ get()</i>
oraz <i> _ _ call()</i></h1></center>”;
class MojaKlasa
{
public $x;
function _ _ get( $name )
{
echo ”Nastąpiła próba wywołania nieistniejącego
pola <b>$name!</b><br/>”;
}
function _ _ set( $name, $value )
{
echo ”Nastąpiła próba przypisania do
nieistniejącego pola <b>$name</b> wartości
<b>$value</b>!<br/>”;
}
function _ _ call( $name, $value )
{
echo ”Nastąpiła próba wywołania nieistniejącej
metody <b>$name</b> z argumentami: <br/>”;
var _ dump( $value );
}
}
$obiekt = new MojaKlasa();
$obiekt->y = 15;
echo ”Oto pole: ” . $obiekt->z . ”<br/>”;
echo ”Oto metoda: ” . $obiekt->Ustaw( ”Styczeń”, 5,
TRUE ) . ”<br/>”;
?>
Artykuł ten opisuje właściwości PHP5 w wersji beta. Przypuszczalnie
więc w ofi cjalnej wersji twórcy PHP na pewno czymś nas jeszcze zaskoczą
– czymś pozytywnym oczywiście. Ale nawet biorąc pod uwagę tylko te
zmiany, które tu opisałem, można stwierdzić, że „piątka” będzie na piątkę.
Rys. 4. Wykorzystanie konstruktora kopiującego (a)
oraz stałych wewnątrz klasy (b)
Rys. 5. Implementacja metod __get(), __set() oraz __call()