Podstawy PHP

Adam Boduch

Wiesz już, czym jest PHP, czym charakteryzują się języki skryptowe oraz jak zainstalować PHP. Pewnie masz już gotowy serwer, przystosowany do programowania w PHP z wykorzystaniem MySQL. Zajmijmy się podstawową składnią PHP, konstrukcją prostych skryptów.

     1 Skrypty PHP
          1.1 Pobieranie PHP
     2 Pierwszy program
          2.2 Otwieranie i zamykanie tagów PHP
     3 Instrukcje
          3.3 Instrukcja echo
          3.4 Długie łańcuchy znaków
          3.5 Smaczki echo
          3.6 Wyświetlanie kodu HTML
          3.7 Unikaj takiego łączenia PHP oraz HTML
     4 Komentarze
     5 Literały
          5.8 Literały tekstowe
          5.9 Literały liczbowe
          5.10 Literały logiczne
     6 Praca ze zmiennymi
          6.11 Przypisanie danych
          6.12 Odwołanie do zmiennej
     7 Stałe
     8 Typy danych
     9 Operatory
          9.13 Operatory inkrementacji i dekrementacji
          9.14 Operatory łańcuchowe
          9.15 Operatory przypisania
          9.16 Operatory arytmetyczne
          9.17 Zaokrąglanie
          9.18 Operatory porównania
          9.19 Operatory logiczne
          9.20 Operatory wykonania polecenia systemowego
          9.21 Operatory kontroli błędów
          9.22 Operatory bitowe
          9.23 Priorytety operatorów
     10 Instrukcje warunkowe
          10.24 Instrukcja if
          10.25 Blok instrukcji
          10.26 Instrukcja else
          10.27 Instrukcja elseif
          10.28 Operator trójoperandowy
          10.29 Instrukcja switch
               10.29.1 Problem ze switch
     11 Pętle
          11.30 Pętla while
          11.31 Pętla do..while
          11.32 Pętla for
          11.33 Pętle nieskończone
          11.34 Pętla for działająca w drugą stronę
          11.35 Pętla foreach
          11.36 Instrukcje continue i break
     12 Funkcje
          12.37 Parametry funkcji
          12.38 Parametry domyślne
          12.39 Zmienne lokalne
          12.40 Zakres zmiennej
          12.41 Czas życia zmiennej
          12.42 Funkcje zagnieżdżone
     13 Programowanie strukturalne
          13.43 Włączanie modułów w ciało funkcji
     14 Operacje na łańcuchach
          14.44 sprintf()
          14.45 strToLower(), strToUpper()
          14.46 trim()
          14.47 strLen()
          14.48 chr(), ord()
          14.49 str_replace()
          14.50 strstr()
          14.51 substr()
          14.52 strpos()
     15 Referencje
          15.53 Przekazywanie przez referencje

Składnia to specyficzne dla języka słowa, znaki, które są analizowane przez parser. Składnia naszego programu musi podlegać pewnym standardom tak, aby parser rozpoznał instrukcje i zareagował zgodnie z ich przeznaczeniem.

Parser (inaczej analizator składniowy) to narzędzie, które analizuje składnie pliku.

Skrypty PHP

Skrypty PHP najczęściej posiadają rozszerzenie *.php i są tworzone przy pomocy dowolnego edytora tekstów. Skrypty PHP mogą być zwykłymi plikami, w których zagnieżdżone są instrukcje PHP.

Kiedy rozpoczniesz swoją przygodę z PHP, większość tutoriali oraz kursów z którymi się spotkasz, bez wątpienia, na pewno zaprowadzą Cię w stronę aplikacji PHP od razu z serverem przeglądarkowym. Nie jest to zły pomysł dla zaawansowanych programistów, ale dla początkujących już bardzo. Dlaczego? Ano dlatego, że wtedy będziesz musiał się uczyć trzech rzeczy na raz, to znaczy samego PHP, HTMLa, dlatego że Twoja jedyna interakcja z PHP będzie poprzez przeglądarkę, oraz HTTP, czyli protokołu którym serwer prozumiewa się z Twoją przeglądarką. Dodatkowo, sprawa ma się o tyle gorzej, że większość kursów z którym się spotkasz, nie będzie rozróżniało PHP, od HTMLa i HTTP. Spotkasz się więc z kodem w którym w jednej i tej samej linijce możesz spotkać PHP, wymieszanego z HTMLem i HTTP, zmiksowane w taki sposób że nie będziesz wiedziało co chodzi!

Dlatego dobrym pomysłem jest najpierw zacząć od samego tylko PHP, bez stron internetowych i bez przeglądarki. Żeby to zrobić, zamiast ściągąć Server typu LAMP/WAMP/Apache, wystarczy że pobierzesz samego tylko PHP.

Pobieranie PHP

Wersje PHP dla Linuxa oraz instalatory na Windowsa są dostępne do pobrania ze strony php.net: https://www.php.net/downloads.php

Kiedy już zainstalujesz PHP, upewnij się że jest on dostępny z poziomu linii poleceń. Uruchom swój ulubiony terminal (cmd, bash, powershell, etc.) i wpisz:

php -v

Powinieneś zobaczyć coś takiego

$ php -v
PHP 8.0.1 (cli) (built: Dec 11 2019 19:55:07)
Copyright (c) 1997-2021 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2009 Zend Technologies

Jeśli zobaczysz wersję PHP, to znaczy że udało się go zainstalować :)

Pierwszy program

Parser PHP wykonuje kod, który znajduje się pomiędzy instrukcjami <?php i ?>. Pozostały tekst, jest po prostu wypisywany. Stwórz nowy plik w dowolnym folderze, o nazwie test.php, o następującej treści:

Trzy razy trzy jest <?php echo 3 * 3; ?>! :)

Następnie uruchom program w PHP z poziomu linii poleceń. Jeśli stworzyłeś swój plik na pulpicie wykonaj poniższy kod, żeby przejść do odpowiedniego folderu:

cd Desktop/
# lub
cd Pulpit/

i uruchom program:

php test.php

Powinieneś zobaczyć wynik programu, czyli:

Trzy razy trzy jest 9! :)

Instrukcja echo umożliwia wyświetlenie tekstu. Równie dobrze można wykorzystać instrukcje `print, która jest z pewnością znana osobom programującym wcześniej w Perlu.

Zamiast znaczników <?php, ?> informujących o rozpoczęciu kodu PHP, można stosować ich skrócone wersje:

Trzy razy trzy jest <? echo 3 * 3; ?>

Taki zapis będzie działał tylko wtedy, gdy włączona została opcja short_open_tag, w konfiguracji PHP, np w pliku php.ini lub przez dynamiczne opcje. Opcja short_open_tag jednak jest domyślnie wyłączona.

Uwaga! Opcja asp_tags jest domyślnie wyłączona!

Otwieranie i zamykanie tagów PHP

Treść kodu źrodłowego zanim otworzysz tag PHP, lub zaraz po tym jak go zamkniesz, jest po prostu wyświetlana.

Dwa programy zaprezentowane poniżej działają w dokładnie taki sam sposób:

  • Trzy razy trzy jest <? echo 3 * 3; ?>! :)
    
  • <?php
    echo 'Trzy razy trzy jest ' . (3 * 3) . '! :)`;
    ?>
    

Dokładniej mówiąc, zapis Trzy razy trzy jest <? echo 3 * 3; ?>! :) można interpretować tak:

<?php echo 'Trzy razy trzy jest ';?><? echo 3 * 3; ?><? echo '! :)';?>

Niemniej, jednoczesne zamknięcie i od razu otwarcie taga PHP nie ma sensu, dlatego możemy uzyskać:

<?php  echo 'Trzy razy trzy jest '; echo 3 * 3; echo '! :)`; ?>

Instrukcje

Programowanie opiera się na stosowaniu instrukcji języka, czytelnych dla parsera. W większości języków programowania jest tak, że instrukcje muszą być oddzielone od siebie znakiem średnika ;. Przykład:

<?
echo 3 * 3; echo 4 * 3; 
?>

W powyższym przykładzie mamy do czynienia z dwoma instrukcjami echo. Pierwsza z nich wypisze wynik mnożenia 3 razy 3, a druga wynik mnożenia 4 razy 3. Po uruchomieniu takiego skryptu, ujrzymy liczbę 912. Pytanie: skąd ona tam się wzięła? Zwyczajnie jest to zlepek dwóch liczb: 9 i 12 - wyników mnożenia. Z punktu widzenia parsera nie ma znaczenia czy umieścimy obie instrukcje jedna pod drugą, czy obok siebie. Tak więc oba wywołania są sobie równe:

<?
echo 3 * 3;
echo 4 * 3;
?>
<?
echo 3 * 3;echo 4 * 3;
?>

Ze względu na czytelność kodu, zalecana jest pierwsza metoda, czyli zapisywanie instrukcji jedna pod drugą.

Naturalnie nie ma także znaczenia liczba spacji, odstępy między instrukcjami, wszystko to jest akceptowane przez parser. W związku z tym poniższy skrypt zostanie wykonany poprawnie:

<?
echo(3*3);
echo 4    * 10;
echo(
      76
      *
      3);      
?> 

Co ciekawe jeżeli wewnątrz znaczników <?, ?> znajdzie się jedna instrukcja, to nie jest konieczne zakończenie jej znakiem średnika ;, np.:

<? echo 2 + 2 ?>

Instrukcja echo

Instrukcja języka PHP echo umożliwia wyświetlenie tekstu. Ponieważ język PHP jest bardzo elastyczny (w przeciwieństwie do np. Delphi/Pascal), instrukcji echo można używać na wiele sposobów. Przyjrzyjmy się przez moment nad zastosowaniem tej instrukcji.

Instrukcja echo umożliwia wyświetlanie, nie tylko liczb, wyniku działań matematycznych, ale także - co chyba najważniejsze - tekstu. Tekst należy jednak ująć w apostrofy lub cudzysłowy:

<?php
echo "Hello World!";
echo 'Hello World!';
?>

Obie instrukcje przedstawione wyżej są równoważne. Jeżeli chodzi o nawiasy, to służą one do grupowania operatorów, tak samo jak w matematyce. Np działanie 2 + 4 * 4, daje inny wynik niż (2 + 4) * 4, właśnie przez nawiasy. Czasem jednak, dodanie nawiasów nic nie zmienia, jak np. dla działania 2 + 4 * 4, dodanie nawiasów 2 + (4 * 4) pozostawi działanie w takim samym stanie. Podobnie jest z ciągami znaków, "One" . "Two" jest równoważne z ("One". "Two"), połączenie znaków zostanie potraktowane tak samo w obu przypadkach, nawias nie był tam potrzebny, jednak nie jest zabroniony. Zauważ, że do łączenia ciągów znaków używamy . w PHP, natomiast do dodawania liczb używamy +.

<?php
echo (
  "Hello World!"
);
  
echo ( 'Hello World!' );
?>

Ja jednak, w tej książce będę korzystał z wywołania bezdodatkowych nawiasów:

<?php
echo 'Hello World!';
?>

Długie łańcuchy znaków

Podsumujmy: jeżeli chcemy wyrazić tekst w języku programowania (np celem jego wyświetlenia), musimy zawrzeć go w apostrofach lub cudzysłowach. Taka konstrukcja nazywa się "łańcuchem znaków" (ang. string (of characters)). Często możesz się spotkać z wypowiedzią: Wyświetlam łańcuch... Teraz będziesz już wiedział, że chodzi tutaj o tekst zawarty w apostrofy lub cudzysłowy.

W PHP nic nie stoi na przeszkodzie, aby łańcuch zapisać w kilku liniach ? np.:

<?php
echo '
    To jest łańcuch, który nie mieści się w jednej linii, więc
    trzeba zapisać go w dwóch linijkach.
';
?>

