Pole
Pole jsou zvláštním typem proměnných, na rozdíl od normálních proměnných mohou obsahovat více hodnot. Pole se skládá z více prvků, z nichž každý má svou hodnotu. K jednotlivým hodnotám se odkazuje pomocí indexu (klíče). Normálně je indexem celé číslo. Implicitně indexy začínají od nuly. Indexem ale může být i řetězec.
Jednoduchá pole
Nejjednodušším typem je pole obsahující sérii prvků s indexy začínající nulou a inkrementálně se zvyšujícími. Například, když budeme mít pole $Zeme a každý jeho prvek bude obsahovat dvoupísmenný kód země, bude to vypadat takto:
| Zápis | Hodnota |
| $Zeme[0] | "cz" |
| $Zeme[1] | "sk" |
| $Zeme[2] | "de" |
| $Zeme[3] | "uk" |
| $Zeme[4] | "fr" |
Na rozdíl od jazyka C mohou pole v PHP obsahovat prvky více datových typů. V C musí být všechny prvky pole stejného datového typu, ale PHP je mnohem flexibilnější. Každý prvek může mít jiný datový typ bez ohledu na datové typy ostatních prvků pole.
Inicializace polí
Existuje více způsobů, jak inicializovat pole. Nejjednodušší je přímé přidání hodnoty. To se provede zápisem proměnné následovanou párem hranatých závorek.
<?php
$Zeme[] = 'cz';
$Zeme[] = 'sk';
$Zeme[] = 'de';
$Zeme[] = 'uk';
$Zeme[] = 'fr';
?>
Tento kód nám vytvoří pole, které je vykresleno v tabulce výše. Obsahuje 5 prvků, které se automaticky očíslují 0 až 4. Pokud se pokusíme příkazem echo vypsat například $Zeme[3], získáme "uk".
Klíče si ale můžeme určit i explicitně uvnitř hranatých závorek.
<?php
$Zeme[0] = 'cz';
$Zeme[1] = 'sk';
$Zeme[2] = 'de';
// Obvykle je praktické přiřazovat index postupně, tak, jak jsme to udělali výše, ale
// pokud je to potřeba, můžeme přiřazovat celočíselné indexy tak, jak budeme potřebovat:
$Zeme[50] = 'ca';
$Zeme[10] = 'fr';
$Zeme[20] = 'us';
echo $Zeme[20]; // Vypíše: us
?>
Pokud přiřazujete prvkům indexy nespojitě, pak budoucímu jednoduchému přiřazení (tj. bez explicitního uvedení indexu) bude přiřazen index o jedničku vyšší, než je nejvyšší index pole.
<?php
$Zeme[50] = 'ca';
$Zeme[10] = 'fr';
$Zeme[20] = 'us';
$Zeme[] = 'cz'; // Dostane index 51
?>
Jiným způsobem inicializace pole je použití vestavěné funkce array(). Jednoduše funkci array() předáme hodnoty, které chceme přiřadit k našemu novému poli.
<?php
$RajskySalat = array('rajče', 'cibule', 'sůl', 'cukr', 'pepř');
echo $RajskySalat[2]; // Vypíše: sůl
// Další prvky už lze do vytvořeného pole přidávat pouze takto:
$RajskySalat[5] = 'voda';
$RajskySalat[] = 'ocet'; // Index 6
$RajskySalat[7] = 'olej';
echo $RajskySalat[6]; // Vypíše: ocet
?>
V této funkci také můžeme použít speciální operátor =>, který nám umožní v našem poli používat specifické indexy. Ne vždy se například hodí, aby pole začínalo indexem 0, například budeme chtít, aby začínalo jedničkou.
<?php
$Mesic = array(1 => 'leden', 'únor', 'březen', '...'); // A tak dále...
echo $Mesic[2]; // Vypíše: únor
?>
Operátor => lze použít před kterýmkoliv prvkem. Také si ukážeme použití indexů, které obsahují řetězec. Nijak se v použití neliší.
<?php
$RajskySalat = array('rajče', 4 => 'pepř', 2 => 'cibule', '...'); // A tak dále...
echo $RajskySalat[0]; // Vypíše: rajče
echo $RajskySalat[2]; // Vypíše: cibule
echo $RajskySalat[4]; // Vypíše: pepř
?>
Práce s poli
Pole je pro začátečníky docela těžké si představit, tudíž si ve skriptu nějaké pole vytvoříme a ukážeme si, jak ho nějakým způsobem analyzovat, případně setřídit a projít za pomoci vestavěných funkcí.
Nejjednodušší funkce, která vám ale na začátku pomůže nejvíce, je count(). Někde se můžete setkat i s aliasem sizeof(). Nijak se od sebe chováním neliší. Tyto funkce vrací počet hodnot v proměnné, která je klasicky polem. Pro všechny ostatní proměnné vrátí hodnotu 1. Výjimkou je proměnná s hodnotou NULL, pro kterou funkce vrátí 0. Rovněž vrací nulu v případě prázdného pole. Pokud chcete vědět, zda pole existuje, použijte funkci isset().
<?php
$Pole = array('cz', 'sk', 'de', 'uk', 'fr');
$Pocet = count($Pole); // $Pocet má nyní hodnotu 5
// Vypíšeme všechny prvky pomocí cyklu:
for ($i = 0; $i < $Pocet; ++$i) {
echo $Pole[$i], '<br>', "\r\n";
}
?>
Proměnnou $i jsme inicializovali s hodnotou 0, protože první index pole má hodnotu 0. Pokud bude mít první index pole jinou hodnotu, přirozeně bychom měli $i inicializovat s touto hodnotou. Následně index $i zvyšujeme o jedničku při každém průchodu cyklem. Poslední iterace nastane, když bude mít $i hodnotu o jedničku menší, než je počet prvků pole - poslední prvek pole má index 4.
Mohlo by vás napadnout, že místo proměnné $Pocet bude lepší napsat funkci count() přímo do podmínky cyklu for:
<?php
$Pole = array('cz', 'sk', 'de', 'uk', 'fr');
for ($i = 0; $i < count($Pole); ++$i) {
echo $Pole[$i], '<br>', "\r\n";
}
?>
Je několik důvodů, proč to nedělat. Jedním z nich je nízká efektivnost skriptu, jelikož je při každé iteraci volána funkce count(). Důležitějším důvodem je ale možnost chyby, pokud se v cyklu pole mění. Například pro uvolnění proměnné (nebo v tomto případě prvku pole) se používá funkce unset(). Pokud použijeme pro odstranění nějakého prvku tuto funkci v našem cyklu, setkáme se s problémem:
<?php
$Pole = array('cz', 'sk', 'de', 'uk', 'fr');
for ($i = 0; $i < count($Pole); ++$i) {
echo $Pole[$i], '<br>', "\r\n";
if (isset($Pole[$i])) {
if ($Pole[$i] == 'cz') {
unset($Pole[$i]);
}
}
}
?>
Znovu volaná funkce count() po vymazání prvního prvku vrátí menší velikost pole, takže na poslední prvek nedojde.
Cyklus for pracuje správně v případech, kdy víme, že indexy pole začínají nulou a jsou přiřazeny sekvenčně. Ale co když nejsou indexy prvků seřazeny postupně, ale v různých krocích či zcela nahodile? V tom případě potřebujeme jiné konstrukce a funkce pro práci s poli.
Nespojitě indexovaná pole
Pole mají vestavěný ukazatel (nebo iterátor). Tento interní kurzor sleduje, se kterým prvkem se aktuálně pracuje. Pro nově vytvořená pole je nastaven na první prvek. Hodnotu prvku, na který ukazuje, můžeme zjistit pomocí funkce current() a jeho index pomocí funkce key().
<?php
$Zeme = array();
$Zeme[24] = 'cz';
$Zeme[32] = 'sk';
$Zeme[17] = 'de';
$Zeme[] = 'uk'; // Index 33
$Key = key($Zeme); // 24
$Value = current($Zeme); // cz
echo 'Prvek ', $Key, ' má hodnotu ', $Value;
?>
Protože bylo pole právě vytvořeno, aktuálním prvkem je první prvek pole, takže kód vypíše: Prvek 24 má hodnotu cz. Prvek "cz" je první, i když jsou v poli prvky s nižším indexem, protože byl jako první přiřazen poli. Dokud nezavoláme funkci pro setřídění pole, pole tříděna nejsou. Tím se budeme zabývat až později.
Pro procházení poli v cyklu, i když jsou indexována nespojitě (nebo nejsou indexována čísly), můžeme použít funkce each() a list(). Nenumerickými indexy se budeme rovněž zabývat později. Nyní si ukážeme příklad cyklu, který prochází polem, jež není spojitě indexováno:
<?php
$Zeme = array();
$Zeme[24] = 'cz';
$Zeme[32] = 'sk';
$Zeme[17] = 'de';
$Zeme[] = 'uk'; // Index 33
reset($Zeme);
while (list($Key, $Value) = each($Zeme)) {
echo 'Prvek ', $Key, ' má hodnotu ', $Value, '<br>', "\r\n";
}
?>
Později podrobně probere, co tento zápis znamená, prozatím řádek...
while (list($Key, $Value) = each($Zeme)) {příkazy}
... chápejte tak, že pro každý prvek pole nastaví proměnnou $Key tak, aby obsahovala index prvku a $Value se rovnala hodnotě prvku. Funkce reset() nastavuje ukazatel na první prvek pole. Samozřejmě to není potřeba, pokud je ukazatel nastaven na první prvek pole, ale je dobrým zvykem tuto funkci volat před každým procházením pole, protože tím zajistíme, že budeme opravdu začínat prvním prvkem. Funkce each() při každém svém volání posouvá ukazatel pole o jeden prvek výše.
Jednoduché procházení poli
PHP od verze 4 umožňuje konstrukci foreach, stejně jako Perl a některé další jazyky. Tato konstrukce umožňuje jednoduché procházení poli. Existují dvě syntaxe, druhá je menším, nicméně užitečným rozšířením té první:
foreach ($Array as $Value) {příkazy}
foreach ($Array as $Key => $Value) {příkazy}
První varianta prochází daným polem $Array. V každém cyklu je hodnota aktuálního prvku přiřazena proměnné $Value a interní ukazatel je zvýšen o jedničku (takže v dalším cyklu budeme pracovat s dalším prvkem). Druhá varianta dělá to samé, ale s výjimkou toho, že index aktuálního prvku pole bude přiřazen proměnné $Key.
Poznámka: Když se foreach spouští poprvé, je interní ukazatel automaticky nastaven na první prvek pole, takže není potřeba volat před cyklem foreach funkci reset().
Poznámka: Také poznamenejme, že foreach pracuje s kopií daného pole, nikoliv s polem samotným, takže ukazatel pole není modifikován jako při použití each.
Nyní si ukážeme několik příkladů, jak procházet pole:
<?php
$Pole = array(1, 2, 5, 10, 20, 50);
// Cyklus while:
while (list(, $Hodnota) = each($Pole)) {
// Vynecháme první argument $Key u list(), nepotřebujeme ho.
echo 'Hodnota: ', $Hodnota, '<br>', "\r\n";
}
// Cyklus foreach:
foreach ($Pole as $Hodnota) {
echo 'Hodnota: ', $Hodnota, '<br>', "\r\n";
}
?>
Oba cykly fungují stejně. I následující:
<?php
$Pole = array(1, 2, 5, 10, 20, 50);
// Cyklus while:
while (list($Key, $Hodnota) = each($Pole)) {
echo 'Prvek s indexem ', $Key, ' má hodnotu ', $Hodnota, '<br>', "\r\n";
}
// Cyklus foreach:
foreach ($Pole as $Key => $Hodnota) {
echo 'Prvek s indexem ', $Key, ' má hodnotu ', $Hodnota, '<br>', "\r\n";
}
?>
Pro procházení polí jsou v PHP i další funkce, například next() a prev(), ale nenapadá mě jediný důvod, proč je používat. Pokud se chcete o tuto problematiku zajímat dopodrobna, navštivte dokumentaci PHP.
Asociativní pole
Doposud všechna naše pole měla celočíselné indexy. Pole však mohou jako indexy používat také řetězce:
<?php
$HlavniMesto['cz'] = 'Praha';
$HlavniMesto['sk'] = 'Bratislava';
$HlavniMesto['de'] = 'Berlín';
$HlavniMesto['pl'] = 'Varšava';
$HlavniMesto['us'] = 'Washington';
echo $HlavniMesto['de']; // Vypíše: Berlín
?>
To samé pole můžeme vytvořit i pomocí funkce array() a operátoru => jako v následujícím příkladu.
<?php
$HlavniMesto = array('cz' => 'Praha',
'sk' => 'Bratislava',
'de' => 'Berlín',
'pl' => 'Varšava',
'us' => 'Washington');
// Nyní pole projdeme cyklem while:
while (list($Key, $Value) = each($HlavniMesto)) {
echo 'Prvek s indexem ', $Key, ' má hodnotu ', $Value, '<br>', "\r\n";
}
?>
Výstup bude následující:
Prvek s indexem cz má hodnotu Praha
Prvek s indexem sk má hodnotu Bratislava
Prvek s indexem de má hodnotu Berlín
Prvek s indexem pl má hodnotu Varšava
Prvek s indexem us má hodnotu Washington
Nyní se podrobně podívejme, jak funkce each() pracuje. Jak jsme viděli, funkce dostává jako argument pole. V tomto případě $HlavniMesto. Vrací klíč a hodnotu aktuálního prvku a pak přesouvá kurzor na další prvek pole. Tyto hodnoty vrací ve formě čtyřprvkového pole s indexy 0, 1, "key" a "value". Prvky 0 a "key" obsahují index aktuálního prvku a prvky 1 a "value" obsahují jeho hodnotu. Konstrukce list() se použije k přiřazení hodnot prvků proměnným, jako by byly polem. Pole vrácené funkcí each() obsahuje nadbytečné prvky, nepotřebujeme ukládat všechny čtyři hodnoty do proměnných, můžeme uložit jen první dvě a zbylé dvě zahodit.
Vícerozměrná pole
Na začátku jsme si pole označili pole jako proměnnou obsahující více hodnot, tudíž jakýsi kontejner. Není žádný důvod, proč by jednotlivé hodnoty nemohly být rovněž pole. Výsledkem bude dvourozměrné pole. Základním způsobem můžeme vytvořit pole, jehož prvky obsahují pole. Pokud vnořená pole také obsahují pole, máme trojrozměrné pole a tak dále.
<?php
$Kontinenty = array('Evropa' => array('cz', 'de'),
'Amerika' => array('us', 'ca'));
echo $Kontinenty['Evropa'][0]; // Vypíše: cz
echo $Kontinenty['Amerika'][1]; // Vypíše: ca
?>
Pro procházení vnořenými poli můžeme samozřejmě použít vnořené cykly:
<?php
$Kontinenty = array('Evropa' => array('cz', 'de'),
'Amerika' => array('us', 'ca'));
// Vypíše název kontinentu:
while (list($KeyK) = each($Kontinenty)) {
echo $KeyK, '<br>', "\r\n";
// Vypíše seznam zemí pro tento kontinent:
while (list($KeyZ, $ValueZ) = each($Kontinenty[$KeyK])) {
echo '- ', $ValueZ, '<br>', "\r\n";
}
}
?>
Výsledkem bude:
Evropa
- cz
- de
Amerika
- us
- ca
Funkce pro řazení polí
I když řazení polí v PHP není většinou potřeba, protože s dynamickými poli se většinou setkáme jako s údaji z databází, které už můžeme dostat seřazené, máme k dispozici několik funkcí. Nejjednodušší z nich je sort(). Tato funkce seřadí prvky v abecedním nebo číselném pořadí a přiřadí jim indexy tak, aby odpovídali novému pořadí.
<?php
$Ovoce = array('citrón', 'pomeranč', 'banán', 'jablko');
sort($Ovoce); // Seřadíme pole.
reset($Ovoce); // Nastavíme ukazatel na první prvek.
// Projdeme pole.
foreach ($Ovoce as $Index => $Hodnota) {
echo 'Ovoce[', $Index, '] = ', $Hodnota, '<br>', "\r\n";
}
?>
Výsledkem bude:
Ovoce[0] = banán
Ovoce[1] = citrón
Ovoce[2] = jablko
Ovoce[3] = pomeranč
Další funkce pro řazení polí jsou například arsort(), asort(), ksort(), natsort(), natcasesort(), rsort(), usort() a uksort(), o kterých se můžete dočíst v oficiálním manuálu PHP.