Základní kurz 9: Pole

V části o datových typech jsme mluvili o čtyřech skalárních typech a zmínili také existenci datového typu pole (Array). Přišel čas se na pole podívat blíže.

U skalárních typů jsme také zmínili, že oproti složeným obsahují pouze jednu dále nedělitelnou hodnotu (a proto se jmenují skalární). Pole je složený typ, bude tedy obsahovat více hodnot.

Zápis pole

Pole se skládá z jednotlivých prvků a každý prvek je určený dvojicí klíč a hodnota. Jako příklad můžeme vzít tento základní kurz, který se skládá z jednotlivých kapitol:

$zakladniKurz = array(1 => "Úvod",
                    2 => "Co je potřeba?",
                    3 => "Nastavení editoru",
                    /* atd. */
                );

Pole se tedy definuje příkazem array(), do kterého zapíšeme jednotlivé prvky oddělené čárkami. Prvek se skládá z klíče a hodnoty, oddělených operátorem => (operátor přiřazení v poli). Za posledním prvkem pole čárka může být a nemusí. Prvky je možné psát všechny na jeden řádek, ale pokud jsou delší anebo jich je hodně, je lepší je dělit na řádky tak, jak je znázorněno v příkladu.

Od PHP 5.4 je možný i zkrácený zápis použitím hranatých závorek místo příkazu array():

$zakladniKurz = [1 => "Úvod",
                    2 => "Co je potřeba?",
                    3 => "Nastavení editoru",
                    /* atd. */
                ];

Prvek pole lze také definovat pouze hodnotou, v tom případě mu PHP klíč přidělí automaticky. A to tak, že pokud v poli není ještě použitý žádný číselný klíč, dostane vkládaný prvek nulu (pozor, ne jedničku!), jinak dostane číslo o 1 vyšší, než nejvyšší již existující (nezáporný) číselný klíč. Tedy když třeba nejdřív vložíte prvek s klíčem 3 a pak vložíte jen hodnoty, PHP bude pokračovat 4, 5, 6, …
// Následující definice $ovoce dají stejný výsledek:
$ovoce = array("jablko", "hruška", "švestka");
$ovoce = array(0 => "jablko", 1 => "hruška", 2 => "švestka");
// Následující definice $vikend dají stejný výsledek:
$vikend = array(6 => "sobota", 7 => "neděle");
$vikend = array(6 => "sobota", "neděle"); // neděle dostane klíč 7

Typ klíče a hodnoty

Zatím jsme viděli pole, kde klíč je číslo a hodnota řetězec, ale už formulace o číselných klíčích výše naznačuje, že to není jediná možnost.

Hodnota prvku pole může mít jakýkoliv datový typ. Cokoli může být v proměnné, může být i hodnotou pole. Dokonce i pole může být hodnota prvku jiného pole.

Klíč může být typu integer (číslo) nebo string (řetězec). Zbývající skalární typy (float a bool) se při pokusu je použít jako klíč pole přetypují se na integer, NULL se změní na prázdný řetězec a ostatní typy (pole, objekt, resource) generují varování Illegal offset type. Není ale důvod se vůbec snažit jiné typy než čísla a řetězce jako klíče v poli používat.

Když je klíčem pole řetězec obsahující jen celé číslo, automaticky se zkonvertuje na to číslo typu integer.

Poli, kde klíče nejsou čísla, ale řetězce, se říká asociativní pole.

Manipulace s prvky pole

Zadat pole tedy umíme, ale jak se dostaneme k hodnotám v poli? Velice jednoduše, za identifikaci pole napíšeme do hranatých závorek klíč požadovaného prvku:

// Máme-li pole $zakladniKurz definované výše:
echo $zakladniKurz[3]; // vypíše: Nastavení editoru