Należy jednak pamiętać o zakończeniu łańcucha! Np. poniższa instrukcja zostanie źle zinterpretowana:

<?php
echo "
    To jest łańcuch, który nie mieści się w jednej linii, więc
    trzeba zapisać go w dwóch linijkach.
';
?>

Wszystko dlatego, że tutaj łańcuch rozpoczyna się od znaku cudzysłowie, a kończy apostrofem! Podczas próby wykonania takiego skryptu PHP wyświetli błąd:

Parse error: parse error, unexpected $end. 

Istnieje jeszcze jedna, mniej popularna metoda zapisywania długich łańcuchów, nazywana NOWDOC:

<?
echo <<<END
To jest łańcuch, który nie mieści się w jednej linii, więc
trzeba zapisać go w dwóch linijkach.
END;
?>

Działa pod warunkiem, iż łańcuch rozpocznie się i zakończy tym samym słowem - w tym wypadku END. Nie jest to jednak metoda często spotykana. Taki zapis jest zaczerpnięty z języka Bash, gdzie był częściej używany w poleceniach i skryptach powłoki. PHP jest mocno inspiryowany wieloma językami jak Bash, C++, Java, C#, Dos oraz Lisp, więc często można spotkać elementy z tych języków w samym PHP, są jednak z reguły używane dość żadko.

Teraz, drogi czytelniku możesz zauważyć pewną różnicę. Jeśli uruchamiasz skrypt jedynie w PHP, tekst który zobaczysz jest tożsamy z tekstem który znajduje się w kodzie źródłowym Twojego skryptu. Gdybyś jednak korzystał z innego tutoriala, w którym korzystanoby również z servera, przeglądarki i aplikacji webowej, zauważyłbyś że Twój wyświetlony tekst zachowuje się inaczej niż ten który masz w swoim skrypcie. Dzieje się tak przez specyfikę HTML'a, oraz tego w jaki sposób HTML renderuje tekst. Podczas korzystania z samego PHP nie musisz się tym w ogóle martwić. Dołączymy HTML do naszej aplikacji w późniejszej części. Na razie ważne jest jedynie to, żebyś skupił się tylko na języku PHP, a nie na innych, niezależnych od niego rzeczach jak specyfika HTMLa.

Smaczki echo

<?php
echo "Adam", "Boduch";
?>

Powyższa instrukcja spowoduje wyświetlenie ciągu "AdamBoduch". Dwie części łańcucha oddzieliłem od siebie przecinkiem, lecz Ty nie będziesz pewnie stosował takiej konstrukcji zbyt często. Te informacje podaje raczej jako ciekawostkę.

Wyświetlanie kodu HTML

Instrukcje PHP mogą, i często są zagnieżdżane wewnątrz kodu HTML. Dzięki temu ich autorzy stworzyć dynamiczną stronę, ale i także skorzystać z formatowania HTML w celu upiększenia strony. Przykład:

<html>
<head>
<title>Skrypt PHP</title>
</head>

<body>
<p>2 + 2 jest <b><? echo 2 + 2 ?></b></p>
</body>
</html> 

Dzięki temu rezultat dodawania 2 do dwóch będzie pogrubiony (dzięki zastosowaniu znacznika <b>). Nic nie stoi na przeszkodzie, aby taki sam rezultat osiągnąć wyświetlając kod HTML poprzez instrukcję echo:

<?php
echo "<html>";
echo "<head>";
echo "<title>Skrypt PHP</title>";
echo "</head>";
echo "<body>";
echo "<p>2 + 2 jest <b>";
echo 2 + 2;
echo "</b></p>";
echo "</body>";
echo "</html>";
?>

Ale, do czego zmierzam? Otóż jak zapewne Ci wiadomo, znaczniki HTML mogą posiadać parametry, które należy zapisać w cudzysłowie. Przykładowo, chcemy, aby znacznik <p> posiadał parametr style. W takim wypadku naturalnym byłoby zastosowanie takiego kodu:

echo "<p style="margin: 10">2 + 2 jest <b>";

Parser PHP napotykając znak cudzysłowia, uzna, że jest to koniec łańcucha. Wykonanie takiego skryptu zakończy się komunikatem błędu

Parse error: parse error, unexpected T_STRING, expecting ',' or ';'. 

Pamiętaj! Jeżeli chcesz, aby znak " stanowił część łańcucha musisz poprzedzić go znakiem backslasha (\ ) w taki oto sposób:

echo "<p style=\"margin: 10\">2 + 2 jest <b>";

Innym rozwiązaniem jest użycie apostrofów zamiast cudzysłowie. W łańcuchach ograniczonych apostrofem może znajdować się znak ":

echo '<p style="margin: 10">2 + 2 jest <b>';

Unikaj takiego łączenia PHP oraz HTML

Prawdą jest, że PHP został przystosowany do łatwego integrowania go z HTML, przez to że większość ludzi i programistów (czasem łącznie z jego twórcami) uważali kod PHP oraz HTML za dwa podobne do siebie byty. Tak jednak nie jest - są to dwa zupełnie różne języki, nie mające ze soba nic wspólnego. Probówanie łączenia ich na siłę, może prowadzić do poważnych luk w bezpieczeństwie, bugów i innych nieprzyjemnych błędów.

Nie osadzaj kodu PHP w kodzie HTML, nie łącz też wywołać zapytań do bazy danych pomiędzy PHP a HTML.

Z mojego doswiadczenia wynika, że kod w którym w jednym miejscu mamy HTML, PHP oraz SQL jest tworzony jedynie przez amatorów; i ma dużo poważnych luk w bezpieczeństwie oraz błędów; podczas gdy kod tworzony przez zawodowców i ekspertów raczej nie jest połączony. Tzn mamy pliki PHP w którym jest dużo HTML, i mało (Albo najlepiej w ogóle) PHP, oraz inne w którym jest tylko PHP ale już bez HTMLa.

  • Ale chwila! Tak łatwo przecież połączyć HTML oraz PHP, i jest to przejżyste i czytelne!

  • Tak, na początku tak. Jeśli kodu HTML i PHP jest mało (np kilka linijek) to faktycznie jest to czytelne i proste. Jednak kiedy kodu przybywa (zarówno HTML, a z czasem i pewnie CSS oraz JavaScript; oraz PHP, a z czasem pewnie i SQL), wtedy zaczyna się to zamieniać w niesamowitą mieszaninę! Wymieszany HTML z JavaScript, CSS oraz PHP i SQL, razem również z kodem samej aplikacji, czasem jeszcze i obrazki i ikonki, albo zewnętrzne style i biblioteki! Koszmar! Dużo lepszym rozwiązaniem na dłuższą metę jest oddzielenie od siebie tych języków, ponieważ, prawdę mówiąc zostały one połączne na siłę.

  • Ale przecież tagi PHP <?php ?> są tak podobne do tagów HTML <b>.

  • Czyżby? Niestety, przykro mi ale nie są. Wydają się tak tylko, kiedy mamy ich niewiele, np kilka linijek, i kod HTML ani PHP nie jest skomplikowany.

Zrób sobie i innym autorom PHP przysługę, i nie łącz HTML'a oraz PHP. Jak więc wytwarzać dynamiczne strony HTML z użyciem PHP? Zobacz dedykowany artykuł specjalnie o tym: <To be added>

Komentarze

Komentarze są elementem składni obecnym w każdym języku programowania. Komentarze to sposób, aby zawrzeć w kodzie źródłowym własne przemyślenia, pomysły dotyczące kodu, czy też prawa autorskie. Komentarze są całkowicie ignorowane przez interpreter i nie mają wpływu na działanie programu.

Istnieje kilka sposób komentowania kodu. Najprostszym z nich jest komentarz jednej linii:

<?php
echo 'Hello World!'; // przywitanie
?>

Komentarz jednoliniowy rozpoczyna się od znaków // i obowiązuje do końca danej linii. To samo można osiągnąć stosując znak # (jest to komentarz obowiązujący w językach Perl oraz Python):

<?
echo 'Hello World!'; # przywitanie
// koniec skryptu
?>

Takie typy komentarzy obowiązują jedynie na długości jednej linii, więc by skomentować kilka linii, trzeba zwyczajnie napisać // przy każdej linii. Alternatyw jest stosowanie jeszcze jednego typu komentarzy, w stylu C++ i Javy, którego początek stanowią znaki /* a koniec znaki */:

<?php
/*
     początek komentarza 
     echo 'Hello World!';
     powyższa instrukcja nie zostanie wykonana
*/
?>

Literały

Pojęcie literału, w językach programowania oznacza wartość wpisaną w kod programu "na sztywno". "Literał" znaczy po prostu "dosłowny". Literałem jest łańcuch "Hello World", który wykorzystywałem nagminnie. PHP rozróżnia kilka podstawowych typów literałów: tekstowe, liczbowe, logiczne, kolekcje (np. array). Przyjrzyjmy się pokrótce każdemu z nich.

Literały tekstowe

Literały tekstowe to zwykłe napisy, łańcuchy tekstowe. Napisy można przedstawiać w apostrofach lub cudzysłowach.

Jeżeli tekst jest zamknięty w cudzysłowy, PHP przetwarza go w poszukiwaniu znaków specjalnych. Takimi znakami specjalnymi może być np. oznaczenie nowej linii (\n) lub znak tabulacji (\t). Spójrz na następujący skrypt:

<?php
echo "Pierwsza linia \n Druga linia \n Trzecia linia";
?>

Gdy uruchomisz taki skrypt zobaczysz, że jednak linie zostały zapisane jedna pod drugą:

Pierwsza linia 
 Druga linia 
 Trzecia linia

Gdybyś korzystał z innego tutoriala, który korzysta z podejścia PHP+HTML w przeglądarce, wpadłbyś w pułapkę, ponieważ HTML miesza używanie nowych linii. Pozostańmy więc przy samym PHP w linii poleceń.

Gdybyś zamiast cudzysłowie użył apostrofów, to znak nowej linii (\n) zostałby potraktowany jako zwykły tekst:

echo 'Pierwsza linia \n Druga linia \n Trzecia linia';

Po uruchomieniu program, w linii poleceń zobaczysz:

Pierwsza linia \n Druga linia \n Trzecia linia

Literały liczbowe

PHP obsługuje liczby całkowite oraz zmiennoprzecinkowe. Oto kilka przykładów wyświetlenia liczb:

<?php
echo 255;
echo 255.34;
echo ?255.45; // wartość ujemna
?> 

Ciekawostką jest fakt, że liczby całkowite można przedstawiać w notacji dziesiętnej, ósemkowej lub szesnastkowej. Instrukcja echo zawsze wypisze liczby całkowite w notacji dziesiętnej, więc poniższe instrukcje wypiszą liczbę 255:

<?php
echo 255; // dziesiętnie
echo 0xFF; // szesnastkowo
echo 0377;  // ósemkowo
?>

Literały logiczne

W wielu językach programowania obowiązują słowa kluczowe true oraz false. To są właśnie literały logiczne oznaczające prawdę (true) lub fałsz (false). Dla PHP nie ma znaczenia wielkość liter w słowach kluczowych, więc równie dobrze możesz napisać false, False czy FALSE. Wielkość liter ma jednak znaczenie w innych miejscach, np wielkościach liter w nazw zmiennych.

Praca ze zmiennymi

Zmienne to kolejny element języka dostępny praktycznie w każdym języku programowania. Stanowi on swoisty pojemnik na dane. W każdym momencie możemy użyć zmienną, przypisać jej dane, aby później owe dane odczytać.

Zmiennych w PHP używa się w bardzo prosty sposób, z użyciem znaku dolara ($):

<?php
$var = 2;
?>

Każda zmienna musi posiadać swoją nazwę. Nazwa zmiennej może składać się z dowolnych znaków alfanumerycznych, pod warunkiem, iż pierwszym znakiem nie będzie liczba. Nazwa zmiennej może składać się z polskich znaków, więc nic nie stoi na przeszkodzie deklaracji takiej oto zmiennej:

