Funkcja jest kawałkiem kodu, który można wywołać podając jej nazwę. Już wcześniej podane zostało kilka funkcji dostarczanych przez PHP, takich jak array(), each(), list(), explode() czy implode(). Jak można zauważyć, funkcje rozpoznaje się po nawiasach występujących po ich nazwie. W nawiasach tych (jeśli funkcja tego wymaga) podaje się parametry dla danej funkcji. Niektóre funkcje zwracają jakąś wartość, a więc wywołanie takiej funkcji można wstawić jak dowolne inne wyrażenie do listy parametrów innej funkcji czy np. do obliczenia.
Programista może też tworzyć własne funkcje.
Przykład 6.1. Definicja funkcji
<?php function suma($parametr1 = 0, $parametr2 = 0) { $wartosc = $parametr1 + $parametr2; return $wartosc; } ?>
Jak widać, definiowana jest funkcja o nazwie suma. Służy ona do obliczania sumy dwóch wyrażeń podawanych jako parametry (kolejne parametry oddziela się przecinkiem). W przypadku pominięcia któregoś z parametrów przypisana mu będzie wartość 0 – dzieje się tak dzięki zaznaczeniu ” = 0″ po określeniu nazwy parametru w definicji funkcji (nie jest to konieczne). Z parametrów funkcji można korzystać jak z dowolnej innej zmiennej, ale oczywiście tylko wewnątrz tej funkcji. Wewnątrz funkcji dostępne są tylko zmienne w niej definiowane i parametry. Można się dostać też do innych zmiennych, ale o tym w punkcie „Zasięg zmiennych”. Do określania co jest zwracane przez funkcję służy instrukcja return. Może ona być wywołana w dowolnym miejscu funkcji – po dojściu do tej instrukcji kończy się wykonanie funkcji.
Funkcja może nie zwracać żadnych wartości. Taka funkcja przydaje się jeśli często powtarzany jest jakiś fragment kodu. Taka funkcja kończy swoje wykonanie po dojściu do końca jej definicji lub instrukcji return (tym razem wywoływanej bez parametru, ponieważ funkcja nie zwraca żadnych wartości).
Funkcje w PHP nie mogą być ponownie definiowane. Mogą być definiowane w zasadzie w dowolnym miejscu kodu. Wewnątrz funkcji znajdować się może dowolny, prawidłowy pod względem składniowym kod – nawet definicje innych funkcji czy klas.
Klasy są ściśle związane z pojęciem obiektowych zasad pisania aplikacji. Jeśli ktoś nie spotkał się jeszcze z taką koncepcją, to postaram się ją objaśnić w kilku zdaniach. Obiekt, tak jak w rzeczywistości, posiada swoje właściwości i można z nim zrobić różne rzeczy. Klasa nie jest obiektem, ale jego definicją (np. klasą jest kamień, ale nie jego konkretny egzemplarz). Definicja klasy zawiera zmienne (właściwości obiektu) i funkcje (rzeczy, które można zrobić z tymi obiektami). Za pomocą takiej konwencji programistycznej czasem można łatwiej i naturalniej opisać interakcje między obiektami. Oto jak się definiuje przykładową klasę i przykładowe działania na niej – jako że to tylko przykład to i klasa nie jest zbyt ambitna.
Przykład 6.2. Przykład definicji klasy
<?php // Początek definicji klasy Koszyk - definiującej koszyk sklepowy class Koszyk { // Definicja zmiennej - tablicy asocjacyjnej zawierającej numery artykułów i // ich ilość var $artykuly; // Metoda dodająca podaną ilość artykułów do koszyka function dodaj($numer, $ilosc) { $this->artykuly["$numer"] += $ilosc; } // Metoda usuwająca podaną ilość artykułów z koszyka function usun($numer, $ilosc) { if($this->artykuly["$numer"]>$ilosc) $this->artykuly["$numer"]-=$ilosc; else $this->artykuly["$numer"]=0; } // Metoda wyświetlająca zawartość koszyka function wyswietl() { while(list($k, $v) = each($this->artykuly)) if($v>0) echo "Artykul nr $k - $v sztuk<br>"; } } // Przykład wykorzystania $koszyk = new Koszyk; $koszyk->dodaj('20', 2); $koszyk->dodaj('12', 4); $koszyk->dodaj('20', 5); $koszyk->usun('12', 4); $koszyk->wyswietl(); ?>
Jak widać na załączonym przykładzie, aby dostać się do zmiennej lub funkcji będącej składową klasy należy użyć operatora „->”. Wewnątrz funkcji należącej do klasy zmienna $this oznacza właśnie ten obiekt – należy używać go chcąc odwołać się do zmiennej lub funkcji należącej do klasy.
W obiektowej koncepcji programowania znajduje się takie pojęcie jak dziedziczenie. Jako że w PHP obiektowość jest bardzo uboga, tak więc i dziedziczenie jest bardzo uproszczone. Ogólnie rzecz mówiąc dziedziczenie służy do tworzenia nowych klas na podstawie innych, rozszerzając ich możliwości. Do naszej klasy można dodać nowy atrybut – nazwę właściciela (zakładam, że przed podanym listingiem w pliku znajduje się definicja klasy Koszyk).
Przykład 6.3. Przykład dziedziczenia
<?php class Nazwany_koszyk extends Koszyk{ var $nazwa; function ustaw_nazwe($nowa_nazwa) { $this->nazwa = $nowa_nazwa; } } $koszyk = new Nazwany_koszyk; $koszyk->ustaw_nazwe('Fredzio'); $koszyk->dodaj('2', 34); echo 'Właściciel: '.$koszyk->nazwa.'<br/>'; $koszyk->wyswietl(); ?>
Kolejnym pojęciem z zakresu obiektowości jest konstruktor. Konstruktor jest to funkcja o takiej samej nazwie jak klasa, która ustala początkowe wartości zmiennych (wywoływana jest automatycznie przy tworzeniu obiektu). Konstruktorowi można podać pewne wartości przy tworzeniu obiektu. Oto kolejna wersja koszyka wyposażona w konstruktor, który ustawia nazwę właściciela na podaną lub „Anonim” jeśli jej nie podano:
Przykład 6.4. Zastosowanie konstruktora
<? class Auto_koszyk extends Nazwany_koszyki { function Auto_koszyk( $nazwa = 'Anonim') { $this->ustaw_nazwe($nazwa); } } $koszyk = new Auto_koszyk('Jakiś właściciel'); $koszyk->dodaj('4', 30); echo 'Właściciel: '.$koszyk->nazwa.'<br/>'; $koszyk->wyswietl(); ?>
W PHP istnieją dwie instrukcje, które pozwalają włączyć do kodu zawartość innego pliku także zawierającego kod PHP. Obu tym instrukcjom podaje się jeden parametr – nazwę pliku do włączenia do kodu (może to być ścieżka do pliku znajdującego się na innym serwerze WWW). Różnica między nimi polega na sposobie włączania tych plików do kodu. W przypadku instrukcji require pliki dołączane są do kodu jeszcze przed parsowaniem, w każdym miejscu gdzie znajduje się instrukcja require. Dlatego instrukcja ta nie nadaje się do dołączania plików których nazwa pobierana jest ze zmiennej – zamiast tego należy użyć instrukcji include. Używając tych instrukcji należy pamiętać o dwóch rzeczach. Po pierwsze, przetwarzanie plików zaincludowanych zaczyna się od trybu HTML, a więc jeśli plik zawiera tylko kod PHP, to powinien zaczynać się od jednego ze znaczników otwierających. Po drugie należy pamiętać, że jeśli instrukcja include używana jest w pętli lub instrukcji warunkowej, to pomimo że jest to teoretycznie jedna linia, to musi znajdować się ona w nawiasach klamrowych, ponieważ ta pojedyncza linia zamieniana jest na wiele linii dołączanych z innego pliku.
Innym typem funkcji służącej do dołączania treści zawartych w innym pliku jest funkcja readfile(). Rzeczą odróżniającą tą funkcję od instrukcji zawartych w poprzednim punkcie jest to, że dane pobrane z pliku nie są przetwarzane przez PHP, więc funkcja ta nadaje się tylko do wyświetlania plików HTML bądź czysto tekstowych.
Przy korzystaniu z funkcji i klas pojawia się problem zasięgu zmiennych. Problem ten dotyczy większości języków programowania. Ogólnie mówiąc chodzi o to, że zmienne dostępne są zazwyczaj tylko w tym zasięgu, w którym zostały zdeklarowane. Przez zasięg rozumiem zasięg główny (to znaczy część kodu, która nie należy do żadnej funkcji lub klasy), klasy i funkcje.
Pomimo, że zmienna $a została zadeklarowana wcześniej, to nic się nie wyświetli, ponieważ zmienna $a nie jest dostępna wewnątrz funkcji. Dostęp do zmiennych globalnych można uzyskać na 2 sposoby. Po pierwsze, można powiadomić PHP że dana zmienna ma być pobierana z zasięgu głównego za pomocą instrukcji global.
W tym przykładzie zostanie wyświetlona prawidłowa wartość zmiennej $a. Istnieje też druga metoda dostania się do zmiennych globalnych. W każdym miejscu kodu dostępna jest tablica asocjacyjna $GLOBALS, której kluczami są nazwy zmiennych dostępnych w zasięgu głównym.
Istnieje jeszcze jeden aspekt dotyczący zasięgu zmiennych: zmienne statyczne.
Przykład 6.7. Zmienna statyczna
<? function aaa() { $a = 0; echo $a; $a++; } aaa(); aaa(); aaa(); ?>
Powyższy przykład jest w zasadzie bez sensu – za każdym razem wyświetlona będzie wartość 0, ponieważ za każdym wywołaniem funkcji zmienna $a będzie od nowa inicjowana wartością 0 a po wyświetleniu i inkrementacji tej zmiennej będzie ona niszczona (wszystkie zmienne inicjowane w funkcji oprócz statycznych są niszczone po wykonaniu się funkcji).
Przykład 6.8. Zmiana zasięgu zmiennej
<? function aaa() { static $a = 0; echo $a; $a++; } aaa(); aaa(); aaa(); ?>
Natomiast w tym przykładzie wyświetlone zostaną wartości 0, 1 i 2. Dzieje się tak, ponieważ mimo że zmienna jest inicjowana wartością 0, to dzięki instrukcji static dzieje się to tylko raz, a do tego po zakończeniu wykonywania się funkcji zmienna ta nie jest niszczona.
W PHP 4.1.0 wprowadzone zostały tak zwane tablice superglobalne. Są one tworzone przez PHP – użytkownik nie może samemu tworzyć takich tablic. Zawierają one dane przekazywane do PHP metodami GET, POST, informacje o przekazanych plikach, dane z ciasteczek i sesji – odpowiedno $_GET, $_POST, $_FILES, $_COOKIE, $_SESSION. Mają one zastąpić tablice $HTTP_*_VARS, które ze względu na kompatybilność są jeszcze obecne. Różnica między tablicami superglobalnymi a tymi używanymi wcześniej jest taka, że tablice superglobalne dostępne są w dowolnym miejscu kodu, bez potrzeby użycia instrukcji global.