Hodnoty prvků pole je možné číst i zapisovat, práce s prvky pole je stejná jako s normálními proměnnými. Přiřazení hodnoty do pole na nějaký už existující klíč přepíše hodnotu, která pod tím klíčem v poli byla. Přiřazení hodnoty neexistujícímu klíči vytvoří nový prvek pole s daným klíčem. Lze také klíč vynechat a napsat jen prázdné hranaté závorky, v tom případě se vytvoří nový prvek a klíč se mu přidělí automaticky způsobem popsaným výše.

Prázdné hranaté závorky samozřejmě nejde použít pro čtení z pole, generuje to chybu úrovně fatal error. Když se pokusíte přečíst z pole hodnotu klíče, který tam není, vrátí se hodnota null a generuje se poznámka (notice). Pro zjištění, jestli prvek pole existuje, je možné použít příkaz isset, o kterém jsme už mluvili.

Ukázka:

<?php
$ovoce = array("jablko", "hruška", "švestka");
// Vypíše druhý prvek, tj. hruška
echo $ovoce[1];
// Přidá nový prvek a přidělí mu první volný klíč, tj. 3
$ovoce[] = "meruňka";
// Přepíše hodnotu s klíčem 2 (švestka)
$ovoce[2] = "broskev";
// Vloží novou hodnotu se zadaným klíčem
$ovoce[9] = "švestka";
// Zkontrolujte, jak nyní vypadá pole
var_dump($ovoce);
?>

Vícerozměrné pole

Jak jsme si řekli, prvkem pole může být dokonce i jiné pole. Pak vzniká tzv. vícerozměrné pole. Sice neplatí žádná speciální pravidla a analogicky se použije to, co jsme si ukázali už výše, ale pro začátečníky to může být matoucí, takže se na ně podíváme blíže.

Definice vícerozměrného pole:

$texty = array ("en" => array("pozdrav" => "hello"),
                    "cs" => array("pozdrav" => "ahoj"));

Definovali jsme proměnnou $texty, která obsahuje pole s klíči "en" a "cs". Prvek "en" je pole, které má jeden prvek "pozdrav" s hodnotou "hello". Prvek "cs" je také pole s jedním prvkem "pozdrav", ale hodnotou "ahoj"

Poznámka: Jestli se divíte, proč je pro češtinu klíč "cs" a ne "cz", kód češtiny podle ISO 639-1 je cs

Vypsání hodnoty z výše definovaného pole:

echo $texty["cs"]["pozdrav"]; // ahoj

Vložení pole do pole:
$nemecky = array("pozdrav" => "hallo");
$texty["de"] = $nemecky;
// Nebo i bez proměnné:
$texty["de"] = array("pozdrav" => "hallo");

Užitečné funkce při práci s poli

Funkcí pro práci s poli je hodně, podíváme se jen na několik těch nejčastěji používaných.

count


Jednou z nejčastěji používaných je funkce count, která vrátí počet prvků v poli.
<?php
$ovoce = array("jablko", "hruška", "švestka");
echo count($ovoce); // 3
?>

U vícerozměrných polí je možné nastavit druhý parametr na COUNT_RECURSIVE (je to název konstanty, takže bez uvozovek), v tom případě count započítá i všechny prvky vnořených polí.
<?php
$texty = array ("en" => array("pozdrav" => "hello"),
                    "cs" => array("pozdrav" => "ahoj"));

echo count($texty); // 2 prvky "en" a "cs"
echo count($texty, COUNT_RECURSIVE); // 4, "en", "cs", "en"/"pozdrav" a "cs"/"pozdrav
?>

implode a explode

Funkce implode převezme jako parametry oddělovač (řetězec) a pole a vrátí řetězec, ve kterém jsou vypsané všechny hodnoty pole, oddělené zadaným oddělovačem.

Opakem je funkce explode, která převezme oddělovač a text (řetězce) a text podle oddělovačů rozdělí do pole, které vrátí.

<?php
$tvaryText = "trojúhelník, čtverec, kruh";
$ovocePole = array("jablko", "hruška", "švestka");
$tvaryPole = explode(", ", $tvaryText);
$ovoceText = implode(", ", $ovocePole);