$_gżegżółka;

W przeciwieństwie do słów kluczowych, PHP odróżnia wielkość liter zmiennych tak więc $_gżegżółka oraz $_Gżegżółka będą stanowiły dwie odrębne zmienne.

Przypisanie danych

W poprzednich deklarowałem zmienne bez przypisania im konkretnych danych. Pomimo iż taka konstrukcja jest prawidłowa, PHP może wyświetlać wiadomość:

Notice: Undefined variable: _gżegżółka. 

Jeżeli programowałeś wcześniej w innych językach możesz być zaskoczony tym, że PHP nie wymaga określania typu dla zmiennej. Oznacza to, że jedna zmienna może zawierać dane w postaci liczbowej, tekstowej lub logicznej.

Zmienne są po to, aby przechowywać dane w pamięci. Przypisanie danych do zmiennej odbywa się przy pomocy operatora przypisania (=). Oto przykład:

<?
$var = 10;
$var = 'Tekst';
$var = true;
?>

Powyższy kod jest jak najbardziej poprawny. Na początek do zmiennej przypisujemy liczbę 10, później tekst, a końcu wartość logiczną true. Pamiętajmy jednak że takie mieszanie typów, podczas gdy jest możliwe i nie powoduje żadnych problemów z działaniem, tak może powodować problemy z czytelnością kodu albo jego późniejszym utrzymaniem. W prawdziwych projektach nie mamy zmiennych $var (nie ma potrzeby nazyważ zmiennej var, od "variable" - "zmienna"; ponieważ każdy programista PHP rozumie że element języka zaczynający się od $ to zmienna). Używamy zmiennych które opisują sens jej istnienia, np $user, $filePath, $accountCreationDate. Byłoby dziwne gdybyśmy stworzyli zmienną $fileSize = 1024; // 1 Kb, i potem przypisali do niej $fileSize = true;. Taki zapis jest możliwy, jednak z punktu widzenia czytelności kodu taki zabieg jest bardzo szkodliwy dla przejrzystości kodu. Jakbyś się poczuł gdybyś wyświetlił echo "Rozmiar pliku: $fileSize"; i zobaczył Rozmiar pliku: true"? :D

Istnieje również możliwość przypisania do zmiennej wartości pochodzącej z innej zmiennej:

<?
  $var1 = 'Napis...';
  $var2 = $var1;
?>

Takim oto sposobem posiadamy dwie zmienne ($var1, $var2), które mają taką samą wartość.

Odwołanie do zmiennej

Wyświetlenie wartości danej zmiennej jest bardzo proste. Realizuje się to przy pomocy instrukcji echo, tak samo jak z użyciem literałów:

<?
  $var = 'Napis...';
  echo $var;
?>
<?
  echo 'Napis...';
?>

Powyższe zapisy są ze sobą równoważne.

Zasada działania zmiennych jest stosunkowo prosta. Interpreter analizując kod źródłowy napotyka na linię, w której do zmiennej $var przypisujemy tekst "Napis...". Następnie sprawdza, czy taka zmienna ($var) już istnieje (ciekawskim wyjaśniam, że sprawdzany jest aktualny "scope"). Jeżeli nie, następuje "rezerwacja" komórki pamięci, do której przypisywana jest wartość zmiennej.

Interpreter zna adres komórki pamięci, w której zapisane zostały dane. Jeżeli chcemy wyświetlić zawartość danej zmiennej, PHP odwołuje się do danej komórki i pobiera z niej informacje. Po zakończeniu działania skryptu, pamięć zarezerwowana przez PHP jest automatycznie czyszczona.

Odwołanie do zmiennych może być także umieszczone w łańcuchu, pod warunkiem, że łańcuch jest tworzony przy pomocy cudzysłowia:

<?
$moje_imie = "Adam";
echo "Moje imię to $moje_imie"; // wyświetli: "Moje imię to Adam"
echo 'Moje imię to $moje_imie'; // wyświetli: "Moje imię to $moje_imie"
?>

W terminologii PHP nazywa się to "string interpolation".

Stałe

Stałe również wypełniają rolę "pojemnika" na dane, lecz w odróżnieniu od zmiennych nie można tych danych modyfikować w trakcie działania programu. Mają też szereg innych cech, np takich że można w nich jedynie umieścić wyrażenia znane w czasie uruchomienia programu, raz są dostępne w całej aplikacji, w tak zwanym "zakresie globalnym". Z tego powodu zaawansowani programiści raczej stosują je żadko lub wcale.

Stałe deklaruje się przy pomocy define():

  DEFINE('AUTOR', 'Adam Boduch');

lub za pomocą słowa kluczowego const:

const AUTHOR = 'Adam Boduch';

Pierwszym parametrem musi być nazwa stałej, a drugim - jej wartość. Podobnie jak w przypadku zmiennych, również stałe mogą przybierać wartości tekstowe, liczbowe czy logiczne.

Odwołanie do stałej jest dosyć proste, wystarczy prosty kod (z pominięciem znaku dolara):

echo AUTOR;

Przyjęło się że deklarując stałe używane są wielkie litery, ale oczywiście nie jest to ograniczenie PHP.

Typy danych

Pomimo tego, że PHP jest bardzo elastyczny, do jednej zmiennej możemy przypisać dowolne dane, to istnieje możliwość ustalenia typu wcześniej. Mimo, że PHP zwykle ustala typ danych na podstawie kontekstu (czyli wartości), możemy odczytać typ danej zmiennej lub ustalić go samodzielnie. Funkcja var_dump() wyświetla informacje na typu zmiennej. Przyjrzyj się poniższemu skryptowi:

<?
  $var = 10;
  var_dump($var); // wyświetli int(10)
  $var = 'string';
  var_dump($var); // wyświetli string(6) "string"
  $var = 2.4;
  var_dump($var); // wyświetli float(2.4)
  $var = true;
  var_dump($var); // wyświetli bool(true)
?>

W połączeniu z funkcją var_dump(), nie musimy używać instrukcji echo, ponieważ funkcja var_dump() sama zajmie się wyświetleniem informacji. Możemy także skorzystać z funkcji gettype() która zwraca typ danych znajdujących się w zmiennej:

<?
  $var = 10;
  echo gettype($var); // wyświetli integer
  $var = 'string';
  echo gettype($var); // wyświetli string
  $var = 2.4;
  echo gettype($var); // wyświetli double
  $var = true;
  echo gettype($var); // wyświetli boolean
?>

Operatory

Podczas eksperymentów z przykładami w tej książce, nie raz używałeś już operatorów. Jest to element języka służący do manipulacji danymi. Przykładowo operator + (dodawanie) służy do dodawania dwóch wartości. Operatorem jest także znak = (operator przypisania) który realizuje przypisanie danych z jednej zmiennej do drugiej. Operatory dzielą się na kilka kategorii:

*Operatory przypisania
*Operatory arytmetyczne
*Operatory porównania
*Operatory bitowe
*Operatory logiczne
*Operatory łańcuchowe
*Operatory inkrementacji i dekrementacji
*Operatory kontroli błędów
*Operatory wykonania systemowego

Pokrótce przyjrzyjmy się tym kategoriom.

Operatory inkrementacji i dekrementacji

Operatory inkrementacji oraz dekrementacji obecne są także w językach C/C++ oraz Java i stamtąd zostały one zaczerpnięte do PHP. Służą one szybkiemu zwiększaniu oraz zmniejszaniu wartości danej zmiennej:

  $i = 10;
  --$i; // wartość $i to 9

Zasada zastosowania jest prosta. W celu zmniejszenia wartości danej zmiennej wystarczy umieścić dwa znaki odejmowania (--) przed lub za nazwą zmiennej. Możliwe są, więc takie rozwiązania:

--$i; // zmniejsz o jeden
$i--; // zmniejsz o jeden
Tak samo działa operator inkrementacji (zwiększania):
++$i; // zwiększ o jeden
$i++; // zwiększ o jeden

Położenie operatorów inkrementacji i dekrementacji ma znaczenie. Konstrukcja ++$i nazywana jest pre-inkrementacją i najpierw zwiększa wartość zmiennej, a potem zwraca $i. Konstrukcja $i++ to post-inkrementacja - najpierw zwraca wartość $i a dopiero później zwiększa ją o 1. Najlepiej zaobserwować to na przykładzie:

<?
$i = 10;
  
echo $i++; // wyświetli 10 i zwiększy o jeden (do 11)
echo '<br>';
echo ++$i; // zwiększy o 1 i wyświetli 12
?>

Mam nadzieje, że to jest jasne. Tak samo ma się sprawa z dekrementacją. Tutaj także obowiązuje pre-dekrementacja oraz post-dekrementacja.

W rzeczywistości operator inkrementacji lub dekrementacji równy jest takiemu działaniu:

$i = $i + 1; // zwiększenie o 1
$i = $i ? 1; // zmniejszenie o 1

Operatory łańcuchowe

W PHP dostępne są dwa operatory działające na łańcuchach. Pierwszy z nich to operator połączenia, konkatenacji (.) który umożliwia połączenie dwóch łańcuchów danych:

<?php
$imie = 'Adam';
$nazwisko = ' Boduch';
echo $imie . $nazwisko;
?>

Powyższy skrypt wyświetli napis "Adam Boduch". Zwróć uwagę, iż wartość zmiennej $nazwisko rozpoczyna się od spacji, która po połączeniu dwóch łańcuchów jest zachowywana.

Drugi operator (.=) dokonuje połączenia łańcucha wraz z przypisaniem wartości z prawej strony do strony lewej:

<?
$a = 'Adam';
$a .= ' Boduch';
echo $a; 
?>

Rezultat wykonania takiego programu jest identyczny jak poprzednim przypadku. Fraza Boduch została "doklejona" na koniec frazy "Adam".

Operatory przypisania

Do tej pory miałeś okazję skorzystać z jednego z operatorów przypisania (=). Oznacza on to, iż zmienna znajdująca się po jego lewej stronie otrzymuje wartość znajdującą się po stronie prawej. Operator przypisania ma większe możliwości, połączenia z operatorami arytmetycznymi oraz łańcuchowymi, np.:

<?php
$i = 10;
$i += 10;
?>

Operator += powoduje zwiększenie wartości zmiennej o wartość znajdującą się po prawej stronie operatora. Dzięki zapisowi $i += 10 wartość zmiennej $i zostanie zwiększona o 10. Warto wspomnieć o możliwości skrótowego zapisu takiej operacji:

$i += 10;  # krótszy
$i = $i + 10; # dłuższy

Nic nie stoi na przeszkodzie zastosowania innych operatorów arytmetycznych w połączeniu z operatorem przypisania (o operatorach arytmetycznych nieco dalej):

<?php
$i = 10;
echo $i * 10; // wyświetli 100;
echo $i; // wyświetli 10
echo $i *= 10; // wyświetli 100
echo $i; // wyświetli również 100, ponieważ $i zostało powiększone w linijce wyżej
?>

Warto w tym momencie zaprezentować przykłady nieco bardziej skomplikowanych możliwości zastosowania operatorów, które także są jak najbardziej prawidłowe. Np.:

<?php
$i = 10;
echo $a = ($i *= 10) + 5;
?>

Przeanalizujmy działanie takiego kodu. W pierwszej linii zadeklarowaliśmy zmienną $i, która posiada wartość 10. W drugiej linii zadeklarowaliśmy zmienną $a do której przypisaliśmy wynik mnożenia wartości zmiennej $i przez 10. Do tego wszystkiego dodaliśmy 5, a całość została wyświetlona przy pomocy instrukcji echo. W wyniku takiego działania zmienna $i będzie posiadać wartość 100, a $a - 105.

Operatory arytmetyczne

