Programowanie obiektowe bez wątpienia ma wiele zalet, najważniejsze z nich to łatwe modyfikowanie oraz wielokrotne wykorzystania klas. W tym artykule pokaże jak korzystać z możliwości PHP, aby tworzyć funkcjonalne a za razem bardzo rozbudowane klasy.
UWAGA, jeżeli jeszcze nie wiesz czym jest OOP, przeczytaj najpierw artykuł „obiekty w PHP”, ponieważ tutaj nie będziemy zajmować się podstawową składnią.
Rozpoczniemy od zdefiniowania klasy zwierze, która będzie naszą oraz będzie punktem wyjścia do dalszej rozbudowy.
class zwierze { var $gatunek; function zwierze($gatunek) { function typowyDzien($jedzenie) { |
Jak widać klasa składa się z jednej zmiennej, konstruktora oraz trzech prostych metod, chyba nie ma czego tutaj tłumaczyć, jeżeli znasz już podstawy programowania obiektowego.
Teraz stworzymy klasę tygrys, która będzie dziedziczyć metody i zmienne z klasy bazowej zwierze, w tym celu przy definicji obiektu użyjemy słowa kluczowego extends.
class tygrys extends zwierze {…} |
Ten zapis czytamy tak: ‘Klasa tygrys jest rozszerzeniem klasy ‘zwierze’, można powiedzieć, że jest to stwierdzenie jak najbardziej poprawne, ponieważ klasa zwierze posiada metody wspólne dla wszystkich zwierząt, natomiast tygrys jako, że również jest zwierzęciem będzie posiadał te metody plus funkcje specyficzne dla wszystkich tygrysów. Skoro tak to zdefiniujmy jakąś metodę.
function poluje($ofiara) { echo $this->gatunek.” poluje na „.$ofiara.”<br>”; } |
Nasuwa się jednak pytanie, a co jeśli zachodzi potrzeba użycia metody z klasy bazowej wewnątrz klasy potomnej? Na szczęście, PHP posiada mechanizm pozwalający na wykonywanie takich operacji, ogólny wzór ma postać: parent::nazwaMetody(), słowo parent oznacza rodzica czyli w naszym przypadku klasę zwierze, oczywiście zamiast słowa parent można wpisać nazwę klasy bazowej, ale jest to nie zalecane, chociażby ze względu na to, że gdy zmieni się nazwa klasy bazowej, klasę pochodna trzeba będzie zmieniać w kilku miejscach. Dopiszmy jeszcze jedna metodę do „tygrysa”, jak się pewnie domyślasz użyjemy w niej słowa kluczowego parent.
function typowyDzien($jedzenie, $ofiara) { parent::typowyDzien($jedzenie); $this->poluje($ofiara); } } |
Co ciekawe w każdej klasie mamy teraz metodę o nazwie typowyDzien, z wnętrza klasy tygrys mamy dostęp do obydwóch funkcji, jednak z zewnątrz tylko do jednej, dzieje się tak dlatego, że PHP pozwala na overloading metod, to znaczy, że metode z klasy bazowej można nadpisać nową funkcją. Zobaczmy teraz jak to wszystko działa i czy w ogóle działa.
$a = new tygrys(„Tygrys”); $a->typowyDzien(„padline”, „jelenia”); /* wyswietli |
Okazuje się, że wszystko jest w porządku, zauważmy jednak, że nasz tygrys nie posiada konstruktora, tymczasem wywołujemy go z jednym parametrem (new tygrys(„Tygrys”);). Przyczyna jest dość prosta, w PHP obiekt jest tworzony wraz z konstruktorem z klasy bazowej o ile nie posiada własnego, a więc gdyby w naszej klasie potomnej dopisać konstruktor byłby on używany domyślnie, innymi słowy PHP używa najnowszego konstruktora.
Obiekty w PHP tworzą spójną całość i trudno sobie wyobrazić, aby istniały one jako osobne funkcje, aczkolwiek istnieje taka możliwość, spróbujmy wywołać którąś z metod w podobny sposób jak poprzednio z tym, że zastąpimy słowo patent nazwą klasy (oczywiście zapisujemy to poza klasą, nie w jej wnętrzu).
zwierze::spij(); // wyświetli: zwierze spi tygrys::poluje(‘inne zwierze’); // wyświetli: poluje na inne zwierze |
Metoda została wywołana poprawnie, ale nie posiada ona żadnych zmiennych i nie może komunikować się z innymi metodami, co więcej nie został utworzony żaden nowy obiekt, dlatego też słowo ‘Tygrys’ z poprzedniego przykładu zostało zastąpione domyślnym słowem ‘zwierze’.
Czasem chcielibyśmy wykorzystać zmienne obiektu na następnej stronie, ale jak wiadomo zaraz po kliknięciu w dowolny link wszystkie dane są usuwane, twórcy PHP przewidzieli taką sytuacje i udostępnili programistą dwie nowe funkcje: serialize() i unseriaze(). Pierwsza z nich służy do serializacji zmiennych (czyli zapisania ich w postaci ciągu znaków), natomiast druga funkcja odtwarza zmienne. Jeśli używasz sesji i session_register() do rejestracji obiektów, te obiekty są serializowane automatycznie na końcu każdej strony PHP i odserializowane automatycznie na każdej z następnych stron. Zasadniczo znaczy to, że te obiekty mogą pokazać się na dowolnej z twoich stron jeśli tylko staną się częścią twojej sesji. Na koniec zrobimy sobie przykład, ale najpierw trzeba przenieść klasy do jednego pliku.
// -> class.php: class zwierze { // tutaj zawartość calej klasy zwierze } class tygrys extends zwierze { // zawartość klasy tygrys } // -> page1.php: // -> page2.php: |
Najpierw należy otworzyć page1.php, a następnie przejść na stronę page2.php, na ekranie powinien pokazać się napis ‘Tygrys poluje na jelenia’, pomimo, że w pliku page2.php nie napisaliśmy.
$a = new tygrys(‘Tygrys’);
Również dobrym pomysłem jest przechowywanie obiektu w bazie danych, algorytm postępowania jest taki sam, najpierw serializujemy i zapisujemy obiekt, a następnie wyciągamy z bazy i odtwarzamy zmienne. Skoro jesteśmy przy serializacji obiektów to warto wspomnieć, że w PHP istnieją dwie magiczne funkcje: _sleep() i _wakeup(). Pierwsza z nich jest wywoływana automatycznie przed każdą serializacją obiektu, jeżeli oczywiście, zdefiniujemy w swojej klasie metodę _sleep(), może ona posłużyć do zamknięcia połączenia z bazą danych lub plikiem. Funkcja _wakeup() działa odwrotnie, to znaczy jest uruchamiana przed odtworzeniem wartości.
Na pewno każdy programista docenia zalety programowania obiektowego, problem w tym ,że nie każdy potrafi je dobrze zastosować, jeśli Ty również masz ten problem to mam nadzieje, że ten artykuł choć trochę rozjaśni Ci sytuację, a także wzbogaci Twoją wiedzę na temat PHP i pozwoli na stworzenie naprawdę potężnych klas.