var_dump($tvaryPole);
var_dump($ovoceText);
?>

sort a deriváty

Seřadí pole. Návratová hodnota je jen true/false (úspěch/neúspěch) a seřazeno bude pole, které je předáno v parametru funkce. Původní klíče v poli se zahodí a setříděné pole bude mít nové klíče vzestupně od 0.

<?php
$ovoce = array("jablko", "hruška", "švestka", 8 => "meruňka", "broskev");
sort($ovoce);
var_dump($ovoce);
// 0 => 'broskev', 1 => 'hruška', 2 => 'jablko', 3 => 'meruňka', 4 => 'švestka'
?>

Funkci sort lze ve druhém parametru nastavit různé konstanty, které ovlivní způsob řazení. Například SORT_FLAG_CASE bude řadit bez ohledu na velikost písmen. Další jsou v manuálu.

Kromě toho existuje celá rodina funkcí, které také řadí pole, ale jiným způsobem. Například rsort se používá stejně jako sort, ale řadí v opačném pořadí. Funkce ksort místo podle hodnot řadí podle klíčů (a samozřejmě neodstraní z pole původní klíče). Funkce asort řadí stejně jako sort, ale zachová původní klíče v poli. A pak existují ještě kombinace jako krsort (řadí podle klíčů v opačném pořadí), arsort (řadí podle hodnot v opačném pořadí a zachová původní klíče) a tak dále.

array_keys

Funkce array_keys vrátí pole klíčů z předaného pole. Hodí se pokud máte asociativní pole a potřebujete seznam klíčů v něm.

Funkce má ještě další dva parametry, pomocí kterých je možné z pole vybrat jen klíče prvků s nějakou konkrétní hodnotou. Viz manuál.

Analogicky existuje také funkce array_values, kterou by bylo možné použít, pokud se chcete zbavit původních klíčů pole a získat pole souvisle očíslované indexy od 0.

funkce range a shuffle

Tyto funkce spolu nemají moc společného, ale jejich kombinace se dá šikovně využít.
Funkce range má dva povinné parametry (začátek a konec) a jeden nepovinný (krok). Vrátí pole, které představuje řadu od hodnoty začátek do hodnoty konec v zadaném kroku (výchozí je 1). Funkce umí vyrobit řadu čísel nebo písmenek.

Příklad:

$rada = range(1, 5);
// Výsledek bude stejný jako:
$rada = array(1, 2, 3, 4, 5);

Funkce shuffle náhodně prohází prvky v poli. Nevrací nové pole, mění rovnou to předané.

Kombinaci range a shuffle lze použít v situaci, kdy je třeba získat několik náhodných čísel (nebo písmen) z určitého rozmezí tak, aby žádné jedno číslo nebylo vybrané vícekrát.

(Poznámka: Toto řešení se používá pro výběr více různých čísel, pokud je potřeba jen jedno náhodné číslo z určitého rozmezí, je lepší použít funkci rand nebo mt_rand)

Příklad: Chceme vypsat tři navzájem různá náhodná čísla od 1 do 20.

$rada = range(1, 20); // vytvoříme řadu
shuffle($rada); // náhodně přeházíme
// a vypíšeme první tři prvky
echo $rada[0] . ", " . $rada[1] . ", " . $rada[2];

Speciální předdefinovaná pole

PHP obsahuje několik speciálních proměnných typu pole, které jsou předdefinované, to znamená, že jsou ve skriptu dostupné automaticky, aniž byste je museli nějak plnit.

Všechny tyto proměnné byste měli používat pouze pro čtení; Pokud potřebujete některou položku nějak upravovat, zkopírujte si ji do jiné proměnné.