Operatory arytmetyczne służą dokonywania prostych operacji znanych Ci zapewne ze szkoły podstawowej (dodawanie, odejmowanie, mnożenie, dzielenie). Lista operatorów arytmentycznych zawarta została w tabeli 2.

Tabela 2. Lista operatorów arytmetycznych

Przykład	Opis
$a + $b	Dodawanie wartości zmiennych $a i $b
$a - $b	Odejmowanie wartości zmiennych $a i $b
$a * $b	Mnożenie wartości zmiennych $a i $b
$a / $b	Dzielenie wartości zmiennych $a i $b
$a % $b	Reszta z dzielenia zmiennych $a i $b

Należy jedynie wyjaśnić sprawę dzielenia. Domyślny operator dzielenia (/) zwraca wynik w postaci liczby zmiennoprzecinkowej (float). Np.:

echo 5 / 2; // wyświetli 2.5

Zmiennoprzecinkowy wynik dzielenia zawsze można zaokrąglić stosując funkcje PHP: round(), floor() oraz ceil().

Zaokrąglanie

W PHP za zaokrąglanie liczb odpowiadają trzy funkcje. Funkcja floor() zaokrągla ułamki w dół; ceil() zaokrągla ułamki w górę. Oto kilka przykładów użycia tych funkcji:

echo 'Floor: 3.5: ' . floor(3.5) . '<br>'; // zwróci 3
echo 'Ceil: 3.5: ' . ceil(3.5) . '<br>'; // zwróci 4
echo 'Floor: 3.5667 ' . floor(3.5667) . '<br>'; // zwróci 3
echo 'Ceil: 3.9 ' . ceil(3.9) . '<br>'; // zwróci 4

Jeżeli chodzi o funkcję round() to do dołu lub do góry, w zależności od liczby jaka została owej funkcji przekazana. Jeżeli jednak podamy funkcji liczbę 3.5 to zostanie ona zaokrąglona w gorę:

echo 'Round(3.5) : ' . round(3.5) . '<br>'; // zwróci 4
echo 'Round(3.6) : ' . round(3.4) . '<br>'; // zwróci 3

Do funkcji round() możemy przypisać drugi parametr, który jest opcjonalny, a oznacza dokładność zaokrąglania. Spójrz na taki kod:

echo round(2.56777676, 3)

Rezultat działania takiego skryptu to 2.568.

Operatory porównania

Jak łatwo się domyśleć, operatory porównania służą porównywaniu wartości znajdujących się po obu stronach owego operatora. Np. poniższa instrukcja zawsze wyświetli cyfrę 1:

echo 2 == 2;

Operator == służy sprawdzaniu (tak samo jak w C i innych językach) czy dwie wartości są sobie równe. Ponieważ w tym wypadku porównujemy dwie liczby 2, działanie takiego operatora zwróci true. Musisz wiedzieć, że wartość true jest równe liczbie 1, a false ? 0.

Dlatego też, jeżeli warunek zostanie spełniony (true) to w przeglądarce zostanie wyświetlona cyfra 1. Tabela 3. zawiera pełną listę operatorów porównania.

Tabela 3. Lista operatorów porównania

Przykład	Opis
$a == $b	Zwraca true jeżeli $a jest równe $b
$a === $b	Zwraca true jeżeli $a jest identyczne z $b (obie zmienne są tego samego typu). 
$a != $b	Zwraca true jeżeli $a jest różne od $b
$a <> $b	Zwraca true jeżeli $a jest różne od $b
$a !== $b	Zwraca true jeżeli $a nie jest identyczne z $b
$a > $b	Zwraca true jeżeli $a jest większe od $b
$a < $b	Zwraca true jeżeli $a jest mniejsze od $b
$a >= $b	Zwraca true jeżeli $a jest większe lub równe $b
$a <= $b	Zwraca true jeżeli $a jest mniejsze lub równe $b

Operatory porównywania są często wykorzystywane w połączeniu z instrukcjami warunkowymi, ale o tym będziemy mówić w dalszej części rozdziału.

Chciałem jeszcze wspomnieć o operatorze === i o identyczności typów. Sprawdźmy, czym ów operator różni się od operatora porównania:

echo 2 == '2';
echo 2 === '2';

Powyższe dwie instrukcje porównują dwie wartości. Zwróć uwagę, że druga wartość jest zapisana w apostrofach, czyli jest łańcuchem tekstowym. Operator == mimo tego w tym przypadku zwróci wartość true (PHP spróbuje w tym momencie przekonwertować łańcuch na liczbę i wtedy dopiero porównywać dane).

Operator === porównuje także typy danych. Skoro więc jedna wartość jest wartością liczbową, a druga ? łańcuchową ? taka konstrukcja zwróci false.

Operatory logiczne

Operatory logiczne są używane podczas analizy wyrażeń logicznych. Lista operatorów logicznych została zawarta w tabeli 4.

Tabela 4. Lista operatorów logicznych

Przykład	                                Opis
$a and $b (lub $a && $b)	Zwraca true jeżeli zarówno $a jak i $b posiadają wartość true. 
$a or $b (lub $a || $b)	Zwraca true jeżeli $a lub $b posiadają wartość true. 
! $a	                                Zwraca true jeżeli $a nie jest true. 

Być może nie widzisz sensu stosowania operatorów logicznych, lecz często stosuje się je w połączeniu z instrukcjami warunkowymi (o tym dalej) oraz funkcjami.

Operatory wykonania polecenia systemowego

