3.1
PHP
PHP je skriptovací programovací jazyk určený obvykle ke generování webového obsahu na straně webového serveru. V současné době se na serverech setkáváme běžně s verzemi 5.6, 7.1 a 7.2. Všechny příklady v těchto materiálech budou psány tak, aby pracovaly na obou těchto verzích. Pokud však vytváříte novou webovou aplikaci, použijte server s PHP verzí 7 a využijte možnosti jazyka PHP této verze. Kromě toho, že PHP 7 je významně rychlejší, nabízí i nové funkce, které se hodí zejména pro objektově orientované programování:
  • Deklarace parametrů funkce i se skalárními datovými typy (bool, float, int, string) a jejich typová kontrola,
  • určení datového typu návratové hodnoty funkce,
  • Null Coalesce Operator ??,
  • porovnávací „Spacechip“ operátor <==>,
  • pole definované jako konstanty,
  • anonymní třídy.
  • skupinová use deklarace,
  • nové funkce intdiv(),Generator::getReturn(),Closure::call()…,
  • datový typ void,
  • nastavení viditelnosti (public, private, protected) u třídních konstant,
  • spousta fatálních chyb byla konvertována na výjimky,
  • všechny E_NOTICE hlášení byly překlasifikovány na E_NOTICE, E_WARNING a E_DEPRICATED.
Opuštěno (Deprecated) v PHP 7 je:
  • starý (PHP4) způsob deklarace konstruktoru,
  • statické volání nestatických metod,
  • salt možnost u funkce password_hash(),
  • rozšíření ext/ereg nahrazeno ext/pcre,
  • rozšíření ext/mysql nahrazeno ext/mysqli a ext/pdo_mysql.