Předdefinovaná pole jsou:
$_SERVER: Obsahuje různé běhové informace a informace o prostředí. Dá se odsud zjistit třeba jaký prohlížeč a z jaké IP adresy odeslal požadavek na stránku. Více informací v manuálu, nebo si zkuste vypsat obsah $_SERVER (poznámka: Ne každý server musí plnit všechny položky uvedené v manuálu a některé servery si mohou přidávat vlastní položky).
$_GET: Obsahuje případná data odeslaná metodou GET (přes <form method="GET" action="…">, nebo odkaz: example.com/skript.php?nazev=hodnota). Klíče v poli jsou názvy formulářových polí (uvedené v atributu name prvků), hodnoty jsou hodnoty polí. Více o odesílání hodnot na server si povíme později.
$_POST: Analogické k $_GET, ale obsahuje data odeslaná metodou POST. Více o odesílání hodnot na server si povíme později.
$_COOKIE: Obsahuje nastavené cookies (klíč je název cookie, hodnota je hodnota). Poznámka: Toto pole je pro čtení, cookies se nenastavují zápisem do něj! K tomu slouží funkce setcookie.
$_FILES: Obsahuje informace o nahraných souborech (například z formuláře přes <input type="file">)
$_SESSION: Obsahuje data session (relace). Těm se věnuje článek v pokročilejší části.
$_REQUEST: Tato proměnná obsahuje nějakou kombinaci $_GET, $_POST a $_COOKIE. Které z nich a s jakou prioritou (které pole „vyhraje“ v případě shody klíčů) závisí na nastavení PHP. Typické nastavení je buď $_GET a $_POST, nebo všechny tři.
$_ENV: obsahuje proměnné prostředí, ve kterém PHP běží.

Nejčastěji se budeme setkávat s prvními čtyřmi uvedenými, hlavně $_GET a $_POST při odesílání formulářů (tomu se bude věnovat celá pozdější kapitola tohoto kurzu.)

Vyzkoušejte si

1. Vytvořte si nějaké pole, vypište počet jeho prvků a poslední prvek.

2. Vytvořte si nějaké pole a pak ho vypište v HTML jako odrážkový seznam (<ul> / <li>)

3. Vypište, jaké všechny klíče obsahuje pole $_SERVER. Nechte si vypsat celé pole na svém serveru a podívejte se, jaké všechny hodnoty obsahuje.

4. Vytvořte skript, který vypíše obsah pole $_GET. Otevřete ho v prohlížeči a podívejte se, co vypíše. Pak zkuste v prohlížeči za adresu skriptu dopsat ?promenna=hodnota a potvrdit. Podívejte se, co vypíše skript tentokrát.

Řešení

1. Když pole bude v proměnné $pole, počet prvků je count($pole);, vypsání posledního prvku je echo $pole[count($pole) - 1];

2.

<?php
$pole = array("alfa", "beta", "gama");
$polozky = implode("<li>", $pole);
echo "<ul><li>" . $polozky . "</ul>";
?>

První <li> se musí vypsat v echo, protože implode před první položku oddělovat nevloží. Kdybychom chtěli mít v kódu i (nepovinné) ukončovací značky </li>, šlo by to přes implode("</li><li>", $pole); a v echo ještě místo "</ul>" dát "</li></ul>"

3. Výpis klíčů lze udělat například příkazem: echo implode(", ", array_keys($_SERVER));
Výpis proměnné $_SERVER pak jednoduše přes var_dump($_SERVER);

4. Když použijete var_dump($_GET);, v prvním případě by pole mělo být prázdné a ve druhém by tam měla být položka s klíčem promenna a hodnotou hodnota.

Máte návrh na vylepšení či doplnění článku? Obsahuje článek nepřesné informace, nebo v něm chybí něco důležitého?
Tento článek má diskusní vlákno na diskusi Jak Psát Web, kam můžete náměty a připomínky napsat.


Správcem webu Péhápko.cz je Joker, mail zavináč it-joker tečka cz. Informace o autorských právech a možnostech použití obsahu viz Autorská práva
Přihlášení