Od razu zaznaczam, że ten operator może nie zadziałać na niektórych serwerach, na których administrator włączył tryb safe_mode lub zablokował funkcje shell_exec(). Operator wykonania polecenia systemowego (bo jest właściwie jeden) umożliwia uruchamianie zewnętrznych aplikacji systemu lub wykonywanie poleceń systemowych. Polecenia systemowe muszą być ograniczone apostrofem wstecznym (`) a rezultat takiego polecenia może być od razu wyświetlony lub przypisany do zmiennej.

Przykładowo, korzystając z systemu Windows możemy wysłać ping do jakiegoś serwera:

<?php
echo `ping www.4programmers.net`;
?>

Rezultatem wykonania takiego polecenia na systemie Windows będzie pojawienie się takiego lub podobnego tekstu, zwróconego przez program:

Badanie 4programmers.net [217.11.138.50] z użyciem 32 bajtów danych:

Odpowiedź? z 217.11.138.50: bajtów=32 czas=33ms TTL=57
Odpowiedź? z 217.11.138.50: bajtów=32 czas=34ms TTL=57
Odpowiedź? z 217.11.138.50: bajtów=32 czas=209ms TTL=57
Odpowiedź? z 217.11.138.50: bajtów=32 czas=737ms TTL=57

Statystyka badania ping dla 217.11.138.50:
    Pakiety: Wysłane = 4, Odebrane = 4, Utracone = 0 (0% straty),
Szacunkowy czas błądzenia pakietu w milisekundach:
    Minimum = 33 ms, Maksimum = 737 ms, Czas średni = 253 ms

Należy zwrócić uwagę na to, iż PHP jest niezależny od platformy systemowej, więc skrypty można uruchomić zarówno na systemie Windows jak i UNIX. Należy zwrócić uwagę na to, że wiele poleceń dostępnych na system UNIX nie funkcjonuje w systemie Windows. Przykładowo, poniższy skrypt nie zostanie prawidłowo wykonany na systemie Windows:

<?  
$a = `ls -al`;
echo $a;
?>

Operatory kontroli błędów

PHP obecnie obsługuje jeden operator kontroli błędów. Jest to znak małpy (@) który postawiony przed jakimkolwiek wyrażeniem PHP spowoduje, iż ewentualny błąd spowodowany przez tę funkcję nie zostanie wyświetlony. Operator kontroli błędów może mieć zastosowanie również przed nazwami zmiennych ? np.:

echo @$zmienna; 

Operatory bitowe

Ostatnia grupa operatorów PHP, to operatory operujące na liczbach. Konkretniej mówiąc działają one na binarnej reprezentacji liczb całkowitych, ale również na ciągach. Tabela 5. zawiera listę operatorów bitowych dostępnych w PHP.

Tabela 5. Lista operatorów bitowych PHP

Przykład	Opis
$a & $b	Mnożenie bitowe. Bit wynikowy jest równy 1 jeżeli obydwa bity składowe są równe 1.
$a | $b	Sumowanie bitowe. Bit wynikowy jest równy 1 jeżeli jeden z bitów składowych jest równy 1. 
$a ^ $b	Dany bit wynikowy jest równy 1 wtedy, gdy jeden z bitów składowych jest równy 1, a drugi 0. 
~ $a	Bity w zmiennej $a mające wartość 0 otrzymują 1 i na odwrót.
$a << $b	Przesuwa bity w zmiennej $a o $b kroków w lewo.
$a >> $b	Przesuwa bity w zmiennej $a o $b kroków w prawo. 

Nie będę rozwlekał tematu operowania na bitach, gdyż wymaga to znajomości przeliczania systemów liczbowych z dwójkowego na dziesiętny i szesnastkowy.

Priorytety operatorów

Podczas programowania w PHP, przy pomocy nawiasów można zmieniać priorytety operatorów, według działań arytmetyki. Przykładowo 2 + 2 * 2 zwróci 6, gdyż operator mnożenia (*) ma większy priorytet. Jednak już po dodaniu nawiasów, wynik takiego działania może wynosić 8: (2 + 2) * 2.

Operatory and, or pomimo, iż działają prawie tak samo jak && i || mają niższy priorytet wykonywania.

Instrukcje warunkowe

Przejdźmy teraz do bardziej zaawansowanego elementu języka, a mianowicie do instrukcji warunkowych, czyli struktur konstruujących działanie programu. Dzięki instrukcjom warunkowym, możemy ustalić kolejność wykonywania aplikacji, w zależności od jej stanu.

Przykładowo, jeżeli użytkownik podał w formularzu na stronie WWW prawidłowe hasło to można przejść do dalszego wykonywania programu. Jeżeli nie ? dalszy dostęp do aplikacji jest blokowany. To właśnie jest realizowane przy pomocy instrukcji warunkowych.

Instrukcja if

Podstawową instrukcją warunkową jest if, która wykonuje dane działania w zależności, do tego, czy podany warunek zostanie spełniony. Instrukcja if posiada taką konstrukcję:

if (warunek) instrukcja;

Jak wspomniałem wcześniej, wraz z instrukcjami warunkowymi, bardzo często wykorzystywane są operatory logiczne oraz porównania:

<?
$var = true;
if ($var) echo 'Zmienna $var posiada wartość true';
?>

Po uruchomieniu takiego programu, przeglądarka wyświetli napis, gdyż taki warunek będzie spełniany zawsze, ponieważ na starcie programu przypisujemy zmiennej $var wartość true. Ten skrypt równie dobrze mógłby wyglądać tak:

<?
$var = true;
if ($var == true) echo 'Zmienna $var posiada wartość true';
?>

Zwracaj uwagę na operator, jakiego używasz w danej sytuacji. Bardzo często operator przypisania (=) stosowany jest w kontekście porównania dwóch wartości, a za to odpowiada operator porównania (==). Jest to bardzo często przyczyną błędów w programie.
Często zachodzi konieczność wykonania jakiegoś kodu, jeżeli warunek posiada wartość fałszywą. W takim wypadku możemy skorzystać z dodatkowego operatora przeczenia (!):

<?
$var = true;
// poniższy warunek nie zostanie nigdy spełniony
if (!$var) echo 'Zmienna $var posiada wartość false';
?>

W podobny sposób można korzystać z pozostałych operatorów porównania:

<?
$i  = rand(1, 100);
if ( $i == 10 ) echo 'Moje gratulacje! Trafiłeś w dziesiątkę!';
?> 

Funkcja rand() losuje liczbę z przedziału od 1 do 100 i zwraca wynik do zmiennej $i. W kolejnej instrukcji następuje sprawdzenie, czy wylosowaną liczbą jest 10. Jeżeli wywołasz funkcję rand() bez podania parametrów, funkcja wylosuje liczbę z przedziału od 1 do N. N jest największą liczbą, jaka może zostać wylosowana. Żeby ją poznać, skorzystaj z funkcji mt_getrandmax():

<?
echo mt_getrandmax(); // wyświetli np. 2147483647
?>

Instrukcja warunkowa może posiadać kilka warunków spełnienia. W takich wypadkach należy skorzystać z operatorów logicznych ? np.:

<?
$prawda = true;
$i = rand(1, 100);
if ( $i == 10 && $prawda ) echo 'Warunek spełniony';
?>

W powyższym przypadku warunek zostanie spełniony, jeżeli zmienna $i będzie posiadała wartość 10, a zmienna $prawda będzie miała wartość true.

Blok instrukcji

Podobnie jak w języku C, bloki instrukcji mogą być zawarte pomiędzy znaki { i }. Powiedzmy, że po spełnieniu warunku chcesz, aby program wyświetlił napis oraz dodatkowo ? zmienił wartość zmiennej. Możesz napisać tak:

<?
$prawda = false;
if ( $prawda )
  echo 'Warunek spełniony';
  $napis = 'Wszystko OK';
  
echo $napis;
?>

Zgodnie z powyższym napisem, warunek nie powinien być spełniany nigdy ? wartość zmiennej $prawda to false. Tymczasem po uruchomieniu takiego skryptu, zobaczysz, że przeglądarka zawsze wyświetla napis Wszystko OK. Nie chcemy, aby tak się działo, ponieważ warunek nie został spełniony. Rozwiązaniem problemu, będzie umieszczenie instrukcji w bloku:

<?php
$prawda = false;
if ( $prawda )
{
    echo 'Warunek spełniony';
    $napis = 'Wszystko OK';
}
echo $napis;
?>

Teraz skrypt nie będzie już wypisywał tekstu, gdyż warunek nie został spełniony (zmienna $napis nie została zadeklarowana). Klamer { i } używamy wtedy, gdy do wykonania mamy wiele instrukcji. Ze względu na czytelność kodu zaleca się używania klamer nawet, gdy mamy do czynienia z jedną instrukcją:

<?
$prawda = true;
if ($prawda) {
    echo 'Warunek spełniony!';
    $i = rand(1, 10);
    if ($i == 10) {
        echo 'Wylosowano 10';
    }
}
?>

Instrukcja else

Dobrze, wiesz już, do czego służy instrukcja if. Często będziesz zmuszony do wyświetlania jakiegoś komunikatu, czy podjęcia jakiejś reakcji, jeżeli warunek nie zostanie spełniony. W takim wypadku mógłbyś użyć drugiej instrukcji if:

<?php
$prawda = true;
if ($prawda) {
    echo 'Prawda';
}   
if (!$prawda) {
    echo 'Fałsz';
} 
?>

Prawie wszystkie języki programowania, w tym PHP, udostępniają alternatywę powyższego rozwiązania ? instrukcję else. Kod znajdujący się po instrukcji else zostaje wykonany, jeżeli instrukcja if nie zostanie spełniona. Powyższy kod, można więc zastąpić poniższym:

<?php
$prawda = false;
  
if ($prawda) {
    echo 'Prawda';
} 
else {
    echo 'Fałsz';
}
?>

Instrukcja elseif

Instrukcja elseif służy do badania dodatkowych warunków jeżeli poprzedni warunek if nie został spełniony. Tak na prawdę elseif jest identyczne do else if.

Taki zapis:

<?
if ($value) {
}
else if ($otherValue) {
}
?>

jest identyczny z zapisem:

<?
if ($value) {
}
elseif ($otherValue) {
}
?>

Nie wprowadza to szczególnej różnicy, jedynie możemy oszczędzić spację.

Operator trójoperandowy

Operator trójoperandowy, nazywany czasem operatorem trójargumentowym. Konstrukcja tej instrukcji może wydać Ci się dziwna, lecz w gruncie rzeczy czasem może być użyteczna. Podczas gdy konstruktcja if/else to "orzeczenie", ang. statement, tak operator trójargumentowy pozwala nam konstruować "wyrażenia", ang. expression. Wyrażenia różnią się od statement'ów tym, że zwracają wynik.

Nie możemy, np. napisać czegoś takiego:

<?php
$zmienna = if ($value) 15 else 16; // To jest błąd składniowy

Możemy jednak użyć operatora trójargumentowego.

<?php
$zmienna = $value ? 15 : 16;
?>

Kod realizujący takie samo zadanie, z użyciem instrukcji if wyglądałby następująco:

<?php
$zmienna;
if ($wakacje) {
    $zmienna =15;
}
else {
    $zmienna =  16;
}
?>

Operator trójoperandowy można stosować w prostych przypadkach, gdyż jego konstrukcja jest nieco ograniczona i jeżeli warunek zostanie spełniony, tylko jedna instrukcja może być wykonana. Konstrukcja tego operatora jest następująca:

warunek ? (instrukcja spełniona) : (instrukcja nie spełniona)

Jeżeli warunek zostanie spełniony, możesz równie dobrze przypisać jakąś wartość do zmiennej, czy dokonać innych operacji:

Instrukcja switch

Instrukcja switch używana jest przeważnie w przypadkach, gdy mamy do czynienia z wyliczeniem wielu możliwych działań w zależności od uzyskanej wartości.
Budowa instrukcji switch jest następująca:

switch (warunek) {
  case wartość1:
    instrukcje;
    break;
  case wartość2:
    instrukcje;
    break;
  default:
    instrukcje;
}

Problem ze switch

Bardzo często, niewątpliwie napiszesz w swoim życiu kilka kodów, które będą wymagały wywołania jednej operacji dla kilku danych wejściowych, np.:

<?php
$color = 'red';

if ($color === 'red') {
  echo 'czerwony';
}
if ($color === 'green') {
  echo 'zielony';
}
if ($color === 'blue') {
  echo 'niebieski';
}

Wielu programistów natychmiast dostrzerze duplikację w takim kodzie, i będzie chciało ją zminimalizować. Samodzielnie, jeśli mają dostęp do takiego kodu, lub będą Cię przekonywać żeby zminimalizować taką duplikację, z czym się w płeni zgadzam. Jednak! Należy uważać! Jedynym sposobem minimalizacji takiej duplikacji którą zna większość programistów jest właśnie switch, zatem kiedy napiszesz taki kod, najpewniej dostaniesz radę żeby zamienić je na switch. Jest to jednak pułapka, bowiem zmiana wielu ifów na switcha w żaden sposób nie usuwa duplikacji, a jedynie pograsza problem, ponieważ ciężej to zrefaktorować. Zamiana wielu ifów na switch to poważny krok wstecz.

Dlaczego nie warto dodawać switcha? Jak więc pozbyć się duplikacji?

Potrzeba dodania switcha do aplikacji (lub wielu podobnych ifów) sugeruje że jest gdzieś bardziej standardowa struktura. Nie jest łatwo ją znaleźć, nie jest też łatwo zaprogramować jej zamiennik; ale nie powinno nas to przekonywać żeby zamieniać ify na switch. Jeśli nie umiemy znaleźć lepszej struktury, powinniśmy zostawić nifów. Funkcja w której jest 20x ifów jest tak samo źle zaprojektowana jak switch który ma 20 klauzl case.

Przykład poprawy kodu wyżej.

<?php
$colorNames = [
  'red' => 'czerwony',
  'blue' => 'niebieski',
  'green' => 'zielony'
];
$color = 'red';

echo $colorNames[$color];

W przykładzie wyżej, użyłem tablic (ang. array), których jeszcze nie omawialismy, ale nie to jest celem. Tutaj, chodzi o wyjaśnienie, że kiedy korzystasz z wielu operacji na podobnych danych, i stworzysz "drabinkę ifów", może zostać Ci doradzone by zmienić to na switch. Chodzi o to, żeby pamiętać że taki switch to krok w tył, i jeśli chcesz coś usprawniać, powinieneś poszukać dodatkowych struktur w swojej aplikacji.

Pętle

Kolejnym elementem, który mam zamiar omówić są pętle. Służą one do wielokrotnego wykonywania tego samego kodu. Dzięki pętlom możesz w prosty sposób wyświetlić ten sam tekst, ale w gruncie rzeczy mogą posłużyć do bardziej złożonych operacji, wykonywania algorytmów itp.
PHP daje możliwość wykorzystania czterech rodzajów pętli ? każda z nich posiada inną charakterystykę. Ilość iteracji pętli (wykonania) może być ustalona z góry lub też zależeć od spełnionego warunku.

Przykładowo pętla może przez cały czas losować liczbę z zakresu od 1 do 100, dopóki nie zostanie wylosowana liczba 50.

Pętla while

Pętla while jest najprostszą pętlą oferowaną w PHP. Przed wykonaniem sprawdza warunek zakończenia i jeżeli zostaje on spełniony ? nie wykonuje żadnych instrukcji. Jeżeli warunek nie zostanie spełniony wykonuje instrukcje z ciała pętli do momentu spełnienia warunku. Oto budowa pętli while:

<?php
while (warunek) {
   instrukcje;
}

Napiszmy na sam początek program, który ma zadanie losować liczbę z zakresu od 1 do 100 dopóki nie wylosuje liczby 50. Na końcu działania pętli wyświetlimy licznik z ilością prób, które podjął program do osiągnięcia tego rezultatu. Aplikacja, o której mowa, napisana z użyciem pętli while, została przedstawiona na listingu 1.

Listing 1. Losowanie liczby przy użyciu pętli while

<?php
$i = 0; // deklarujemy zmienna (licznik)
  
while ($rand !== 50) { // wykonuj dopóki zmienna $rand nie będzie równać się 50
    $rand = rand(1, 100);
    ++$i; // zwiększ licznik prób
}
  
echo "Wylosowałem liczbę 50 po $i próbach!";

Przeanalizujmy program od końca. Na samym końcu widzimy instrukcję echo która wyświetla komunikat o ilości prób wylosowania liczby 50. Zmienna $i to licznik prób - na samym początku działania programu nadajemy jej wartość 0. Warunkiem zakończenia pętli jest wylosowanie liczby 50, stąd warunek $rand !== 50 który można przetłumaczyć: "wykonuj dalej jeżeli wartością zmiennej $rand nie jest 50". W ciele pętli użyłem operatora inkrementacji w celu zwiększenia wartości zmiennej $i.

Jeżeli Twoje PHP ma ustawioną opcję pokazywania ostrzeżeń, zapewne podczas działania tego programu przeglądarka wyświetli napis: Notice: Undefined variable: rand. PHP próbuje nam przekazać, że zmienna $rand nie została nigdzie zainicjowana, a my próbujemy odwołać się do niej przy pierwszej iteracji pętli. Rozwiązaniem może być dodanie na samym początku skryptu, linii:

$rand = 0;

Innym rozwiązaniem jest wyłączanie powiadamiania o ostrzeżeniach. Realizuje to funkcja error_reporting(). Na samym początku skryptu możesz więc dodać następującą linię:

error_reporting(E_ERROR & ~E_NOTICE);

Mówi ona o tym, że chcemy dostawać informację o błędach, ale bez wskazówek (ang. notice).

Warunek zakończenia pętli może być bardziej "skomplikowany", tzn. można używać operatorów porównania oraz operatorów logicznych. Na listingu 2. znajduje się poprawiony kod, który sprawdza, czy wylosowaną liczbą nie jest 50 lub 70.

Listing 2. Losowanie liczby przy użyciu pętli while

<?
$i = 0; // deklarujemy zmienna (licznik)
$rand = 0;  
while ($rand !== 50 && $rand !== 70) { // wykonuj dopóki zmienna $rand nie będzie równać się 50
    $rand = rand(1, 100);
    ++$i; // zwiększ licznik prób
}  
echo "Wylosowałem liczbę $rand po $i próbach!";  
?>

Pętla do..while

Pętla do..while jest bardzo podobna do pętli while. W zasadzie jedyną różnicą jest fakt, iż warunek zakończenia pętli sprawdzany jest na końcu a nie na początku jak to ma miejsce przy pętli while. Oznacza to, że pętla zawsze, zostanie wykonana, co najmniej raz. Spójrz na poniższy przykład:

<?
$bool = false;
do {
    echo 'Witaj!';
}
while ($bool);
?>

Zmiennej $bool nadajemy wartość false, natomiast w ramach tego co napisaliśmy warunkiem wykonywania pętli jest posiadanie przez zmienną wartości true. Mimo tego po uruchomieniu skryptu przeglądarka wyświetli napis Witaj!. Gdybyśmy zamiast pętli do..while użyli while, skrypt nie zwróciłby żadnego napisu.

Ponieważ zapewne wielu Czytelników programowało wcześniej w języku Pascal, warto wspomnieć, iż pętla do..while jest odpowiednikiem pętli repeat..until w języku Pascal.

Pętla for

Pętla for zasadniczo różni się od wspomnianych wcześniej pętli. W pierwszym wierszu pętli znajdują się wszystkie wyrażenia kontrolujące:

for (wyrażenie1; wyrażenie2; wyrażenie3) {
  instrukcje;
}

Przed rozpoczęciem wykonywania pętli, wykonywane jest wyrażenie1. Zazwyczaj ma ono na celu zainicjowanie zmiennej kontrolnej przebieg całej pętli. Wyrażenie2 wykonywane jest przy każdej iteracji pętli - jeżeli wyrażenie ma wartość true, działanie jest kontynuowane. Oto przykład działania pętli for - dziesięciokrotne wypisywanie jednego napisu:

<?php
for ($i = 1; $i <= 10; $i++) {
    echo "Napis nr $i" . PHP_EOL;
}
?>

chociaż programist zapisałby tą pętle tak:

<?php
for ($i = 0; $i < 10; $i++) {
    echo 'Napis nr ' . ($i+1) . PHP_EOL;
}
?>

Dlatego że dla programistów indeksowanie (iterowanie) wszystkiego od 0 jest bardziej naturalne.

W wyniku działania takiego skryptu, przeglądarka wyświetli tekst:

Napis nr 1
Napis nr 2
Napis nr 3
Napis nr 4
Napis nr 5
Napis nr 6
Napis nr 7
Napis nr 8
Napis nr 9
Napis nr 10

Pierwsze wyrażenie z pętli inicjuje zmienną $i (nadaje jej wartość 1). W tym momencie zaczyna się wykonywanie ciała pętli, czyli wypisanie pierwszego tekstu na ekranie. Druga iteracja sprawdza warunek zakończenia. Warunkiem zakończenia jest osiągnięcie przez zmienną $i wartości większej niż 10. Jeżeli warunek nie jest spełniony pętla wykonuje wyrażenie3, czyli zwiększenie wartości zmiennej $i o 1.
Działanie w wyrażeniu trzecim niekoniecznie musi zwiększać wartość zmiennej o 1. Równie dobrze taka pętla może wyglądać w ten sposób:

<?php
for ($i = 1; $i <= 10; $i += 2) {
    echo "Napis nr $i";
}
?>

Dzięki temu realizujemy "przeskok" iteracji o dwa "oczka". W rezultacie tego wykonanych zostanie jedynie 5 iteracji pętli:

Napis nr 1
Napis nr 3
Napis nr 5
Napis nr 7
Napis nr 9

Pętla for w języku PHP (podobnie zresztą jak w C) daje duże możliwości i jest bardzo elastyczna. Spójrz na poniższy przykład:

<?php
$j = 0;  
for ($i = 1; $i <= 10; $j++, $i += 2) {
    echo "Napis nr $i";
} 
echo "Wystąpiło $j iteracji...";
?>

Oprócz zwiększania wartości zmiennej $i o 2, zwiększamy także wartość zmiennej $j o 1. Taką operację równie dobrze moglibyśmy umieścić w ciele pętli:

<?php
$j = 0;  
for ($i = 1; $i <= 10; $i += 2) {
    $j++;
    echo "Napis nr $i";
}  
echo "Wystąpiło $j iteracji...";
?>

Pętle nieskończone

Specyfika pętli for pozwala nam na opuszczenie nawet wszystkich parametrów, co owocuje powstaniem tzw. nieskończonej:

for (;;) {
}

Taka pętla będzie wykonywana w nieskończoność. Nasz skrypt nie skończy działania sam, chyba że "ubijemy" program wyłączając terminal lub "zabijając proces" poprzez manager zadań.

Przytoczmy ponownie przykład z losowaniem:

<?php
$i = 0;
  
for (;;) {
   ++$i;
   if (rand(1, 100) === 50) {
       break;
   }
}  
echo "Liczba wylosowana po $i próbach";
?>

W tym programie pętla będzie wykonywana dopóty dopóki nie zostanie wylosowana liczba 50. Instrukcja break, w połączeniu z pętlami powoduje wyjście z ciała (zakończenie działania pętli).

O instrukcjach break oraz continue opowiem nieco dalej. W pętli for można pominąć jedynie warunek zakończenia, dzięki czemu jesteśmy w stanie ukrócić poprzedni program:

<?php
for ($i = 1; ; $i++) {
    if ( rand(1, 100) === 50) {
        break;
    }
}  
echo "Liczba wylosowana po $i próbach";
?>

Skoro mowa o pętli forever, to należałoby wspomnieć o tym, że pętla while także posiada taką możliwość ? oto przykład:

<?
  $i = 0;
  
  while (1)
  {
     if ( ++$i == 10 )
     {
         echo 'Kończymy!';
         break;
     }
  }
?>

Pętla for działająca w drugą stronę

Jeżeli programowałeś wcześniej w języku Pascal, to wiesz, że i tam istnieje pętla for. Jeżeli chcemy, aby zmienna pomocnicza zmniejszała swoją wartość, musimy zastosować słowo kluczowe downto. W PHP sytuacja wygląda nieco inaczej ? tutaj wystarczy zastosować operator dekrementacji:

<?
  for ( $i = 10; $i > 0; $i-- )
  {
      echo "Napis nr $i<br>";
  }
?>

Zwróć uwagę, że wartość początkowa, pomocniczej zmiennej $i to 10. Za każdą iteracją tej pętli wartość ta podlega zmniejszeniu.

Pętla foreach

Pętla foreach operuje ona jedynie na tablicach, dlatego też na razie nie będę wyjaśniał jej działania.

Instrukcje continue i break

Instrukcja break służy do natychmiastowego zakończenia działania pętli. Jak zapewne już zauważyłeś działa ona także w połączeniu z instrukcją switch. Instrukcja break obsługuje dodatkowy parametr, który mówi ile struktur ma zostać zakończonych w danym momencie (może się bowiem zdarzyć, że np. instrukcja switch zostanie umieszczona w pętli). Spójrz na poniższy kod:

<?
  for ( $i = 1;; $i++)
  {
     switch ( rand(1, 100) )
     {
         case 20:
         echo 'Wylosowano liczbę 20<br>';
         break 1;
         
         case 50:
         echo 'Wylosowano liczbę 50<br>';
         break 2;
     }
  }
  
  echo "<br>Wystąpiło $i iteracji";

?>

Jeżeli wylosowaną liczbą jest 20, program wyświetli komunikat, a następnie opuści jedynie instrukcję switch (liczba 1 przy instrukcji mówi o ilości instrukcji, które trzeba opuścić). Przy wylosowaniu liczby 50, nakazujemy aplikacji opuszczenie zarówno instrukcji switch jak i pętli. W rezultacie takiego działania, przeglądarka może wyświetlić np. taki tekst:

Wylosowano liczbę 20
Wylosowano liczbę 20
Wylosowano liczbę 20
Wylosowano liczbę 20
Wylosowano liczbę 50

Wystąpiło 197 iteracji

Jeżeli chodzi o instrukcję continue, to jej wystąpienie powoduje do przejścia do kolejnej iteracji, z pominięciem dalszego kodu:

<?
  for ( $i = 1;; $i++)
  {
     $rand = rand(1, 100);
     
     if ( $rand == 50 )
     {
         echo 'Wylosowano liczbę 50<br>';
         continue;
         
         echo 'Ale fajnie, ten napis nigdy się nie pojawi!';
     }
     
     if ( $rand == 20 )
     {
         break;
     }
  }
  
  echo "<br>Wystąpiło $i iteracji";

?>

Instrukcja continue, podobnie jak i break obsługuje dodatkowy parametr mówiący ile poziomów zagnieżdżonych pętli dana instrukcja dotyczy. W powyższym skrypcie, po wylosowaniu liczby 50, wyświetlany jest napis, a program przechodzi do następnej iteracji. Pętla kończy działania dopiero po wylosowaniu liczby 20.

Funkcje

Idea programowania proceduralnego zaczęła się pojawiać wraz z bardziej zaawansowanymi programami. Tradycyjny moduł projektowania nie sprawdzał się dobrze, gdy programy zaczęły być bardziej skomplikowane ? wówczas ich konserwacja, naprawianie błędów było niezwykle trudne.

Ktoś mądry wymyślił wtedy, że można by było program dzielić na mniejsze części ? tzw. procedury. Przykładowo, jeżeli mamy kod, który wyświetla pewien komunikat i kończy działanie programu, a ów kod jest używany wiele razy w programie to należałoby go dublować kilkakrotnie. Powoduje to nie tylko zwiększenie objętości kodu, ale również większe narażenie na błędy. Bo co jeżeli w tym małym fragmencie, który jest zdublowany wiele razy, wystąpi błąd? Należałoby wówczas przeszukiwać cały kod i w każdym miejscu poprawiać usterkę.
Teraz, w nowoczesnych językach programowania można pewien fragment kodu umieścić w procedurze i ? za każdym razem kiedy zajdzie potrzeba jego wykonania ? wywołać procedurę!

W językach takich jak C, czy PHP nie istnieją procedury, a funkcję. Podczas czytania tego podręcznika stosowałeś już funkcję wbudowane w PHP ? m.in. rand(). Owa funkcja realizująca proces losowania liczb może przyjmować parametry, które należy podać w nawiasach. Każdy parametr należy oddzielić znakiem przecinka. Język PHP pozwala na definiowanie własnych funkcji, z użyciem słowa kluczowego function.
Każda funkcja musi posiadać nazwę ? parametry są opcjonalne:

function About() { }

Kod funkcji należy wpisać pomiędzy klamrami. Nazwy funkcji nie są wrażliwe na wielkość liter, nie możesz więc zadeklarować dwóch funkcji o takiej samej nazwie:

function about() { }
function ABOUT() { } 

Nazwa funkcji nie może rozpoczynać się od cyfry. Może natomiast zawierać polskie znaki, cyfry oraz znak podkreślenia (_).

Parametry funkcji

Funkcja nie musi, ale może posiadać parametry (również nazywane argumentami). Deklarując funkcję, nazwy parametrów należy wpisać w nawiasie, oddzielając je przecinkami:

function foo($x, $y) 
{
}

Nie ma ograniczeń, co do liczby parametrów. Napiszmy prosty program, korzystający z funkcji, którego celem będzie przeliczanie stopni Celsjusza na Fahrenheita. Program znajduje się na listingu 3.

Listing 3. Program przeliczający stopnie Celsjusza na Fahrenheita

<?

  function Fahrenheit( $Celsius )
  {
      return ( $Celsius * 9/5 + 32 );
  }
  
  $Celcius = 30;
  
  echo "$Celcius stopni Celsjusza to " . Fahrenheit($Celcius) . " stopni Fahrenheita";

?>

Funkcje mogą, lecz nie muszą zwracać wyniku. W naszym wypadku funkcja Fahrenheit() pobiera wartość parametru $Celsius i przelicza stopnie na skalę Fahrenheita, by na końcu zwrócić wynik do aplikacji. Za zwrócenie rezultatu działania funkcji, odpowiada instrukcja return, która równa się zakończeniu działania funkcji. Przestrzegam, więc początkujących programistów przed umieszczeniem kodu po poleceniu return! Taki kod nie zostanie nigdy wykonany.

Parametry domyślne

Funkcja rand() nie wymagała parametrów aczkolwiek je akceptowała. My, deklarując funkcję także możemy ustalić parametry domyślne, tzn. takie których podanie nie jest wymagane. Np.:

function Fahrenheit( $Celsius = 20 )
{
    return ( $Celsius * 9/5 + 32 );
}

Jeżeli nie podamy parametru, wywołując funkcję Fahrenheit(), parametrowi $Celsius zostanie nadana wartość 20. Należy zaznaczyć, że jeżeli mamy do czynienia z wieloma parametrami, te domyślne powinny być zgrupowane po prawej stronie. Spójrz na ten kod:

<?

 function foo($param1 = 'param1', $param2)
 {
   echo $param1;
 }

 foo();
?>

Mamy tu do czynienia z parametrem domyślnym $param1, który znajduje się po lewej stronie. Parametr $param2 nie jest już domyślny, a znajduje się po stronie prawej. Wywołując funkcję foo() nie możemy pominąć parametru pierwszego mim iż jest on domyślny. Wszystko dlatego, że funkcja foo() wymagania podania wartości parametru $param2.

Zmienne lokalne

W funkcjach możesz deklarować zmienne, które widoczne będą jedynie w obrębie tej funkcji (takie zmienne nazywamy zmiennymi lokalnymi). PHP, pamięć dla tych zmiennych rezerwuje w momencie wywołania danej funkcji, a zwalnia w momencie zakończenia działania owej funkcji. Dlatego taki kod nie zostanie wykonany prawidłowo:

<?

 function foo()
 {
     $foo = 'Zmienna';
 }

 foo();
 echo $foo;
?>

Tj. skrypt można uruchomić, ale z punktu widzenia PHP, zmienna $foo nie jest zadeklarowana. Użyliśmy jej bowiem, jedynie w funkcji foo() ? po zakończeniu jej działania zmienna lokalna została usunięta.

Ponieważ interpreter wykonuje instrukcje od góry do dołu, w PHP3 funkcja musiała być zadeklarowana przed jej wywołaniem. Począwszy od PHP4, takiego wymogu nie ma więc wywołanie funkcji może wyglądać tak:

foo();

function foo()
{
} 

Zakres zmiennej

To, co z początku w PHP może wydać się problematyczne to używanie zmiennych globalnych w funkcjach. Normalnie zmienne globalne nie są widoczne dla funkcji ? trzeba jawnie określić, iż planujemy użyć zmiennej globalnej, w danej funkcji. Służy tego słowo kluczowe global:

<?

  // deklaracja nowej zmiennej
  $foo = 20;

  function foo()
  {
      // użyj zmiennej w funkcji
      global $foo;
      // zmień jej wartość
      $foo = 10;
  }

 foo();
 echo $foo; // wyświetli 10
?>

Zmienne globalne to zmienne deklarowane w programie, natomiast zmienne lokalne są deklarowane w funkcjach.

Dzięki instrukcji global jesteśmy w stanie modyfikować wartość zmiennej z poziomu funkcji. Usuń z programu instrukcję global, doprowadzając wygląd funkcji do takiej postaci:

  function foo()
  {
      // zmień jej wartość
      $foo = 10;
  }

Zobacz jaki będzie efekt działania takiego programu. Wartość zmiennej nie ulegnie zmianie ? w funkcji foo() zostanie zadeklarowana nowa zmienna lokalna o tej samej nazwie, co zmienna globalna (jest to możliwe), lecz będą to dwie różne zmienne.

Czas życia zmiennej

Wspomniałem wcześniej iż zmienne lokalne "żyją" jedynie w trakcie działania funkcji. Po jej zakończeniu, zmienna lokalna jest niszczona. Jest to prawda aczkolwiek możemy to zmienić stosując dyrektywę static. Przypatrz się poniższemu skryptowi:

<?
  function foo()
  {
      static $foo = 0;
      return ++$foo;
  }

  $foo = foo();
  $foo = foo();
  
  echo $foo;
?>

W funkcji foo() deklarujemy zmienną $foo i przypisujemy jej wartość 0. Klauzula static znajdująca się przez nazwą zmiennej powoduje zachowanie wartości zmiennej nawet po zakończeniu działania funkcji. Funkcja foo() zwraca zinkrementowaną wartość zmiennej $foo ? jeżeli owa funkcja zostanie wykonana dwa razy, zmienna $foo będzie posiadała wartość 2.

Z powyższego skryptu usuń klauzulę static i sprawdź działanie programu.

Funkcje zagnieżdżone

PHP umożliwia deklarowanie funkcji wewnątrz innych funkcji, lecz takie zagnieżdżone funkcje nie mogą być wywoływane bezpośrednio z programu:

<?

  function foo()
  {
      function bar()
      {

      }
      
      bar(); // wywołanie funkcji
  }
  
  /* funkcja bar() nie będzie dla PHP widoczna */
  bar();
?>

Programowanie strukturalne

Nieco wcześniej, w tym rozdziale wspominaliśmy o programowaniu proceduralnym, które było ułatwieniem podczas pisania programów.

Podział na procedury i funkcje jednak nie wystarczył, gdy programy były coraz dłuższe. Wówczas ktoś wpadł na pomysł, aby części kodu źródłowego podzielić na inne mniejsze pliki. Taką możliwość wprowadzono także w jednej z wcześniejszych wersji Turbo Pascala.
Idee dzielenia kodu na mniejsze pliki nazwano programowaniem strukturalnym.

Dzielenie programu na kilka mniejszych części znacznie ułatwia konserwacje programu oraz projektowanie. Przykładowo, w jednym pliku (nazwanym przykładowo functions.php) mogą znaleźć się funkcje, z których często będziemy korzystać. Następnie skrypt index.php może korzystać ze skryptu functions.php dzięki czemu będziemy mogli wykorzystać funkcje znajdujące się w tym module.

Moduł to zwykły plik tekstowy zawierający kod języka, czyli inaczej mówiąc ? zwykły skrypt PHP.

Włączenie kodu PHP z innego skryptu realizowane jest przez instrukcję include lub require. Spójrz na listingi 4. oraz 5.

Listing 4. Moduł zawierający funkcję Fahrenheit()

<?

  function Fahrenheit( $Celsius )
  {
      return ( $Celsius * 9/5 + 32 );
  }

?>

Listing 5. Skrypt włączający moduł 4.php

<?
  /* włączenie skryptu p3.4.php */
  include 'p3.4.php';

  $Celcius = 30;

  echo "$Celcius stopni Celsjusza to " . Fahrenheit($Celcius) . " stopni Fahrenheita";

?>

Listing 4. zawiera funkcję Fahrenheit() którą następnie można wykorzystywać w wielu innych skryptach PHP. Włączenie tego modułu w inny skrypt jest możliwe dzięki instrukcji include.

W PHP zamiast include, możesz użyć instrukcji require. Obydwie instrukcje działają niemalże identycznie. Jedyną różnicą jest obsługa błędów. Jeżeli próbujemy włączyć do skryptu moduł, który nie istnieje (albo jego nazwa się zmieniła), instrukcja include wygeneruje tylko ostrzeżenie. Instrukcja require w takim wypadku pokaże błąd Fatal Error.

Podczas włączania modułu przy pomocy instrukcji require lub include, nazwę owego modułu możesz podać w nawiasach:

include('p3.4.php');

Do włączania modułów do skryptu, służą także instrukcje include_once oraz require_once. Działają one podobnie jak include i require, z tą różnicą że jeżeli plik został już wcześniej dodany do skryptu, nie zostanie dodany ponownie. Spójrz na poniższy kod:

<?
  /* wł?czenie skryptu p3.4.php */
  include 'p3.4.php';
  include 'p3.4.php';

  $Celcius = 30;

  echo "$Celcius stopni Celsjusza to " . Fahrenheit($Celcius) . " stopni Fahrenheita";

?>

Wykonanie takiego skryptu spowoduje wystąpienie błędu Fatal error: Cannot redeclare fahrenheit(). Gdy w miejsce include wstawimy include_once, skrypt zostanie wykonany poprawnie.

Należy zwrócić uwagę na nazwy skryptów włączanych przy pomocy instrukcji include i require. Konkretnie chodzi o wielkość liter na systemach nie rozróżniających wielkości liter ? takich jak Windows:

  include 'P3.4.php'; // wczyta skrypt p3.4.php

Włączanie modułów w ciało funkcji

Jeżeli zastosujemy instrukcję include (lub require) w ciele danej funkcji, to kod z tego modułu zostanie wstawiony w ową funkcję. Należy się liczyć z tym, że kod takiego modułu nie będzie widoczny poza daną funkcję.

Operacje na łańcuchach

PHP udostępnia kilka ciekawych funkcji operujących na łańcuchach, o których istnieniu powinieneś mieć świadomość. W tej części zaprezentuje przykłady użycia tych funkcji, lecz proszę nie mylić tego z wyrażeniami regularnymi.

sprintf()

Oto budowa funkcji sprintf (parametry oraz zwracana wartość):

string sprintf ( string format [, mixed args])

Funkcja sprintf() zwraca sformatowany łańcuch tekstowy. Pierwszym parametrem tej funkcji musi być łańcuch, który zawierać będzie znaki poprzedzone znakiem procenta (%). Owe znaki zostaną w trakcie procesu formatowania, zastąpione wartościami z kolejnych parametrów funkcji sprintf() ? np.:

<?
  $imie = 'Adam';
  echo sprintf('Mam na imię %s', $imie);
?>

Taki skrypt wyświetli napis Mam na imię Adam. W miejsce znaków %s, zostanie wstawiona zawartość zmiennej $imie. Parametr %s oznacza, że to miejsce ma zostać zastąpione wartością łańcuchową. Istnieje możliwość, aby w formatowanym łańcuchu umieścić następujące parametry:

*%% - wstawia znak procenta (%);
*%d ? wartość typu integer;
*%f ? wartość typu float;
*%s ? wartość typu string;
*%x ? wartość szesnastkowa;
*%b ? wartość binarna;
*%c ? pojedynczy znak;

Spójrz na poniższy przykład prezentujący obliczanie procentowej zawartości danej sumy:

<?
  $percentage = 25;
  $value = 120;
  
  echo sprintf('%f%% ze %f złotych to %f zł', $percentage, $value, ( $percentage * $value / 100 ) );
?>

Taki skrypt obliczy procent (określony w zmiennej $percentage) z sumy określonej w zmiennej $value. Przeglądarka może wyświetlić taki tekst:
25.000000% ze 120.000000 złotych to 30.000000 zł

Mimo, iż skrypt działa prawidłowo, wartości zmienno przecinkowe należałoby zaokrąglić do, powiedzmy ? dwóch miejsc po przecinku. Jest to możliwe dzięki takiemu formatowaniu łańcucha:

echo sprintf('%0.2f%% ze %0.2f złotych to %0.2f zł', $percentage, $value, ( $percentage * $value / 100 ) );

W PHP istnieje również instrukcja printf() która działa bardzo podobnie do sprintf(). Jedyną różnicą jest fakt, iż sprintf() to funkcja, która zwraca wartość tekstową, czyli możemy taką wartość przypisać do zmiennej. Instrukcja printf() nie zwraca żadnej wartości ? należy użyć jej w ten sposób:

  printf('%0.2f%% ze %0.2f złotych to %0.2f zł', $percentage, $value, ( $percentage * $value / 100 ) );

strToLower(), strToUpper()


string strToLower ( string str)
string strToUpper ( string string)

Funkcje strToLower() oraz strToUpper() umożliwiają zmianę wszystkich znaków podanych w łańcuchu na małe lub duże znaki. Zasada użycia jest dość prosta:

<?
  $string = 'php jest super!';
  
  echo strToUpper($string) . PHP_EOL;
  echo strToLower($string) . PHP_EOL;
?>

W wyniku działania takiego skryptu, przeglądarka wyświetli:

PHP JEST SUPER!
php jest super!

Możesz także skorzystać z funkcji ucfirst() która zamienia jedynie pierwszy znak danego łańcucha na duża literę.

PHP udostępnia także funkcję ucwords() która zamienia na wielkie litery jedynie pierwsze znaki danych wyrazów ? np.:

echo ucwords('hello world');  // zwróci Hello World

trim()

string trim ( string str [, string charlist])

Funkcja trim() usuwa tzw. "białe" znaki z początku oraz końca łańcucha tekstowego. Pisząc "białe znaki" mam na myśli spacje, znaki nowej linii (\n) lub tabulacje (\t):

<?php
echo trim("   To jest tekst, który zawiera białe znaki...\n    ");

Domyślnie, funkcja trim() usuwa następujące znaki:

*" " ? spacja;
*\t ? znak tabulacji;
*\n ? znak nowej linii;
*\r ? powrót karetki;
*\0 ? pusty bajt;

PHP udostępnia także funkcje ltrim() oraz rtrim() które usuwają kolejno białe znaki z lewej oraz prawej strony łańcucha.

strLen()

int strlen ( string str)

strLen() jest przydatną funkcją służącą do określania długości łańcucha podanego w parametrze. Zwracana ona liczbę określającą ilość znaków:

echo strLen('PHP'); // zwróci 3

chr(), ord()


string chr ( int ascii)
int ord ( string string)

Te dwie proste funkcje służą do operowania na kodach ASCII.
ASCII to skrót od słów American Standard Code for Information Interchange. Jest to zestaw kodów z zakresu od 0 do 127, przyporządkowany przez ANSI, amerykański instytut do spraw standardów. Poszczególnym znakom alfanumerycznym (litery alfabetu angielskiego i cyfry) przyporządkowany jest numer. Np. litera a ma numer 97.

Funkcja ord() zwraca numer znaku podanego w parametrze natomiast funkcja chr() zwraca znak na podstawie numeru podanego w parametrze tej funkcji:

<?
  echo ord('A'); // zwróci 65
  echo chr(65);  // zwróci A
?>

str_replace()

mixed str_replace ( mixed search, mixed replace, mixed subject [, int &count])

Bardzo użyteczna funkcja str_replace() umożliwia zastępowanie tekstu w łańcuchu, w prosty i szybki sposób. Funkcja posiada trzy parametry, które są wymagane do prawidłowego działania: szukana fraza, nowa fraza oraz jako trzeci parametr ? łańcuch, w którym odbędzie się szukanie. Oto przykład:

<?
   echo str_replace('fajne', 'super', 'PHP jest fajne');
?>

W powyższym skrypcie, słowo fajne zostanie zastąpione przez super, w wyniku czego przeglądarka wyświetli napis: PHP jest super.

Począwszy od PHP 5 funkcja str_replace() wyposażona została w nowy, opcjonalny parametr, który poprzez referencję zwraca ilość zastąpionych fraz:

<?
   $text = str_replace('fajne', 'super', 'PHP jest fajne, a użycie MySQL też jest fajne', $counter);
   echo "Nowy tekst: $text; zastąpiono <b>$counter</b> frazy!";
?>

Funkcja str_replace() jest wrażliwa na wielkość liter. W poniższym przykładzie, zastąpiona zostanie tylko jedna fraza, dlatego, że w łańcuchu znajduje się wyraz FAJNE, który jest pisany wielkimi literami:

 $text = str_replace('fajne', 'super', 'PHP jest FAJNE, a użycie MySQL też jest fajne', $counter);

Lekarstwem na to może być użycie funkcji str_ireplace() która została do PHP włączona dopiero w wersji 5.0. Nie rozróżnia ona wielkości liter; poza tym działa identycznie, co str_replace().

strstr()

string strstr ( string haystack, string needle)

Funkcja przeszukuje łańcuch haystack w poszukiwaniu frazy needle. Jeżeli takową znajdzie zwraca część łańcucha począwszy od niej do końca. Przykład:

<?
   echo strstr("[email protected]", "@"); // zwróci @server.com
?>

Funkcja ta jest wrażliwa na wielkość liter. Jeżeli nie chcesz, aby małe/wielkie litery były rozróżniane zastosuj funkcję stristr.

substr()

string substr ( string string, int start [, int length])

Funkcja umożliwia wycięcie części z podanego łańcucha (określonego w pierwszym parametrze). Drugi parametr, start określa pozycję, od której rozpocznie się wycinanie. Ostatni, opcjonalny parametr length określa ilość znaków do wycięcia:

<?php
echo substr("Gumisie, Kaczor Donald i Muminki to moje ulubione bajki", 9);

W tym przykładzie funkcja wytnie 9 pierwszych znaków z łańcucha i wyświetli napis Kaczor Donald i Muminki to moje ulubione bajki. Oto jak wyglądałaby ta funkcja, jeżeli chcielibyśmy zostawić jedynie frazę Kaczor Donald i Muminki:

echo substr("Gumisie, Kaczor Donald i Muminki to moje ulubione bajki", 9, 23);

Funkcja substr() akceptuje także parametry ujemne, w przypadkach, gdy chcemy wyciąć tekst znajdujący się na końcu frazy:

   echo substr("Gumisie, Kaczor Donald i Muminki to moje ulubione bajki", -19); // zwróci moje ulubione bajki

strpos()

int|false strpos ( string haystack, string needle [, int offset])

Funkcja strpos() zwraca liczbę typu integer, która określa pozycję frazy needle w łańcuchu haystack. Poniżej przedstawiam przykład sprawdzenia czy w adresie e-mail występuje znak @:

<?php
if (strpos("[email protected]", "@") === false) {
    echo 'Zły adres';
}

Funkcja zwraca położenie danego znaku (lub łańcucha), ale może to być także liczba 0, która oznacza, że znajduje się na pierwszej pozycji w łańcuchu. Funkcja zwraca też false, jeśli wyrażony podciąg nie znajduje się w ciągu głównym. Jest to szczególnie niebezpieczne, poprzez słabe typowanie PHP, dlatego że "loose comparison", czyli tzw. "luźne porównanie" sprawia że można przyrównać false do 0, i PHP właśnie to zrobi jeśli użyjemy ==. Należy więc pamiętać żeby zawsze używać ===, jeśli korzystamy z strpos().

Funkcja stripos() działa bardzo podobnie co strpos() z tym, że nie zwraca uwagi na wielkość znaków.

Referencje

Mówiliśmy o zmiennych jako o pojemniku do przechowywania danych. Taka zmienna identyfikowana jest poprzez nazwę. My nie musimy się o nic martwić ? to PHP odpowiada za umieszczenie zawartości zmiennej w odpowiedniej komórce pamięci.

Referencje są sposobem dostępu do wartości zmiennej poprzez różne nazwy. Należy bowiem rozróżnić dwie rzeczy jakimi są: wartość zmiennej oraz nazwa zmiennej. Ta sama wartość może być odczytana poprzez różne nazwy ? to właśnie umożliwia referencja.
Referencję utworzyć można poprzez operator &:

<?

  $a = 10;
  $b = &$a;
  
  echo $b;

?>

Dzięki temu utworzyliśmy powiązanie zmiennej $b, ze zmienną $a. Należy zaznaczyć, że od tej pory zarówno zmienna $b jak i $a wskazują na to samo miejsce w pamięci, a tym samym ? posiadają tę samą wartość. W powyższym przykładzie instrukcja echo wyświetli wartość 10.

Oto kolejny przykład:

<?
  $a = 10;
  $b = &$a;
  
  $a = 20;
  
  echo $b;
?>

Zauważ, że po utworzeniu referencji, wartość zmiennej $a zostaje zmieniona na 20, a w następnym wierszu wyświetlamy wartość zmiennej $b. Jednak w skutek działania tego skryptu i tak zostanie wyświetlona liczba 20. Wszystko dlatego, że zarówno $a i $b wskazuje na tę samą wartość.

Przekazywanie przez referencje

Przypomnij sobie fragment rozdziału, w którym omawialiśmy budowę funkcji. Do każdej funkcji można było przekazać parametr, na którym funkcja mogła swobodnie operować. Takie przekazywanie nazywa się przekazywaniem przez wartość. Polega to na utworzeniu lokalnej kopii zmiennej do wykorzystania jedynie przez funkcję. Oryginalna wartość zmiennej przekazanej do funkcji, nie zostaje w żaden sposób naruszona. Przykład:

<?
  function foo($value)
  {
     $value = 15;
  }
  
  $a = 10;
  foo($a);
  echo $a;
?>

Na samym początku deklarujemy zmienną $a i przypisujemy jej wartość 10, którą następnie przekazujemy do funkcji foo(). W funkcji modyfikujemy wartość przekazanego parametru, lecz zmienna $a nadal będzie posiadać wartość 10. Wszystko dlatego, że parametr funkcji foo() - $value ? jest jedynie kopią zmiennej $a.

Przekazywanie parametrów przez referencję jest szybsze i mniej "pamięciożerne", gdyż funkcja nie operuje na kopii zmiennej, ale na wartości oryginalnej. Wystarczy umieścić operator & przed nazwą parametru w funkcji foo():

<?
  function foo(&$value)
  {
     $value = 15;
  }
  
  $a = 10;
  foo($a);
  echo $a;
?>

W funkcji foo() następuje zmiana wartości parametru $value. Jako, że parametr $value wskazuje na tę samą wartość, co wartość zmiennej $a, instrukcja echo wyświetli liczbę 15.

Nie należy zapominać, że przekazywanie przez referencję wiąże się z przekazaniem zmiennej (lub instrukcji new ? o tym w dalszej części) ? inne wartości (np. stałe) nie są akceptowane, tak więc poniższe wywołanie zakończy się komunikatem błędu Only variables can be passed by reference:

foo(10); // stała, a nie zmienna

W PHP 5 możliwe jest ustawianie domyślnych wartości dla parametrów funkcji, które mają być przekazane przez referencje.
Usuwanie referencji
Normalnie za niszczenie danej zmiennej w trakcie działania programu, odpowiada funkcja unset():

  $a = 10;
  unset($a);
  echo $a;

W powyższym kodzie, zmienna $a nie będzie już dostępna. Funkcja unset() odpowiada także za niszczenie referencji. Nie usuwa jednak wartości z pamięci, lecz kasuje powiązanie pomiędzy zmiennymi. Oto przykład:

<?
  $a = 10;
  $b = &$a;

  $a = 20;
  unset($a);

  echo $b;
?>

W tym przykładzie funkcja unset() usuwa powiązanie zmiennej $a z $b, lecz sama wartość nie zostaje usunięta z pamięci. Wciąż, więc można odczytać wartość korzystając z odwołania do zmiennej $b. Taki kod spowoduje wyświetlenie na ekranie liczby 20.

PHP

5 komentarzy

i o klasach :<

Szkoda, ze nie opisano foreach. Tylko tej konstrukcji nie znam :P

Gdzieś wcięło kilka rozdziałów, o zmiennych i stałych i początkowe o operatorach. Coś się zchrzaniło.

Podziwiam Cie za to, ze chialo Tobie pisac sie az tyle, ale w koncu piszesz ksiazki ;)

Książki Pana Adama zawsze były na wysokim poziomie merytorycznym i były bardzo przejrzyste. Pozdrawiam