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. Echo a print 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
V 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() a 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() a 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() a 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šší:
- !
- &&
- ||
- =
- and
- xor
- 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:
- Komplikovanější operace u logických výrazů umisťovat na konec.
- 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
V 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).
V 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í HTML a PHP 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() a 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
V 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 HTML a CSS, 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?