C
M
Y
K
Klasy i obiekty
Klasa i obiekt to dwa kluczowe pojêcia towarzysz¹ce progra-
mowaniu obiektowemu. Pisanie kodu obiektowego polega na
definiowaniu klas, zwi¹zków i relacji miêdzy nimi oraz ma-
nipulowaniu obiektami. Klasa jest typem danych, zaœ obiekt
– zmienn¹.
W jêzyku PHP na ogó³ nie deklarujemy typu zmiennej.
Jeœli zmienna przechowuje liczbê czy napis, to w skrypcie
nie wystêpuje jawne ustalenie typu. Typ zmiennej wynika
z wykonanych na niej operacji.
Do sprawdzenia typu zmiennej stosujemy funkcjê
var_dump(). Po wykonaniu poni¿szego kodu zmienna
$z1 bêdzie typu int, o czym przekona uzyskany
wydruk:
$z1 = 123;
var_dump($z1);
W przegl¹darce pojawi siê tekst int(123) informuj¹cy
o typie (int) i wartoœci (123) zmiennej $z1. W powy¿szym
przyk³adzie wystêpuje zatem typ int oraz zmienna $z1,
przy czym typ int pojawia siê w sposób niejawny: wynika
on z wartoœci przypisanej do zmiennej.
W przypadku zmiennych bêd¹cych obiektami sprawa
wygl¹da odmiennie. Tworz¹c obiekt musimy podaæ nazwê klasy (czyli
typ zmiennej). Kod obiektowy:
//definicja typu
class ALAMAKOTA {
}
//utworzenie zmiennej
$z2 = new ALAMAKOTA;
//sprawdzenie typu zmiennej
var_dump($z2);
zawiera definicjê typu ALAMAKOTA oraz zmienn¹ $z2.
Tym razem w przegl¹darce pojawi siê tekst object(alama-
kota), który mówi o tym, ¿e obiekt $z2 jest typu obiekto-
wego ALAMAKOTA.
Pomiêdzy powy¿szymi przyk³adami nale¿y odnoto-
waæ dwie ró¿nice. Typ int jest predefiniowany i nie mu-
simy pisaæ jego definicji, podczas gdy klasa ALAMA-
KOTA musi byæ zawarta w skrypcie. Druga ró¿nica po-
lega na tym, ¿e typ zmiennej $z1 zostaje ustalony na
podstawie wartoœci 123 przypisanej do zmiennej, zaœ
w odniesieniu do obiektu $z2 nazwa typu ALAMAKO-
TA zostaje podana jawnie.
W dwóch przedstawionych przyk³adach wystêpuj¹:
typ int i zmienna $z1 oraz typ ALAMAKOTA
i zmienna $z2.
W stosunku do typów i zmiennych obiektowych sto-
sujemy terminologiê klasa i obiekt. Mówimy „klasa ALAMAKO-
TA” oraz „obiekt $z2”.
PHP
INTERNET.listopad.2005
102
NA CD
NEWSY
Z OK£ADKI
FIRMA
MAGAZYN
PROGRAMY
WEBMASTERING
Na przestrzeni ostatnich lat programowanie obiektowe w PHP
uleg³o istotnym zmianom. Wersja 3 zawiera³a jedynie namiastkê
obiektowoœci, PHP4 wspiera programowanie obiektowe w znacznym
stopniu, ale dopiero wersja 5 jest jêzykiem obiektowym w pe³nym
tego s³owa znaczeniu. W trzech odcinkach omówimy podstawy
programowania obiektowego w PHP, zbadamy mo¿liwoœci PHP4
w dziedzinie obiektowoœci oraz poka¿emy nowoœci
wprowadzone w PHP5.
W³odzimierz Gajda
PROGRAMOWANIE
OBIEKTOWE
Część I
l
jakie możliwości
niesie za sobą PHP5
pod względem
programowania
obiektowego
l
jakie są różnice
w programowaniu
obiektowym w PHP4
i PHP5
CZEGO SIÊ DOWIESZ
Z TEGO ARTYKU£U?
l
znajomość PHP
na poziomie
podstawowym
WYMAGANA WIEDZA
UWAGA! Dwie
pozostałe części
tego artykułu,
wraz z listingami
i przykładami,
są dostępne na płycie
CD oraz w naszym
serwisie internetowym:
www.mi.com.pl
w PHP4 i PHP5
Podstawy programowania obiektowego w PHP
C
M
Y
K
Definicja klasy
Definicja klasy w jêzyku PHP jest nastêpuj¹ca:
class A {
//sk³adowe klasy
}
Po s³owie kluczowym class umieszczamy nazwê klasy, zaœ
pomiêdzy nawiasami klamrowymi – sk³adowe klasy, którymi
w PHP s¹ pola oraz metody. Pola to zmienne, w których prze-
chowujemy dane, natomiast metody to funkcje przetwarzaj¹ce
obiekt. Kolejnoœæ pól i metod w definicji klasy mo¿e byæ
dowolna, warto jednak stosowaæ ogólnie przyjêt¹ konwencjê
i umieszczaæ na pocz¹tku klasy wszystkie pola, po nich zaœ
– metody.
W czêœci jêzyków programowania sk³adow¹ klasy mo¿e byæ
tak¿e w³aœciwoœæ – specjalne pole, do którego dostêp powoduje
wywo³anie dodatkowych metod. W PHP4 w³aœciwoœci nie wystêpu-
j¹ w ogóle, zaœ w PHP5 do definiowania w³aœciwoœci mo¿emy u¿yæ
funkcji _get() oraz _set(). Termin w³aœciwoœæ jest stosowany tak¿e
w odniesieniu do zwyk³ych pól klasy.
Poniewa¿ w PHP5 pojawi³y siê specyfikatory dostêpu, definicja
sk³adowych klasy nieco ró¿ni siê w jêzykach PHP4 oraz PHP5.
Teraz omówimy definiowanie sk³adowych klasy w jêzyku PHP4,
zaœ zagadnienia dotycz¹ce PHP5 przedstawimy w dalszej czêœci,
w punkcie zatytu³owanym „Specyfikatory dostêpu”.
Definicja pola w jêzyku PHP4 sk³ada siê ze s³owa kluczowego
var, po którym nastêpuje nazwa poprzedzona znakiem dolara. Kla-
sa mo¿e zawieraæ dowoln¹ liczbê pól, których nazwy musz¹ byæ
unikalne w ramach klasy. Podobnie jak w przypadku zwyk³ych
zmiennych, tak i w odniesieniu do pól nie okreœlamy ich typu.
Wartoœci pól mo¿emy inicjalizowaæ sta³ymi, nie mo¿emy natomiast
stosowaæ do tego celu wyra¿eñ.
Definicja metody nie ró¿ni siê niczym od zwyk³ej definicji
funkcji. Warto jednak zaznaczyæ, ¿e metody nie mog¹ byæ, tak jak
na przyk³ad w C++, prze³adowywane. Innymi s³owy nazwy metod
w obrêbie klasy musz¹ byæ unikalne. Oczywiœcie metody – analo-
gicznie jak zwyk³e funkcje – mog¹ zawieraæ parametry.
Klasa A po dodaniu dwóch pól oraz dwóch metod przyjmie
w PHP4 postaæ:
class A {
var $pole1;
var $pole2;
function fun1()
{
//...
}
function fun2()
{
//...
}
}
Umieszczenie powy¿szej klasy wewn¹trz skryptu nie spowoduje
¿adnych widocznych efektów. Definicja klasy jest definicj¹ typu.
Ustala ona budowê obiektu: okreœla jego pola i metody. Jednak ¿aden
konkretny obiekt podanego typu nie jest tworzony, a metody nie s¹
wywo³ywane.
Klasy w jêzyku PHP podlegaj¹ dwóm ograniczeniom sk³a-
dniowym:
X
klasa musi byæ umieszczona w jednym bloku kodu PHP,
X
definicje metod musz¹ znajdowaæ siê wewn¹trz definicji klasy.
Obiekty – instancje klasy
Jak ju¿ powiedzieliœmy, obiekt jest zmienn¹, której typ jest klas¹.
Obiekty tworzymy nieco inaczej ni¿ zmienne skalarne. W przypadku
zwyk³ych zmiennych wystarczy instrukcja przypisania:
$imie = ’Jan’;
natomiast w przypadku obiektu stosujemy operator new, po którym
podajemy nazwê klasy. Jeœli w skrypcie pojawia siê definicja klasy A,
wówczas utworzenie obiektu podanego typu przyjmie postaæ:
$ob = new A;
Mówimy „obiekt $ob klasy A” lub nazywamy zmienn¹ $ob. „in-
stancj¹ klasy A” czy te¿ „egzemplarzem klasy A”.
Dostęp do pól i metod
Do sk³adowych klasy odwo³ujemy siê operatorem ->. Jeœli klasa A ma pola
$pole1, $pole2 oraz metody fun1() i fun2(), wówczas po utworzeniu obiektu
$tmp mo¿emy przypisywaæ wartoœci do pól i wywo³ywaæ metody:
$tmp = new A;
$tmp->pole1 = ”Ala ma kota”;
$tmp->fun1();
Zwróæmy uwagê na fakt, ¿e znak dolara pojawia siê zawsze jeden raz
przed zmienn¹. W stosunku do pola $pole1 poprawnym odwo³aniem jest:
$tmp->pole1 = ”Ala ma kota”;
podczas gdy instrukcja:
PRZYK£AD NIEPOPRAWNY
$tmp->$pole1 = ”Ala ma kota”;
jest b³êdna z racji na wyst¹pienie znaku dolara przed nazw¹ pola pole1
(mimo ¿e dolar ten wystêpuje przed nazw¹ pola w definicji klasy var
$pole1;).
W PHP w wersji 4 wszystkie pola i metody klasy maj¹ zasiêg pu-
bliczny. Oznacza to, ¿e mo¿emy odwo³ywaæ siê do ka¿dego pola
i ka¿dej metody z dowolnego miejsca skryptu.
Referencja $this
Równie¿ wewn¹trz definicji metod klasy mo¿emy uzyskiwaæ dostêp
do jej sk³adowych. W tym celu stosujemy referencjê $this. Referencja
$this jest nazywana w dokumentacji jêzyka PHP pseudozmienn¹.
Odwo³ania takie maj¹ postaæ:
function fun1()
{
$this->pole1 = 10;
$this->fun2();
}
Pamiêtajmy, ¿e odwo³ania pozbawione referencji $this (takie, które
by³yby poprawne w jêzykach C++ czy w obiektowym Pascalu œrodo-
wiska Delphi) w PHP s¹ niepoprawne. Jeœli wewn¹trz metody fun1()
napiszemy:
function fun1()
{
$pole1 = 33;
}
PHP
INTERNET.listopad.2005
103
WEBMASTERING
PROGRAMY
MAGAZYN
FIRMA
Z OK£ADKI
NEWSY
NA CD
Chcesz wiedzieć więcej? Zajrzyj na nasze forum:
http://forum.mi.com.pl
C
M
Y
K
to instrukcja taka spowoduje utworzenie lokalnej zmiennej o nazwie $pole1
wewn¹trz funkcji fun1(). Wartoœæ 33 nie bêdzie zapisana do pola obiektu, a do
zmiennej lokalnej, i zostanie utracona po zakoñczeniu dzia³ania funkcji. Jest to
doœæ powszechny b³¹d nêkaj¹cy programistów rozpoczynaj¹cych poznawanie
obiektowego PHP. B³¹d jest o tyle k³opotliwy, ¿e nie powoduje (w odró¿nie-
niu do dwóch dolarów $obiekt->$pole) komunikatów ze strony parsera PHP.
Warto odnotowaæ, ¿e w niektórych przypadkach referencja $this nie
wskazuje obiektu, w którym wyst¹pi³a w definicji. Dzieje siê tak w przy-
padku statycznego wywo³ywania metod klasy przy u¿yciu operatora ::.
W poni¿szym kodzie referencja $this wskazuje obiekt b klasy B, a nie, jak
by siê wydawa³o, obiekt klasy A:
class A {
var $pole1 = ’black’;
function fun1()
{
echo $this->pole1;
}
}
class B {
var $pole1 = ’white’;
function fun2()
{
A::fun1();
}
}
$b = new B;
$b->fun2();
Powy¿sza dwuznacznoœæ zosta³a w PHP5 rozwi¹zana poprzez za-
kaz stosowania referencji $this wewn¹trz metod statycznych.
Konstruktor w PHP4
Poœród wszystkich metod danej klasy jedna pe³ni specjaln¹ rolê. Meto-
d¹ t¹ jest konstruktor. W PHP4 konstruktorem jest metoda o nazwie
identycznej jak klasa, w której wystêpuje. Konstruktor klasy A nazywa
siê A i jest zdefiniowany w klasie A:
class A {
function A()
{
echo ’...xxx...’;
}
}
Konstruktor jest wywo³ywany automatycznie podczas tworzenia
obiektu. Zatem umieszczenie w kodzie skryptu instrukcji:
$tmp = new A;
spowoduje wywo³anie konstruktora klasy A, skutkiem czego w prze-
gl¹darce pojawi siê tekst ”...xxx...”.
Konstruktor, podobnie jak i inne metody, mo¿e zawieraæ parame-
try. W takim przypadku utworzenie instancji wymaga podania po
nazwie klasy parametrów konstruktora:
$ob = new Ksiazka($tytul, $id);
Przykład: Klasa MenuWierszy
Przedstawione zagadnienia stanowi¹ pierwszy krok w kierunku pro-
gramowania obiektowego i pozwalaj¹ na przygotowanie w pe³ni funk-
cjonalnych skryptów. Zagadnieniami tymi s¹:
X
definicja klasy zawieraj¹cej pola i metody,
X
tworzenie instancji klasy operatorem new,
X
uzyskiwanie dostêpu do pól i metod klasy z zewn¹trz
(operator –>),
X
uzyskiwanie dostêpu do pól i metod z wnêtrza metod klasy
(referencja $this),
X
konstruktor klasy.
Opisany skrypt jest napisany w wersji 4 jêzyka PHP. Z racji na
zgodnoœæ w dó³, skrypt ten bêdzie dzia³a³ poprawnie tak¿e w wersji 5.
Pracê nad skryptem rozpoczynamy od ustalenia sk³adowych klasy,
czyli jej pól i metod. Klasa o nazwie MenuWierszy bêdzie zawiera³a
dwa pola $FIle i $FElementy oraz trzy metody: konstruktor Menu-
Wierszy(), getMenu() i getTresc(). Pola bêd¹ przechowywa³y informa-
cje dotycz¹ce zawartoœci witryny: liczba wierszyków dostêpnych na
stronie (pole $FIle), tytu³y wierszyków oraz nazwy plików teksto-
wych, w których wiersze s¹ zapisane (dwuwymiarowa tablica $FEle-
menty). Konstruktor klasy bêdzie tworzy³ obiekt i ustala³ wartoœci pól
na podstawie danych odczytanych z pliku, zaœ metody getMenu()
i getTresc() bêd¹ odpowiedzialne za przygotowanie kodu HTML za-
wieraj¹cego menu oraz treœæ strony. Wydruki generowane przez meto-
dy getMenu() oraz getTresc() bêd¹ powstawa³y na podstawie wartoœci
pól $FIle oraz $FElementy. Definicja klasy z pominiêciem implemen-
tacji metod zosta³a przedstawiona na listingu 1
.
Wewn¹trz konstruktora MenuWierszy() oraz metod getMenu()
i getTresc() mo¿emy operowaæ polami $FIle oraz $FElementy. Stosu-
jemy w tym celu referencjê $this, pisz¹c:
$this->FIle = count($tmp);
czy
$this->FElementy = array();
Definicjê klasy umieszczamy w pliku menuwierszy.class.php i do-
³¹czamy do g³ównego skryptu strona.php instrukcj¹ require_once. Jak
ju¿ wiemy, definicja klasy nie powoduje wykonania ¿adnego kodu.
Metody klasy, podobnie jak zwyk³e funkcje, nie podlegaj¹ wykonaniu,
a¿ do momentu, gdy w skrypcie pojawi siê ich wywo³anie. W celu wy-
korzystania przygotowanej klasy MenuWierszy musimy utworzyæ
obiekt bêd¹cy instancj¹ podanej klasy:
$menu = new MenuWierszy;
Instrukcja ta tworzy obiekt o nazwie $menu klasy MenuWier-
szy. Konstruktor klasy jest wywo³ywany automatycznie podczas
tworzenia obiektu. Obiekt $menu po utworzeniu bêdzie zawiera³
wszelkie informacje niezbêdne do wygenerowania menu oraz
zawartoœci strony (informacje te s¹ odczytywane z pliku 00in-
dex.log w konstruktorze).
Metody getMenu() oraz getTresc() zwracaj¹ kod HTML stanowi¹-
cy menu oraz zawartoœæ strony. Wywo³anie tych metod umieszczamy
w odpowiednich miejscach kodu HTML strony g³ównej. Zarys g³ów-
nego skryptu zapisanego w pliku strona.php jest przedstawiony na
listingu 2
.
Zmiany wprowadzone w PHP5
Wersja 5 jêzyka PHP wprowadzi³a kilka istotnych zmian i rozszerzeñ
dotycz¹cych programowania obiektowego. W stosunku do omówione-
go przyk³adu rozszerzeniu uleg³a definicja klasy (wprowadzono specy-
fikatory dostêpu), definicja konstruktora oraz dodano pojêcie destruk-
tora. Przyjrzymy siê poszczególnym zmianom, a nastêpnie zmodyfiku-
jemy klasê MenuWierszy tak, by stosowa³a mechanizmy dostêpne
w PHP5.
PHP
INTERNET.listopad.2005
104
NA CD
NEWSY
Z OK£ADKI
FIRMA
MAGAZYN
PROGRAMY
WEBMASTERING
Podczas nauki programowania obiektowego w PHP5 warto w kon-
figuracji maszyny PHP wprowadziæ wpis:
error_reporting = E_ALL | E_STRICT
który spowoduje drukowanie komunikatów diagnostycznych w przy-
padku stosowania konstrukcji PHP4. Niestety, sta³a E_ALL nie obej-
muje nowo wprowadzonej wartoœci E_STRICT. St¹d koniecznoœæ po-
wy¿szej modyfikacji.
Specyfikatory dostępu
Specyfikatorem dostêpu jest jedno ze s³ów kluczowych: public, protec-
ted oraz private. S³owa te umieszczamy bezpoœrednio przed definicj¹
metody lub pola (w przypadku definicji pola pomijamy wówczas
s³owo kluczowe var).
Pisz¹c:
class A {
private $pole1;
protected $pole2;
public $pole3;
var $pole4;
private function fun1()
{
}
protected function fun2()
{
}
public function fun3()
{
}
function fun4()
{
}
}
zdefiniujemy klasê A o czterech polach i czterech metodach.
Pole $pole3 oraz metoda fun3() s¹ sk³adowymi publicznymi.
Do sk³adowych publicznych obiektu mo¿emy odwo³ywaæ siê
z dowolnego miejsca w skrypcie. W jêzyku PHP w wersji 4
wszystkie sk³adowe mia³y zawsze zasiêg publiczny. Ze wzglêdu
na zgodnoœæ w dó³, pominiêcie specyfikatora dostêpu w stosunku
do metody oraz u¿ycie s³owa kluczowego var w odniesieniu do
pola dzia³a w PHP5 w identyczny sposób jak w PHP4. Tak dekla-
rowane sk³adowe (w powy¿szej klasie s¹ nimi $pole4 oraz fun4())
maj¹ zasiêg publiczny. W przypadku w³¹czenia komunikatów
E_STRICT, parser PHP5 drukuje komunikat o stosowaniu prze-
starza³ych rozwi¹zañ (tj. stosowaniu s³owa kluczowego var; defi-
niowanie metod bez podawania specyfikatora dostêpu nie generu-
je komunikatów E_STRICT).
Sk³adowe $pole1 oraz fun1() s¹ sk³adowymi prywatnymi. Sk³ado-
we o dostêpie prywatnym s¹ widoczne jedynie wewn¹trz metod danej
klasy. Zatem do pola $pole1 oraz metody fun1() z powy¿szego przy-
k³adu mo¿emy odwo³ywaæ siê jedynie wewn¹trz metod fun1(), fun2(),
fun3() oraz fun4() pisz¹c:
$this->pole1 = ’ble’;
$this->fun();
Ka¿de odwo³anie do pola $pole1 lub metody fun1() nie poprzedzo-
ne referencj¹ $this jest b³êdne.
Natomiast sk³adowe o zasiêgu protected, nazywane chronionymi
(w przyk³adzie: $pole2 i fun2()), s¹ dostêpne wewn¹trz klasy (tak jak
sk³adowe prywatne) oraz wewn¹trz klas dziedzicz¹cych.
Konstruktory i destruktory
Definicja konstruktora w PHP4, wprawdzie nie zalecana, ale ci¹gle
pozostaje zachowana w PHP5. W celu u³atwienia wprowadzania
zmian w nazwach klas, konstruktorem w PHP5 jest metoda o zarezer-
wowanej nazwie _construct(). W ten sposób zmiana nazwy klasy nie
poci¹ga za sob¹ ¿adnych dodatkowych zmian w kodzie skryptu. Pozo-
sta³e cechy i zachowanie konstruktora (tj. automatyczne wywo³ywanie
podczas tworzenia instancji obiektów) pozostaj¹ niezmienione. Kon-
struktor jest zazwyczaj (poza specyficznymi przypadkami, na przyk³ad
obiektów typu singleton) metod¹ publiczn¹.
Oczywiœcie w klasie nie nale¿y definiowaæ dwóch konstrukto-
rów: jednego zgodnego z PHP4, drugiego – z PHP5. W takim przy-
padku wyniki dzia³ania kodu bêd¹ zale¿ne od wersji PHP. W PHP5
konstruktorem bêdzie metoda _construct(), zaœ w PHP4 – metoda
o nazwie identycznej jak klasa. W przypadku pojawienia siê w kla-
sie obydwu konstruktorów parser PHP5 generuje komunikat
E_STRICT. Natomiast stosowanie w PHP5 konstruktorów z PHP4
nie powoduje drukowania komunikatu E_STRICT – programista
musi sam o tym pamiêtaæ.
Podsumowuj¹c, w jêzyku PHP5 konstruktor mo¿emy definiowaæ
na dwa sposoby: jako metodê o nazwie _construct() lub jako metodê
o nazwie identycznej jak nazwa klasy. Zalecanym rozwi¹zaniem jest
stosowanie metody _construct().
Dodatkowo w PHP5 po raz pierwszy pojawia siê pojêcie destrukto-
ra. Destruktorem jest metoda o nazwie _destruct(). Jest ona wywo³y-
wana automatycznie, gdy obiekt przestaje istnieæ.
Klasa MenuWierszy w PHP5
Wprowadzaj¹c do klasy MenuWierszy podane rozszerzenia po pierw-
sze zmodyfikujemy nazwê konstruktora, a po drugie dodamy specyfi-
katory dostêpu do pól i metod. Wszystkie pola klasy bêd¹ polami pry-
watnymi, zaœ metody – metodami publicznymi.
Klasa MenuWierszy po wprowadzeniu elementów dostêpnych
w PHP5 zosta³a zawarta na listingu 3
.
Skrypt g³ówny strona.php zawieraj¹cy tworzenie instancji oraz wy-
wo³anie metod getMenu() i getTresc() nie ulegnie zmianie.
Z racji na zgodnoœæ w dó³ oba przyk³ady zawieraj¹ce klasê Menu-
Wierszy zostan¹ poprawnie wykonane przy u¿yciu PHP w wersji 5.
Natomiast tylko pierwsze z rozwi¹zañ (bez u¿ycia specyfikatorów do-
stêpu) zostanie poprawnie wykonane w PHP4.
Tabela 1
zawiera sumaryczne zestawienie podstawowych
zagadnieñ dotycz¹cych programowania obiektowego w PHP z za-
znaczeniem ró¿nic pomiêdzy wersjami 4 oraz 5. Natomiast tabela 2
zawiera przyk³ady ilustruj¹ce wszystkie omówione do tej pory
zagadnienia.
n
Ćwiczenia przedstawione w artykule są dostępne na stronie domowej
autora pod adresem
http://www.gajdaw.pl.
PHP
INTERNET.listopad.2005
105
WEBMASTERING
PROGRAMY
MAGAZYN
FIRMA
Z OK£ADKI
NEWSY
NA CD
C
M
Y
K
UWAGA!
Dwie pozostałe części tego artykułu,
wraz z listingami i przykładami,
są dostępne na płycie CD oraz w naszym
serwisie internetowym: www.mi.com.pl