Více o přepracovaných, nových nebo opuštěných funkcích jazyka a zpětné kompatibilitě naleznete přímo na oficiálním webu php.net.
3.1.1
Základní syntaxe
Poznámka
V příkladech vysvětlujících danou problematiku budu pro názornost pojmenovávat proměnné, funkce a další struktury tak, aby i samotný název čtenáři mnoho napovídal. Čtenář mi jistě promine, že někdy budu používat anglické názvy a jindy zase české. V běžném programování jistě doporučuji vše pojmenovávat dle dohodnutých norem, ve kterých je obvykle koncensus nad angličtinou. Zde budu české názvy používat jen u drobných vysvětlujících příkladů ku prospěchu studenta a pochopení příkladu. Samotnému se mi ježí chlupy na těle při pohledu na diakritiku v názvech proměnných, tříd, rozhraních, konstant… U větších příkladů v kapitole 5 budu pro ukázku „dobrých praktik“ používat již jen angličtinu.
PHP se nejčastěji v jednoduchých příkladech vkládá do HTML, a tak tímto začneme i my zde. PHP píšeme mezi značky <?php a ?>. Jiné podoby nedoporučuji. Na serverech mohou být vypnuté a například <%, %>, <%= jsou již ve verzi 7 vyřazené. PHP můžeme vkládat v HTML kamkoliv a kolikráte chceme. Pokud budeme v souboru používat jen PHP, stačí jej na začátku otevřít pomocí <?php a ukončovat se již nemusí. Aby webový server předal soubor PHP interpretu a nikoliv rovnou do sítě webovému klientovi, nesmíme zapomenout zapsat souboru příponu php. I když se případně jedná o HTML stránku, tak nesmí mít příponu html nebo htm.
Příklad:
<h1><?php echo "Hello world!" ?></h<?php echo "1" ?>>
Výsledek:
<h1>Hello world!</h1>
V příkladu je použit příkaz echo, který se snaží svůj argument (argumenty) převést na řetězec a vypíše je na výstup. Podobně pracuje i příkaz print a funkce printf() nabízí formátovaný výstup, jak jsme zvyklí například u jazyka C. Echoprint můžeme zapisovat také jako funkce.
Příklad:
echo "Jedna"; echo ("Dva"); print "Tři"; print ("Čtyři"); printf ("Pět");
Výstup:
JednaDvaTřiČtyřiPět
PHP můžeme používat řádkové (//), blokové (/* … */) a dokumentační komentáře (/** … */). Jakmile začneme psát řádkový komentář, interpret jej chápe automaticky do konce řádku. Blokový komentář musí mít svůj začátek a konec a může jít přes více řádků. Komentáře interpret ignoruje.
Příklad:
echo 'Text'; //řádkový komentář /* Blokový komentář */ $x = 1 + 2/* + 3 */;
V PHP se u všech klíčových slov (echo, if, else, while, break…), tříd a funkcí nerozlišují velká a malá písmena. U názvů proměnných se velikosti rozlišují:
$prom = 1; $Prom = 2; eCHo $prom; //vypíše 1
Příkazy se oddělují středníkem (;).
3.1.2
Proměnné, konstanty, datové typy, přiřazení, operace
Proměnné jsou pojmenovaná místa v paměti, do kterých můžeme ukládat v průběhu běhu programu hodnoty. V PHP se proměnné nemusí deklarovat, nemusí se jim tedy určovat datový typ. Ten si PHP samo dle obsahu k proměnné určí. Proměnné můžeme začít rovnou používat v místě, kde je potřebujeme. Před názvem každé proměnné musí být znak $ (dolar). Název proměnné může obsahovat jen znaky a-b, A-B, 0-9 a _ (podtržítko), přičemž nesmí začínat číslem. U názvu proměnných se rozlišují velikosti písmen. Tomu říkáme, že jsou case-sensitive.
Proměnné vytvořené vně funkcí jsou přístupné jen vně funkcí (globální) a podobně proměnné vytvořené uvnitř funkce jsou přístupné jen uvnitř funkce (lokální). Proměnné uvnitř funkce se po vykonání funkce smažou z paměti. Tomu můžeme předejít pomocí klíčového slova static.
Příklad:
$x = 1; function fce() { $y = 2; echo "[x=$x,y=$y]"; } fce(); echo "[x=$x,y=$y]";
Výsledek:
[x=,y=2] [x=1,y=]
Navíc se dvakrát vypíše upozornění: „Notice: Undefined variable: ...“, které nás upozorňuje na pokus získání hodnoty z proměnné, která v paměti není.
Do proměnných ukládáme hodnotu pomocí operace přiřazení (=). Proměnnou, do které ukládáme hodnotu, píšeme vždy vlevo od rovná se. Napravo může být jakýkoliv výraz, který je nejprve vyhodnocen a jeho hodnota poté uložena. Přiřazení můžeme zřetězovat. Do proměnné můžeme také ukládat referenci na jinou proměnnou pomocí prefixu &.
1 + 2 = $x; //špatně $x = 1 + 2; //dobře x = 1 + 2 = 3 $x = $y = 3; // y = 3 a poté x = 3 $x = ($y = 4) + 5; // y = 4 a poté x = 4 + 5 = 9 $y = 6; // y = 6 $x = &$y; // x = reference na y echo $x; // 6 $y = 7; // y = 7 echo $x; // 7
Hodnoty v proměnných náleží vždy nějakému datovému typu. PHP má skalární datové typy (boolean, integer, float a string), složené datové typy (array, object) a speciální datové typy (resource a null). V PHP 7 jsou tu ještě callable, iterable, void.
Tabulka 8. Vybrané základní datové typy
Datový typ
Příklad hodnot
Popis
boolean
true nebo false
logická hodnota
integer
-1, 0, 1, 2, 3…
celočíselná hodnota
float
3.1415
desetinné číslo
string
"Text"
textový řetězec
array
[1,2,3,4]
pole hodnot
Zdali je proměnná patřičného datového typu, můžeme ověřit pomocí funkcí is_string(), is_bool(), is_float(), is_array(). Pokud chceme otestovat, je-li proměnná nastavená, použijeme isset(). Další užitečnou funkcí je empty(), která zjišťuje, je-li proměnná prázdná. Všechny výše uvedené pomocné funkce vrací logickou hodnotu. Funkce isset()empty() mohou u někoho vyvolat nejasnosti, proto uvedu příklady. U příkladu je použita funkce var_dump(), která vypíše obsah argumentu i s datovým typem. Pro přehled je v komentáři za příkazem napsán i jeho výsledek.
$x = 1; var_dump(isset($x), empty($x)); //bool(true) bool(false) var_dump(isset($y), empty($y)); //bool(false) bool(true) $x = 0; var_dump(isset($x), empty($x)); //bool(true) bool(true) $x = null; var_dump(isset($x), empty($x)); //bool(false) bool(true) $x = ""; var_dump(isset($x), empty($x)); //bool(true) bool(true) $x = [1,2,3,4]; var_dump(isset($x), empty($x)); //bool(true) bool(false) $x = []; var_dump(isset($x), empty($x)); //bool(true) bool(true)
Shrneme-li to, funkce isset() vrací true, pokud proměnná existuje a má jinou hodnotu než null. V opačných případech vrací false. Funkce empty() vrací false, pokud proměnná existuje a má neprázdnou hodnotu. V opačných případech vrací true. Mezi neprázdné hodnoty nepatří: 0 (int), 0.0 (float), "" (prázdný řetězec), null, false a prázdné pole.
Pokud chceme proměnnou zrušit, což se nám může hodit, pokud si chceme rychle uvolnit paměť, můžeme použít funkci unset().
Jistě vás i napadne možnost přetypování, tedy potřeby z hodnoty jednoho datového typu vytvořit pokud možno stejnou hodnotu jiného datového typu. Je zajímavé, jak funguje přetypování řetězce na číslo. Uveďme si několik příkladů, které možnosti lépe osvětlí:
echo "Převod z boolean:\n"; $bool = true; var_dump($bool); //bool(true) var_dump(strval($bool)); //string(1) "1" var_dump(intval($bool)); //int(1) var_dump(intval(false)); //int(0) var_dump(floatval($bool)); //float(1) echo "\nPřevod z celého čísla:\n"; $int = 1; var_dump($int); //int(1) var_dump((string) ($int)); //string(1) "1" var_dump((boolean) ($int)); //bool(true) var_dump((float) ($bool)); //float(1) echo "\nPřevod z floatu:\n"; $float = 1.2; var_dump($float); //float(1.2) var_dump((string) ($float)); //string(3) "1.2" var_dump((boolean) ($float)); //bool(true) var_dump((int) ($float)); //int(1) var_dump((int) ceil($float)); //int(2) echo "\nPřevod z řetězce:\n"; $text = "5 kg"; var_dump($text); //string(4) "5 kg" var_dump(boolval($text)); //bool(true) var_dump(intval($text)); //int(5) var_dump(floatval($text)); //float(5) var_dump(explode(" ", $text)); /* array(2) { [0]=> string(1) "5" [1]=> string(2) "kg" } */ echo "\nPřevod z pole:\n"; var_dump($pole); /* array(4) { [0]=> int(2) [1]=> int(4) [2]=> int(6) [3]=> int(8) } */ $pole = [2, 4, 6, 8]; var_dump(boolval($pole)); //bool(true) var_dump(intval($pole)); //int(1) var_dump(floatval($pole)); //float(1) var_dump(implode(",", $pole)); //string(7) "2,4,6,8"
Možnosti převodu jsou velmi široké. Můžeme použít funkce intval(), strval()…, nebo před výraz, který chceme přetypovat, vložit název výsledného datového typu v kulatých závorkách. Pokud převádíme celočíselné číslo na desetinné, nemusíme řešit nic speciálního. Opačně již musíme počítat se ztrátou desetinné části. Pomoci si však v případě potřeby můžeme zaokrouhlovacími funkcemi round(), floor()ceil(). Velmi pěkný je převod z řetězce na číslo, kdy se PHP snaží rozpoznat číslo z počátku řetězce. Pro převod z pole na řetězec a z řetězce na pole můžeme použít funkce implode()explode().
3.1.2.1
Logické hodnoty
Logická hodnota může nabývat pouze stav true (pravda) nebo false (nepravda). Krom funkcí, které vrací logickou hodnotu, máme i logické operace, jejichž výsledkem je také true nebo false.
Tabulka 9. Porovnávací operace
Operace
Význam
==
true, když jsou hodnoty shodné
===
true, když jsou hodnoty identické, tedy shodné v hodnotě i datovém typu
!=
true, když nejsou hodnoty shodné
<>
true, když nejsou hodnoty shodné
!==
true, když nejsou hodnoty shodné, nebo se nerovnají datové typy
>
true, když je levá hodnota větší než pravá
<
true, když je levá hodnota menší než pravá
>=
true, když je levá hodnota větší nebo rovná pravé
<=
true, když je levá hodnota menší nebo rovná pravé
Logické výrazy mohou být komplikovanější než jen jedno porovnání hodnot. Pokud potřebujeme složit větší výraz z několika základních, můžeme použít logické spojky a priority určovat pomocí kulatých závorek.
Tabulka 10. Logické operace
Spojka
Význam
!
unární negace
and
Logický součin. true, když jsou oba výrazy true.
or
Logický součet. true, když je alespoň jeden výraz true.
xor
Exklusivní součet. true, když jsou výrazy různé.
&&
Logický součin. true, když jsou oba výrazy true.
||
Logický součet. true, když je alespoň jeden výraz true.
Rozdíl mezi and/or a &&/|| je v prioritách. Seznam operací dle priorit od nejvyšší:
  1. !
  1. &&
  1. ||
  1. =
  1. and
  1. xor
  1. or
Praktický příklad:
var_dump(true || true || false); // true var_dump(true && false && false); // false var_dump(false || true && false); // false var_dump(false || true && true); // true var_dump(true and false or false); // false var_dump(true xor false); // true var_dump(true xor true); // false $x = true and false; // (x = true) and false var_dump($x); // true $x = true && false; // x = (true && false) var_dump($x); // false
Také je dobré neopomenout, že jakmile je výsledná hodnota výrazu známa, zbytek výrazu je již nevyhodnocuje. Z toho by si programátor měl vyvodit dvě pravidla:
  1. Komplikovanější operace u logických výrazů umisťovat na konec.
  1. Vyvarovat se přiřazovacím operacím ve výrazech, u kterých není jasné, že se provedou.
Příklad:
$x = 1; var_dump(true || ++$x == 2); // true var_dump($x); // 1 var_dump(false || ++$x == 2); // true var_dump($x); // 2 var_dump(false || $x++ == 2); // true var_dump($x); // 3
3.1.2.2
Čísla
PHP můžeme zapsat čísla ve dvojkové, osmičkové, desítkové a šestnáctkové soustavě. Každý zápis má svá pravidla.
Tabulka 11. Struktura zápisu celočíselných hodnot pro různé číselné soustavy
Soustava
Struktura čísla
dvojková
0[bB][01]+
osmičková
0[0-7]+
desítková
[1-9][0-9]* | 0
šestnáctková
0[xX][0-9a-fA-F]+
Celočíselná (integer) čísla jsou vždy znaménková z intervalu určeného předdefinovanými PHP konstantami <PHP_INT_MIN;PHP_INT_MAX >. Konstanty se mohou lišit na 32b a 64b systémech.
Desetinná čísla se zapisují s desetinnou tečku (2.3, -5.1, .564) a může se použít i zápis s uvedením exponentu (1E2, -1.4E5, 123E-4).
PHP máme 6 aritmetických operátorů.
Tabulka 12. Aritmetické operátory
Operace
Význam
+
unární plus (kladná hodnota) nebo sčítání
-
unární mínus (záporná hodnota) nebo odčítání
*
násobení
/
dělení
%
zbytek po dělení
**
exponent
Existuje více variací na tyto operace. Známe i inkrementaci (++) a dekrementaci (--), u kterých rozlišujeme variantu pre a post. Pak máme zkrácené zápisy (+=, -=, /=, *=). Pro vlastní určení priorit můžeme použít standardní kulaté závorky. Nejlépe si to ukážeme na příkladech.
$x = 2; $y = 3; $z = $x + $y; //z = 2 + 3 = 5 $z = $x + $y * 2; // z = 2 + (3 * 2) = 8 $z = ($x + $y) * 2; // z = (2 + 3) * 2 = 10 $x++; // x = x + 1 = 2 + 1 = 3 $z = ++$x - $y; // nejprve x = x + 1 = 3 + 1 = 4 a poté z = 4 - 3 = 1 $x += $y; // x = x + y = 4 + 3 = 7 $x /= 2; // x = x / 2 = 3.5 $x = $z % 2; // x = 1 (zbytek po dělení 7/2) $z = 3 + -$x++; // z = 3 + (-1) = 2 a poté x = x + 1 = 1 + 1 = 2 $z = $x**$y; // z = x * x * x = 2 * 2 * 2 = 8 $z -= 2; // z = z - 2 = 8 - 2 = 6 $z = -$x + -(--$y); // nejprve y = y – 1 = 3 – 1 = 2 a poté z = -2 + -2 = -4
Pro celočíselné hodnoty máme k dispozici bitové operace.
Tabulka 13. Bitové operace
Operace
Význam
&
AND - bitový součin
|
OR - bitový součet
^
XOR – bitový exklusivní součet
~
NOT – bitová negace
<<
bitový posun vlevo – násobení dvěma
>>
bitový posun vpravo – dělení dvěma
3.1.2.3
Řetězce
Práce s řetězci je velmi jednoduchá a intuitivní. Textový řetězec musí být uvozen a ukončen buď uvozovkami ("), nebo apostrofy ('). V textovém řetězci obaleném uvozovkami můžeme používat jednoduše apostrofy, a pokud chceme uvozovky, musíme použít tzv. escape sekvenci. To platí i obráceně. V uvozovkách můžeme použít escape sekvence \n, \r, \t, \v, \\, \" a další. V řetězcích obalených apostrofy můžeme použít jen \\ a \'. Další rozdíl je v tom, že proměnné v textovém řetězci obaleném uvozovkami jsou nahrazovány svým obsahem, kdežto u řetězců v apostrofech nikoliv. Textové řetězce se spojují operátorem tečka (.). Tak jako u zkrácených aritmetických operací, můžeme použít i zkrácený zápis pro spojení řetězců (.=), který značí přilepení řetězce na konec původního řetězce. K textovým řetězcům můžeme přistupovat jako k poli znaků. To vše si pro názornost uvedeme v příkladu:
echo 'Zde píši "uvozovky".\n'; echo "Zde píši 'apostrofy'.\n"; echo 'Zde píši "uvozovky" i \'apostrofy\'.' . "\n"; echo "Zde píši \"uvozovky\" i 'apostrofy'.\n"; echo "Spojujeme" . " " . "více " . 'řetězců' . ' do jednoho.' . "\n"; $sloveso = 'je'; echo "Toto $sloveso řetězec.\n"; echo "Toto $sloveso[0]e řetězec.\n"; echo 'Toto $sloveso řetězec.' . "\n"; echo 'Toto ' . $sloveso . ' řetězec.' . "\n";
Výstup:
Zde píši "uvozovky".\nZde píši 'apostrofy'. Zde píši "uvozovky" i 'apostrofy'. Zde píši "uvozovky" i 'apostrofy'. Spojujeme více řetězců do jednoho. Toto je řetězec. Toto je řetězec. Toto $sloveso řetězec. Toto je řetězec.
PHP disponuje mnoha funkcemi pro práci s řetězci. Můžeme tak v řetězci vyhledávat, získávat podřetězce, převádět na pole a mnoho dalších funkcí.
Tabulka 14. Vybrané funkce pro práci textovými řetězci
Funkce
Popis
explode()
Převádí řetezec na pole prvků. Můžeme si určit oddělovací řetězec.
html_entity_decode()
Převádí HTML entity v řetězci na jejich korespondující znaky.
htmlentities()
Znaky v řetězci, které je možné konvertovat, konvertuje na jejich HTML entity.
htmlspecialchars()
Všechny speciální znaky (ampersand, uvozovky, apostrofy, menší než, větší než) konvertuje na HTML entity.
htmlspecialchars_decode()
inverzní funkce k htmlspecialchars()
str_replace()
Nahrazuje podřetězce v řetězci jinými řetězci.
strip_tags()
odstranění HTMLPHP značek z řetězce
strlen()
Vrací délku řetězce.
strpos()
Vrací pozici prvního nalezení hledaného podřetězce.
strtolower()
Převede všechny znaky A-Z na a-z.
substr()
Vrátí podřetězec řetězce.
trim()
Odstraní neviditelné znaky (mezery, nové řádky, tabulátor…) ze začátku i konce řetězce.
3.1.2.4
Pole
PHP má velmi flexibilní pole. Pro připomenutí uvedu, že pole je množina prvků, kde každý má svou hodnotu a klíč. Pomocí klíče prvku se v poli dostaneme k jeho hodnotě. U pole v PHP nemusíme udávat počet prvků. Pole mohou mít smíšené datové typy hodnot svých prvků. Pole mohou být asociativní a klíče prvků mohou být také smíšené. Pole mohou být vícerozměrná.
Tabulka 15. Operace s poli
Operace
Význam
+
sjednocení polí (UNION)
==
true, když levé i pravé pole mají stejné prvky (klíče i hodnoty)
===
true, když levé i pravé pole mají stejné prvky i ve stejném pořadí
!=
true, když pole nejsou shodná
<>
true, když pole nejsou shodná
!==
true, když pole nejsou identická (prvky ani pořadí)
Analyzujte rozdíl mezi operací + a array_merge().
PHP má mnoho desítek funkcí, které s poli pracují. Některé velmi používané funkce si uvedeme.
Tabulka 16. Vybrané funkce pro práci s poli
Funkce
Popis
array()
Vytvoří pole.
range()
Vytvoří pole prvků v daném rozmezí hodnot.
count()
Vrací počet prvků pole.
in_array()
Zjistí, je-li prvek s hledanou hodnotou v poli.
array_key_exists()
Zjistí, je-li prvek s hledaným klíčem v poli.
sort()
Seřadí prvky pole. (Řadících funkcí existuje mnoho, řadit můžeme vzestupně, sestupně, podle hodnot, podle klíčů, se zachováním vazby klíč – hodnota…)
array_merge()
Sloučí více polí do jednoho.
Každé pole má svůj vnitřní ukazatel na aktuální prvek. Pomocí funkce current() získáme hodnotu aktuálního prvku. Pomocí funkcí end(), prev(), next()reset() se můžeme v poli po prvcích pohybovat.
Pokud neuvedeme při vytváření prvků pole jejich klíče, PHP nám automaticky vytvoří klíče číselné. Nezapomínejme, že podobně jako u jiných programovacích jazyků má první prvek klíč s hodnotou 0 (nula). Na jednotlivé prvky pole se dostáváme pomocí hranatých závorek ([ a ]). Pokud při ukládání prvku do pole neuvedeme v hranaté závorce hodnotu klíče, bude prvek přidán na konec pole a klíč se automaticky vygeneruje jako další číselný. Pokud hodnotu klíče uvedeme a v poli se prvek s uvedeným klíčem nachází, tak se jeho hodnota přepíše na novou. Pokud takový klíč v poli není, vytvoří se nový prvek pole se zadaným klíčem a hodnotou. Více to osvětlí příklad na jednorozměrná pole:
var_dump(array(1, 2, 3)); var_dump([1, 2, 3]); var_dump([1 => 1, 2, 3]); var_dump(['red' => 'červená', 'green' => 'zelená', 'blue' => 'modrá']); $pole = [1, 2.2, 'A']; var_dump($pole[2]); $pole[2] = 'B'; var_dump($pole[2]); $pole[] = 'C'; var_dump($pole[3]); $pole[55] = 'D'; var_dump($pole[55]); var_dump($pole);
Výsledek:
array(3) { [0]=> int(1) [1]=> int(2) [2]=> int(3) } array(3) { [0]=> int(1) [1]=> int(2) [2]=> int(3) } array(3) { [1]=> int(1) [2]=> int(2) [3]=> int(3) } array(3) { ["red"]=> string(9) "červená" ["green"]=> string(7) "zelená" ["blue"]=> string(6) "modrá" } string(1) "A" string(1) "B" string(1) "C" string(1) "D" array(5) { [0]=> int(1) [1]=> float(2.2) [2]=> string(1) "B" [3]=> string(1) "C" [55]=> string(1) "D" }
Vícerozměrná pole jsou taková pole, jejichž prvky jsou opět pole a případně jejich prvky zase pole atp. Pro jednoduchost si dvourozměrné pole představme jako obdélníkové hrací pole, kde má každé políčko svou souřadnici zadanou svou horizontální a vertikální pozicí. Více jak třírozměrná pole si lidé špatně představují a není k tomu vlastně ani důvod si tato pole představovat. Je potřeba si jen prakticky uvědomit, že abychom se dostali k  hodnotě daného prvku, potřebujeme znát více klíčů. Například jako kdybychom měli velkou databázi všech existujících automobilů. Abychom se dostali k tomu konkrétnímu, musíme znát jeho výrobce, model, karoserii, motorizaci… Uveďme si příklad pro dvourozměrné pole.
$pole = [['A','B','C'],['D','E','F']]; var_dump($pole); echo $pole[0][2]; //C
Výsledek pak vypadá takto:
array(2) { [0]=> array(3) { [0]=> string(1) "A" [1]=> string(1) "B" [2]=> string(1) "C" } [1]=> array(3) { [0]=> string(1) "D" [1]=> string(1) "E" [2]=> string(1) "F" } } C
PHP disponuje i několika vestavěnými superglobálními poli, tedy poli, která jsou přístupná odkudkoliv ve vašem zdrojovém kódu. U většiny z nich samotné PHP připraví před vykonáním vašeho skriptu jejich prvky, které můžete ve skriptu používat. Takováto pole poznáme jednoduše, jsou připravená jako proměnné, které začínají obvykle podtržítkem (_).
Tabulka 17. Superglobální pole
Pole
Popis
$GLOBALS
Pole globálních proměnných, ke kterému můžeme přistupovat i v těle funkcí. Klíčem prvku je název proměnné, hodnotou je pak její hodnota.
$_SERVER
Pole informací ze serveru. Najdeme v něm IP adresu serveru, název software webového serveru, protokol, URI, ale i adresu, ze které se na server přišlo a další data…
$_REQUEST
data odeslaná formulářem
$_GET
data odeslaná formulářem metodou GET
$_POST
data odeslaná formulářem metodou POST
$_FILES
informace o souborech odeslaných formulářem na server
$_COOKIE
pole s uloženými COOKIE
$_SESSION
Pole pro data, která jsou perzistentní v rámci sezení.
Není bezpečné číst data odeslaná formulářem přímo z polí $_GET, $_POST a $_REQUEST. Data mohou být podvržena. K těmto polím přistupujte pomocí funkce filter_input(), kde můžeme vstupní data jak validovat (ověřit jejich podobu), tak sanitizovat (upravit do požadované podoby). Tímto způsobem si můžeme zajistit, že získáme opravdu základní řetězec, číslo, email…
$email = filter_input(INPUT_GET, 'email', FILTER_SANITIZE_EMAIL);
Server ke každé vygenerované stránce přistupuje individuálně, tedy veškeré proměnné jsou po skončení skriptu smazány z paměti a server je připraven na obsluhu dalšího požadavku. Mnohdy však potřebujeme hodnoty v proměnných zachovat do další stránky. Příkladem je udržení přihlášení uživatele, vložené produkty v košíku a podobně. K tomuto účelu slouží pole $_SESSION. Na začátku skriptu, ještě před jakýmkoliv výpisem, tedy než se pošle klientovi HTTP hlavička, se musí session nastartovat funkcí session_start(). Poté se již jen zapisuje a čte z perzistentního pole $_SESSION. Pustíme nejprve a.php:
<?php session_start(); $_SESSION['x'] = 'X';
Poté pustíme skript b.php:
<?php echo $_SESSION['x'];
Hodnota „X“ se v poli pod klíčem „x“ uchová i pro b.php, kde je vypsána.
3.1.2.5
Konstanty
Konstanty oproti proměnným si jen jednou nadefinujeme a poté nesmíme jejich hodnoty měnit. Konstanty můžeme definovat pomocí funkce define() nebo klíčového slova const. Konstanty definované mimo funkce můžeme ve funkci použít a i obráceně – konstanty definované uvnitř funkce můžeme použít vně. Toto nelze u definice pomocí const. Konstantu voláme buď jednoduše svým názvem, nebo funkcí constant(). Názorně je to ukázáno v příkladu:
define("KONSTANTA_1", "1\n"); const KONSTANTA_2 = "2\n"; echo constant("KONSTANTA_1"); //1 echo KONSTANTA_2; //2 fce(); echo KONSTANTA_1; //1 echo KONSTANTA_2; //2 echo KONSTANTA_3; //3 const KONSTANTA_4 = ["A\n", "B\n", "C\n"]; echo KONSTANTA_4[1]; //B function fce() { define("KONSTANTA_3", "3\n"); //const KONSTANTA_4 = "4\n"; //nelze echo KONSTANTA_1; //1 echo KONSTANTA_2; //2 echo KONSTANTA_3; //3 }
3.1.3
Řídící struktury
Do řídících struktur patří podmínky a cykly. Podmínky se nám umožňují program větvit, cykly umožňují části kódu opakovat. Základní podmínka if, která je používána většinou programovacích jazyků, platí i v PHP. Tuto podmínku lze zřetězovat, vnořovat, definovat i alternativní větev… Argument v podmínce je vždy vyhodnocen jako boolean. Ukažme si několik příkladů:
$x = -3; if (is_numeric($x)) { if ($x == 0) { echo 'nula'; } elseif ($x > 0) { echo 'kladné'; } else { echo 'záporné'; } } else { echo 'není číslo'; }
Někdy je efektnější při více větvích použít switch. U něho můžeme použít zřetězení operací (kaskády), dokud z větve nevyskočíme příkazem break.
Mějme kód:
switch ($x) { case 'a': case 'b': case 'c': echo 'X'; break; case 'd': echo 'Y'; case 'e': echo 'Z'; break; default: echo '-'; }
Pak jeho výstup v závislosti na proměnné x bude takovýto:
Tabulka 18. Výstup struktury switch z uvedeného příkladu
Proměnná x
Výstup
a
X
b
X
c
X
d
YZ
e
Z
cokoli jiného
-
Poslední podmínkou je ternární operátor, který můžeme chápat jako inline podmínku. Tedy v místě volání se přímo objeví dle vyhodnocení logického výrazu jedna ze dvou hodnot. Výhodné je toto použít právě na místech, kde se očekávají hodnoty, které určujeme podmínkou a nechceme program rozepisovat na několik řádků. Syntaxe ternárního operátoru je jednoduchá:
logický_výraz ? hodnota_při_true : hodnota_při_false;
Ternární operátory je možné do sebe vnořovat. Pojďme si to ukázat na příkladu, kde tutéž situaci napíšeme jak standardní podmínkou, tak pomocí ternárního operátoru:
$c = 1; echo "Máme $c "; if ($c == 1) { echo "úl"; } else if ($c > 1 && $c < 5) { echo "úly"; } else { echo "úlů"; } echo ". "; echo "Máme $c " . ($c == 1 ? "úl" : ($c > 1 && $c < 5 ? "úly" : "úlů")) . ".";
Ternární operátor používejme s rozmyslem. Program by měl být stále dobře čitelný a pochopitelný. To řeší strategie KISS.
3.1.4
Funkce
PHP jsou stovky již připravených funkcí, které můžeme obratem používat. Není třeba vkládat do úvodů zdrojových kódů nějaké knihovny a podobně. Automaticky máme přístup k funkcím pro práci s poli, textovými řetězci, datem a časem, čísly, souborovým systémem a mnoho dalších okruhů činností. Jednotlivé funkce jsou dobře popsány v manuálu PHP. Není je tedy třeba vysvětlovat.
Funkce si můžeme vytvářet vlastní. Zejména v OOP je velmi zásadní znalost práce s funkcemi. Funkce se deklaruje pomocí klíčového slova function, za kterým následuje název funkce, v kulatých závorkách parametry a za nimi ve složených závorkách samotné tělo funkce. V PHP se neudává návratový typ. Pokud tvoříme funkci bez parametru, stejně kulaté závorky uvádíme. Funkci voláme jejím názvem, za kterým vždy uvádíme i kulaté závorky. Příklad jednoduché funkce bez parametrů, která po svém zavolání vypíše aktuální čas:
printTime(); function printTime(){ echo date("H:i:s") . "<br>"; }
Všimněme si, že funkci můžeme deklarovat až po jejím volání. Funkce nemusí nic vracet. Další příklad ukáže funkci s proměnným počtem parametrů, která bude vracet jejich součet:
echo "Výsledek je " . suma(1) . ".<br>"; echo "Výsledek je " . suma(1, 2) . ".<br>"; echo "Výsledek je " . suma(1, 2, 3) . ".<br>"; function suma($x, $y = 0, $z = 0) { return $x + $y + $z; }
Kde výsledek je:
Výsledek je 1. Výsledek je 3. Výsledek je 6.
Funkce má vlastní paměťový prostor. Proměnné vytvořené ve funkci nejsou přístupné vně a obráceně.
$x = 1; echo $x; fce(); echo $x; function fce() { $x = 2; echo $x; }
Výstup:
121
Můžeme však použít & (ampersand) pro adresu proměnné (ukazatel):
$x = 1; echo $x; fce($x); echo $x; function fce(&$x) { $x = 2; echo $x; }
Výstup:
122
Příkaz return ukončí provádění funkce a vyhodnocený výraz zapsaný hned za returnem se vloží do místa volání funkce. Pokud tedy existuje nějaký kód za returnem, nikdy se nevykoná. Efektně jej však můžeme využít v podmínkách. Příkazů return může být ve funkci více. Zase však pozor na přehlednost kódu. Oproti jiným jazykům může jedna funkce v PHP vracet hodnoty různých datových typů. Výše uvedené vlastnosti si předveďme v příkladu:
if (($x = divide(1, 2)) !== false) { echo $x; } function divide($x, $y) { if ($y == 0) { return false; } return $x / $y; }
Výsledek:
0.5
Toto je trochu krkolomný příklad, ale jednoduše demonstruje vše potřebné. Zrovna operace dělení nulou by se dala řešit vyhozením výjimky. O tomto ale až později.
PHP podporuje anonymní funkce, tedy funkce, u kterých nezadáváme jejich název. Jednoduchý příklad:
$fce = function($n) { print($n * $n); }; $fce(2);
Výstup:
4
V tomto příkladu se naše jednoduchá anonymní funkce uložila do proměnné, kterou je poté hned volána. Pojďme si ukázat něco praktičtějšího, tedy použití anonymní funkce v parametru jiné funkce. Pomocí funkce array_map() a naší anonymní funkce si vypíšeme jednotlivé prvky zadaného pole:
array_map(function($item) { printf("%s ", $item); }, array(1, 2, 3, 4, 5));
Výstup:
1 2 3 4 5
3.1.5
Chyby a ladění kódu
Ladění PHP kódu se může zdát obtížné, je-li spouštěn na straně serveru. Samotné PHP nám nenabízí žádný sofistikovaný způsob ladění. Použít můžeme hotová externí řešení jako například Tracy z Nette, která je také známá pod označením „Laděnka“. Samotné PHP nám nabízí funkce var_dump(), var_export() a debug_zval_dump():
$promenna = 1.1; var_dump($promenna); debug_zval_dump($promenna); var_export($promenna); echo "\n"; $pole = array(1, 1.1, '2.1', true); var_dump($pole); debug_zval_dump($pole); var_export($pole);
Výsledek:
float(1.1) double(1.1) refcount(2) 1.100000000000000088817841970012523233890533447265625 array(4) { [0]=> int(1) [1]=> float(1.1) [2]=> string(3) "2.1" [3]=> bool(true) } array(4) refcount(2){ [0]=> long(1) refcount(1) [1]=> double(1.1) refcount(1) [2]=> string(3) "2.1" refcount(1) [3]=> bool(true) refcount(1) } array ( 0 => 1, 1 => 1.100000000000000088817841970012523233890533447265625, 2 => '2.1', 3 => true, )
Funkce var_dump() nám zobrazí hodnotu a datový typ svého argumentu. Funkce debug_zval_dump() navíc i počet referencí. Funkce var_export() vypíše proměnnou tak, že je ji možné použít rovnu v PHP.
PHP nám přináší i magické konstanty __LINE__ (aktuální řádek), __FILE__ (aktuální soubor), __DIR__ (adresář aktuálního souboru),__CLASS__ (aktuální třída), __METHOD__ (aktuální metoda), __FUNCTION__ (aktuální metoda). Programátoři si spolu s výše uvedenými magickými konstantami a funkcemi vytváří obvykle svá jednoduchá řešení, která umí například i logovat výpisy proměnných do souboru.
Příklad na magické konstanty:
function fce() { echo "soubor: " . __FILE__ . "\nřádka: " . __LINE__ . "\nfunkce: " . __FUNCTION__; } fce();
Výsledek pak může vypadat takto:
soubor: C:\xampp\htdocs\ODZ\K3_PHP\index.php řádka: 5 funkce: fce
Potlačit chyby můžeme pomocí @-operátoru, který je možné psát před výrazy. Podívejme se na příklad s chybami, které však nejsou vypsané.
$pole = [1,2,3]; echo @$pole[100]; // žádný Notice: Undefined offset: 100 $concent = @file_get_contents('soubor.txt'); // žádný Warning: No such file or directory
Velmi důležitá je funkce error_reporting(), která nastavuje, jaké typy chyb chceme vypisovat. Pro vývoj, doporučuji mít nastavené E_ALL. Jinak máme možnost povolovat, či zakazovat poznámky (E_NOTICE), upozornění (E_WARNING), chyby za běhu (E_ERROR) a další. Na serverech v produkčním režimu jsou obvykle vypnuté poznámky a upozornění.
PHP umožňuje ošetřování vzniklých chyb i za pomocí výjimek (Exception). Výjimky jsou objekty, a proto je tomuto tématu věnováno více v kapitole 4.10.
3.1.6
Shrnutí jazyka PHP
Souhrn
V této kapitole jsme se poměrně podrobně seznámili s jazykem PHP, který slouží obvykle ke generování webového obsahu, zejména pak v podobě HTML. Jelikož této kapitole předcházely klientské technologie HTMLCSS, tak by měl nyní čtenář být schopen samostatně vytvořit kvalitní dynamický web či jiné webové skripty dle zadání. Pro větší webové systémy doporučuji dále nastudovat objektové programování a práci s databází.
Jaký bude výsledek operace (0x10 + 0b10 + 010)?
Jakou hodnotu má logický výraz (FALSE OR !FALSE AND 0)?
Co vypíše příkaz printf("\"\\/I\\//\\T PHP\"");?
Jaký je výsledek operace ((1+.5/-2)+-.5*-1)?
Co vypíše příkaz print(-1/*2*/+1);?
Jakou hodnotu má výraz (TRUE > FALSE)?
Jaký operand slouží pro spojování řetězců?
Jaká funkce převede řetězec dle vybraného oddělovače na pole jeho podřetězců?
Může hodnota prvku pole být opět polem?
Musí funkce v PHP vracet vždy hodnoty stejného datového typu?
Vykonává se PHP kód na straně webového klienta, tedy webovým prohlížečem?