else
, pokud jako podmínku vezmeme nesplnění podmínky zapsané v if
), základní myšlenka u cyklů je
„Opakuj daný blok kódu tak dlouho, dokud je splněna nějaká podmínka“.Na jeden druh situací, kdy cykly jdou využít, jste asi narazili už když jsme mluvili o [odkaz]polích[/odkaz]: Jak
provést nějakou operaci pro každý prvek pole? Ve smyslu výše uvedené myšlenky by to tedy bylo: „Opakuj načtení dalšího
prvku pole a nějakou operaci s ním tak dlouho, dokud ten další prvek existuje“.
K tomu slouží v PHP foreach
. Použití je:
foreach ($pole as $klic => $hodnota) { // kód }
<?php $pole = array("a", "b", "c", "d", "e"); foreach ($pole as $index => $hodnota) { echo "V poli na indexu ".$index." je hodnota: ".$hodnota."<br>"; } ?>
<?php $pole = array("a", "b", "c", "d", "e"); echo "Pole obsahuje hodnoty: "; foreach ($pole as $hodnota) { echo $hodnota."<br>"; } ?>
while
.
Zápis i princip se podobá podmínce if
:
while (podmínka) { // kód }
while
a pokračuje se dalším cyklem, tedy
se znovu vyhodnotí podmínka, a tak dále.
Z uvedeného principu vyplývá jedna důležitá věc: Podmínka musí záviset na něčem, co se během průchodu cyklem změní
(nebo alespoň může změnit). Pokud je podmínka pořád stejná, cyklus nikdy neskončí.
Někdy lze vidět úmyslné konstrukce typu while(true)
, kdy autor kódu pak vyskočí z cyklu někde uvnitř (o tom
si povíme níže), ale v drtivé většině případů je použití takové konstrukce známkou špatného návrhu kódu, takže je lepší
se tomu vyhýbat.
Časté použití cyklu while je pro načítání řádků ze souboru nebo záznamů z databáze, což si ukážeme v pokročilejších kapitolách zde na webu. Jako příklad můžeme uvést cyklus, který spočítá sumu čísel od 1 do určeného čísla:
<?php $cislo = 10; $soucet = 0; // Dokud číslo je větší než 0 while ($cislo > 0) { // přičteme číslo k součtu $soucet = $soucet + $cislo; // a snížíme číslo o 1 $cislo = $cislo - 1; } echo "Suma čísel od 1 do $cislo je: $soucet"; ?>
while
, liší se jen tím, že zatímco cyklus while vždy nejdřív vyhodnotí podmínku a pak
(je-li splněna) provede kód, cyklus do-while vždy nejdřív provede kód a pak vyhodnotí podmínku (a je-li splněna,
pokračuje dalším cyklem). Z toho vyplývá, že cyklus do-while se vždy provede alespoň jednou, i když podmínka už od
začátku není splněna.
Předchozí příklad přepsaný na cyklus do-while by vypadal takto:
<?php $cislo = 10; $soucet = 0; // Podmínka je uvedena až na konci cyklu do { // přičteme číslo k součtu $soucet = $soucet + $cislo; // a snížíme číslo o 1 $cislo = $cislo - 1; // Jelikož snižujeme hodnotu už před podmínkou, je v podmínce 1 a ne 0 } while ($cislo > 1); echo "Suma čísel od 1 do $cislo je: $soucet"; ?>
for
. Hodí se pro specifickou, ale velmi častou, situaci, kdy cyklus spočívá v tom,
že provedeme kód kde zvyšujeme (případně snižujeme) hodnotu nějaké proměnné (počítadla) a to opakujeme tak dlouho,
než proměnná dosáhne nějaké hodnoty. Tento typ situace je i náš ukázkový příklad (v kódu snižujeme hodnotu $cislo tak
dlouho, až není vyšší než 0, respektive 1). Cyklus for je na začátku složitější na pochopení, ale pak tuto situaci naopak
zpřehledňuje a zkracuje zápis. Může vypadat asi takto:
for ($i = 0; $i < 10; $i = $i+1) { // kód }
$i = 0;
) je příkaz, který se provede jednou před prvním cyklem. Obvykle, stejně jako
v uvedeném příkladu, se tato část používá k inicializaci proměnné s počítadlem. Druhá část (v příkladu výše
$i < 10
) je podmínka a funguje stejně, jako u cyklu while: Vyhodnotí se na začátku každého cyklu a kód se
provede jen tehdy, když výsledná hodnota odpovídá logické hodnotě true
. Třetí část (v příkladu
$i = $i+1
) se provede vždy na konci každého cyklu (po vykonání kódu) a jejím smyslem je změnit počítadlo.
Výše uvedený příklad je tedy funkčně stejný jako tento cyklus while:
$i = 0; while ($i < 10) { // kód $i = $i + 1; }
<?php $vstup = 10; $soucet = 0; for ($cislo = $vstup; $cislo > 0; $cislo = $cislo - 1) { $soucet = $soucet + $cislo; } echo "Suma čísel od 1 do $vstup je: $soucet"; ?>
$cislo = $cislo - 1;
.
V praxi se používá operátor inkrementace či dekrementace ($cislo++;
, resp. $cislo--;
).
<?php // vnější cyklus pro řádky for ($r = 1; $r < 5; $r++) { // vnitřní cyklus pro sloupce for ($s = 1; $s < 5; $s++) { echo "[$r;$s] "; // vypsání hodnoty buňky ve vnitřním cyklu } echo "<br>"; // ukončení řádku ve vnějším cyklu } ?>
Výskok z cyklu může mít dvě podoby: Buď chcete ukončit aktuální cyklus a pokračovat dalším cyklem, nebo chcete ukončit
cykus jako celek (tj. další cyklus už neprovádět).
V první situaci (pokračování dalším cyklem) se používá příkaz continue
. Například kdybychom chtěli vypsat
všechny hodnoty nějakého pole, kromě nul:
<?php $pole = array(1, 5, 0, 4, 9, 0, 3); foreach ($pole as $klic => $hodnota) { if ($hodnota == 0) continue;echo "Hodnota na indexu $klic v poli je: $hodnota <br>"; } ?>
continue n
, kde n je číslo udávající, kolik vnořených cyklů se má ukončit.
Tedy continue 1
je totéž jako continue a ukončí stávající cyklus, continue 2
ukončí stávající
cyklus a cyklus o úroveň nad ním, a tak dále.
Příkaz continue
lze kromě cyklů použít i pro výskok z větve podmínky switch
a podmínka switch se
počítá i jako úroveň vnoření cyklu.
Použití continue
jde nahradit použitím podmínky a většinou je to i lepší řešení. Pro náš konkrétní příklad
by kód šel napsat takto:
<?php $pole = array(1, 5, 0, 4, 9, 0, 3); foreach ($pole as $klic => $hodnota) { if ($hodnota != 0){ echo "Hodnota na indexu $klic v poli je: $hodnota <br>"; } } ?>
break
, který už známe jako ukončení bloku case
z minulé kapitoly o podmínkách. Kromě bloku
case
tedy příkaz break
(okamžitě) ukončí i cyklus a pokračuje dalším příkazem za ním. Pro ukázku
můžeme opět vypisovat hodnoty z pole jako výše, ale tentokrát budeme chtít vypisovat hodnoty jen do chvíle, než
narazíme na první nulu (tedy u námi definovaného pole se vypíší pouze první dvě hodnoty). Kód bude prakticky stejný,
jen místo příkazu continue
použijeme break
:
<?php $pole = array(1, 5, 0, 4, 9, 0, 3); foreach ($pole as $klic => $hodnota) { if ($hodnota == 0) break;echo "Hodnota na indexu $klic v poli je: $hodnota <br>"; } ?>
break
se lze vyhnout, ale v některých případech to může znamenat poměrně rozsáhlé přepracování
kódu, zejména když jen upravujete nějaký už hotový kód. Pokud ale existují podobně náročné varianty s break
a bez, je lepší preferovat variantu bez použití break
.
Také příklad výše by šel přepsat bez použití break
, ale vyžadovalo by to pozměnit celý návrh cyklu. Můžeme
si ale při té příležitosti ukázat další způsob procházení pole:
<?php $pole = array(1, 5, 0, 4, 9, 0, 3); // funkce count() vrátí počet položek v poli $pocet = count($pole); $i = 0; while (($i < $pocet) && ($pole[$i] != 0)) { echo "Hodnota na indexu $i v poli je: $pole[$i] <br>"; $i++; } ?>
while
, ovšem i tak je k procházení celého pole jednodušší a přehlednější
využít cyklus foreach
.
1. Napište skript, který vypíše lichá čísla od 10 do 50.
2. Vytvořte si pole s názvy dnů v týdnu a pak zkuste vypsat seznam dnů v týdnu, přičemž aktuální den v týdnu bude
zvýrazněný značkou <strong>.
Číslo aktuálního dne v týdnu zjistíte pomocí date("w")
, pro české prostředí to ale má záludnost: Používá se
americké pořadí dnů v týdnu (tj. první den je neděle) a čísluje se od nuly. Tedy 0 = neděle, 1 = pondělí, atd.
Řešení (kromě uvedených existují i jiná možná řešení): 1.
<?php // 10 a 50 jsou sudá čísla, takže je do cyklu nemusíme zahrnovat for ($i = 11; $i < 50; $i++) { // Liché číslo se určí tak, že modulo (zbytek po dělení) 2 je 1 if (($i % 2) == 1) { echo $i." "; } } ?>
<?php // vložení hlavičky stránky, kterou jsme vytvořili ve [odkaz]4. kapitole[/odkaz] include "spolecna_hlavicka.php";// Neděli vložíme poslední, aby ve foreach byla na konci, ale s indexem 0 // Při array("neděle", "pondělí", …) by neděle byla první i ve výpisu $dny = array(1=>"pondělí", "úterý", "středa", "čtvrtek", "pátek", "sobota", 0=>"neděle"); $dnes = date("w");
foreach($dny as $i => $den) { if($i == $dnes) { echo "<strong>$den</strong> "; } else { echo $den." "; } } ?>
<?php // Indikátor, zda je první položka $prvni = true; // 10 a 50 jsou sudá čísla, takže je do cyklu nemusíme zahrnovat for ($i = 11; $i < 50; $i++) { // Liché číslo se určí tak, že modulo (zbytek po dělení) 2 je 1 if (($i % 2) == 1) { // Pokud je první položka if ($prvni) { $prvni = false; // zruší se indikátor první položky } else { echo ", "; // jinak se vypíše oddělovač } echo $i; } } ?>