Základní kurz 13: Funkce

Autor: Joker
Už v kapitole o základech syntaxe jsme si řekli o funkcích, argumentech (resp. parametrech) a jak zavolat vestavěnou funkci PHP. Později jsme se seznámili i s dalšími funkcemi, ale stále šlo o vestavěné funkce PHP. V této kapitole si ukážeme, jak vytvářet své vlastní funkce.

Poznámka: Funkce se týkají zejména procedurálního programování v PHP. Pokud chcete raději programovat objektově, místo funkcí budete vytvářet třídy a metody. Z této a následujících kapitol ale budete potřebovat jednu důležitou znalost, a sice kontext, který se uplatní i v objektově-orientovaném programování.

Zápis funkce

Funkce se zapisuje klíčovým slovem function, následovaným závorkami, ve kterých mohou být definovány argumenty, a kódem funkce ve složených závorkách.
Příklad:

function pozdrav() {
  echo "Ahoj!";
}

Volání funkce pak vypadá stejně jako u vestavěných funkcí, tedy např.:
pozdrav();

Poznámka: V názvech funkcí se, stejně jako u proměnných, doporučuje používat jen písmena bez diakritiky, čísla, pomlčku a podtržítko. PHP dovoluje i některé další znaky, ale je lepší si vystačit jen s těmi uvedenými, například některá vývojová prostředí mohou s jinými znaky v názvu mít problémy. Velikost písmen se u funkcí nerozlišuje, takže u funkce pozdrav() definované výše budou fungovat i volání Pozdrav(); PozdraV() či POZDRAV(). Že to funguje ale ještě neznamená, že je to dobrý nápad. Kvůli přehlednosti byste vždy měli používat jen jednu formu zápisu, čili volání stejné jako definici.

Argumenty

Funkce také může mít argumenty a může vracet hodnotu. Hodnota se vrací pomocí klíčového slova return a argumenty se píší do závorek za název funkce.
Příklad:

function sude($cislo) {
  // zkontroluje, zda je číslo sudé
  // Číslo je sudé, pokud číslo modulo 2 je 0
  return (($cislo % 2) == 0) ? true : false;
}
Poznámka: Výsledkem samotného (($cislo % 2) == 0) je true nebo false, takže zápis by mohl být ještě kratší: return (($cislo % 2) == 0). Zápis s podmíněným operátorem byl použit jen proto, aby bylo na první pohled zřejmé,
co funkce vrací.

Volání funkce by pak vypadalo třeba sude(5); a jeho výsledkem bude hodnota, kterou vrací funkce. Celý kód by tedy mohl vypadat třeba takto:

<?php
  // vložení hlavičky stránky, kterou jsme vytvořili ve 4. kapitole
  include "spolecna_hlavicka.php";

  function sude($cislo) {
    // zkontroluje, zda je číslo sudé
    return (($cislo % 2) == 0) ? true : false;
  }
  if (isset($_GET["cislo"])) {
    // Konverze na číslo, zároveň případné nežádoucí vstupy změní na 0
    $vstup = intval($_GET["cislo"]);
    $vyrok = "není";

    if (sude($vstup)) {
      $vyrok = "je";
    }
    echo "Číslo $cislo $vyrok sudé";
  }
  // níže HTML formulář pro odeslání
?>
<form action="" method="get">
<label for="cislo">Zadejte číslo:</label>
<input type="text" name="cislo" id="cislo">
<input type="submit" name="odeslat" value="Odeslat">
</form>

Funkce může mít argumentů i více, pak se oddělují čárkami. Také lze argumentům zadat výchozí hodnoty. Argumenty se zadanou výchozí hodnotou by měly být v seznamu argumentů funkce na konci (jinak to nemá smysl) a stávají se nepovinnými. Argumenty bez výchozí hodnoty jsou povinné a při volání funkce je nelze vynechat. To si můžete vyzkoušet, když funkci sude z příkladu výše zkusíte zavolat bez argumentu: sude(); Výsledkem bude varování „Missing argument 1 for sude()“.
Výchozí hodnota u nepovinných argumentů se zadává takto:
function funkce($prvni, $druhy=0, $treti=1) { …
Příklady volání takové funkce:
funkce(1, 2, 3); // hodnoty argumentů jsou 1, 2, 3
funkce(1, 2); // hodnoty argumentů jsou 1, 2, 1
funkce(1); // hodnoty argumentů jsou 1, 0, 1
funkce(); // skončí chybou, první argument musí být uveden

Předání argumentu referencí

Když se funkci předá proměnná jak jsme to dělali výše, zkopíruje se do funkce jen její hodnota a pracuje se s ní nezávisle na původní proměnné. Proto například toto nefunguje dle očekávání:

<?php
  function dvakrat($hodnota) {
    $hodnota = $hodnota * 2;
  }

  $cislo = 5;
  dvakrat($cislo);
  echo $cislo; // vypíše 5 a ne 10
?>

Protože uvnitř funkce se pracuje jen s kopií hodnoty, případné změny se neprojeví vně funkce. Toho můžeme docílit tak, že do funkce předáme tzv. referenci na proměnnou. Reference se označuje při definici funkci uvedením ampersandu (&)
před daný argument. Když se pak funkci předá nějaká proměnná, předá se jí odkaz přímo na tu proměnnou a změny její hodnoty uvnitř funkce se projeví i vně funkce. Upravený příklad tedy již bude fungovat dle očekávání:
<?php
  function dvakrat(&$hodnota) {
    $hodnota = $hodnota * 2;
  }

  $cislo = 5;
  dvakrat($cislo);
  echo $cislo; // vypíše 10
?>

Reference se občas hodí, ale neměli byste je používat místo návratové hodnoty (což dělá i příklad výše). Použití návratové hodnoty bývá přehlednější. Příklad výše by tedy šlo upravit takto:
<?php
  function dvakrat($hodnota) {
    return $hodnota * 2;
  }

  $cislo = 5;
  $cislo = dvakrat($cislo);
  echo $cislo; // vypíše 10
?>

Rekurze

Funkce může volat i sama sebe (tzv. rekurze). Není to ale příliš časté a patří to mezi pokročilejší techniky programování. Stejně jako u cyklů i u rekurze je třeba dát pozor, aby řetěz volání někdy skončil a nenastal nekonečný cyklus. Klasickým příkladem využití rekurze je výpočet faktoriálu čísla:

function faktorial($cislo) {
  if ($cislo < 0) return 0; // chyba

  if ($cislo < 2) return 1; // 0! a 1! = 1
  else {
    // Jinak je výsledek číslo krát faktoriál o 1 nižšího čísla
    return $cislo * faktorial($cislo - 1);
  }
}

Rekurze je ovšem oproti jiným technikám náročnější na systémové zdroje, zejména při větším počtu vnoření, takže bývá často výhodnější rekurzivní volání funkce nahradit cyklem. To lze udělat i v případě faktoriálu:
function faktorial($cislo) {
  if ($cislo < 0) return 0; // chyba

  $vysledek = 1;
  for ($i = 2; $i <= $cislo  ; $i++) {
    $vysledek = $vysledek * $i;
  }
  return $vysledek;
}

Několik užitečných rad, jakým způsobem organizovat kód do funkcí:

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í