Algoritmy s PHP

Ján Guniš, PF UPJŠ, Košice

 

Definícia vlastných funkcií

Ak v skripte na na rôznych miestach vykonávame tú istú (príp. líšiacu sa len parametrami) postupnosť príkazov, je vhodné použiť funkciu. Funkciu môžeme chápať ako časť programu, obsahujúcu istú postupnosť príkazov. Funkcie sa zvyknú označovať aj pojmom podprogramy, program v programe. Funkciu môžeme "zavolať" z ľubovoľnej časti nášho skriptu. Príkazy obsiahnuté vo funkcii sa automaticky vykonajú pri každom volaní funkcie. Ak je náš skript príliš obsiahly a obsahuje množstvo zdrojového kódu, funkcie značne sprehľadnia celý skript.

 

Príklad Vysvetlenie
function meno (zoznam parametrov)
{
zoznam príkazov;
return hodnota;
}
každá funkcia má svoje meno
pomocou parametrov predávame funkcii hodnoty, ktoré má spracovať
telo funkcie je uzatvorené v {} a obsahuje vykonávaciu časť, zoznam príkazov
pomocou príkazu return funkcia po skončení vráti výsledok svojej práce
jednoduché funkcie nemusia používať vstupné parametre a nemusia vracať hodnotu
 
<?
function heslo_dna()
{
echo "PHP je supeeer!"
}
heslo_dna();
?>
jednoduchá funkcia, ktorá nemá žiadne vstupné parametre a nevráti žiadny výsledok


takto sa funkcia vola z hlavného programu, každé takéto zavolanie spôsobí výpis textu "PHP je supeeer!"
 
<?
function sucet($a, $b)
{
return $a + $b;
}
$x = 10;
$y = 20;
echo sucet($x,$y);
echo sucet(sucet($x,10),$x+$y)
?>
funkcia sucet vráti súčet dvoch čísel, ktoré dostala ako parametre

ako parameter môžeme funkcii predať konštantu, premennú, výraz, výstupnú hodnotu z inej funkcie

parametre môžu byť všetkých typov, ktoré PHP podporuje (čísla, reťazce, polia, objekty), rovnaké typy dát môže funkcia aj vracať

v tomto prípade sa najskôr vyhodnotí sucet($x,10), potom $x+$y
tieto dve hodnoty sa potom pošlú ako parametre funkcii sucet

 

Rozsah platnosti premenných

PHP pristupuje k premenným vo funkciách odlišným spôsobom, ako sme zvyknutí napr. z Turbo Pascal-u. Premenné použité v skripte, nie sú automaticky prístupne vo funkcii. Aj keď vo funkcii použijeme premennú rovnakého mena, ako používa hlavný program, PHP ju interpretuje ako novú premennú. Akákoľvek zmena premennej vo funkcii nemá vplyv na hodnotu rovnomennej premennej v hlavnom programe.

Príklad Vysvetlenie
<?
function pis()
{
echo $a;
$a = 20;
}
$a = 10;
pis();
echo $a;
?>
funkcia a hlavný program používajú premennú $a
pre PHP sú to však 2 nezávislé premenné

výstup tohoto skriptu je 10

príkaz echo $a vo funkcii nemá žiaden efekt, pretože premenná $a vo funkcii nebola definovaná (nebola jej priradená žiadna hodnota), takže výstupom je prázdny reťazec

 

Niekedy ale potrebujeme vo funkcii používať aj globálne premenné. PHP ponúka možnosť ako pristupovať aj ku globálnym premenným.

Príklad Vysvetlenie
<?
function pis()
{
global $a;
echo $a;
$a = 20;
}
$a = 10;
pis();
echo $a;
?>
ku globálnym premenným pristupujeme vo funkciách pomocou príkazu global

v tomto prípade premenná $a vo funkcii je tá istá premenná ako premenná $a v hlavnom programe

výstup tohoto skriptu je: 1020
najskôr premennej $a priradíme v hlavnom programe hodnotu 10
potom sa jej hodnota vo funkcii vypíše
vo funkcii jej priradíme hodnotu 20
a táto hodnota sa vypíše v hlavnom programe

<?                   
function pis()
{
$GLOBALS["a"] = 20; 
echo $a;
$a = 5;
}
$a = 10;
pis();
echo $a;
?>
ku globálnym premenným môžeme pristupovať aj cez asociatívne pole $GLOBALS (pozor, píše sa veľkými písmenami)

výstupom toho skriptu je 20
$GLOBALS["a"]]  =  20; //priradí do globálnej premennej $a hodnotu 20
echo $a;
//vypíše hodnotu lokálnej premennej $a (prázdny reťazec)
$a = 5; 
//lokálnej premennej $a priradí hodnotu 10

Funkcie môžu mať definované svoje lokálne funkcie. Bohužiaľ neexistuje možnosť ak pristupovať k premenným nadradenej funkcie. Pristupovať sa dá len ku globálnym premenným definovaným v hlavnom programe.

Doteraz sme si ukázali ako PHP pracuje s parametrami, ktoré sú volané hodnotou (do funkcie sa posiela hodnota). PHP vie pracovať aj s parametrami, ktoré sú volané odkazom (funkcii sa neposiala hodnota premennej, ale odkaz na ňu). Pri predávaní parametrov odkazom nesmieme zabudnúť na to, že funkcia mení hodnotu premennej v hlavnom programe.

Príklad Vysvetlenie
<?
function zmen(&$x, $y)
{
$x = 5;
$y = 5;
}
$a = 10;
$b = 10;
zmen($a,$b);
echo $a . $b;
?>
parametre v hlavičke funkcie ktoré sú volané odkazom odlíšime tak, že pred daný parameter uvedieme znak &

výstupom toho skriptu je 5 10

hodnota premennej $a sa zmenila vo funkcii príkazom $x = 5
$a v hlavnom programe a $x vo funkcii sú dve rôzne mená pre jednu a tú istú premennú

<?
function zmen($x, $y)
{
$x = 5;
$y = 5;
}
$a = 10;
$b = 10;
zmen(&$a,$b);
echo $a . $b;
?>
skutočnosť, že parameter bude volaný hodnotou, môžeme definovať aj pri volaní funkcie

tento skript pracuje rovnako ako predchádzajúci

 

Občas vytvoríme funkciu, ktorú v drvivej väčšine voláme s rovnakými parametrami. Je zbytočné a nepraktické pri každom volaní používať tie isté parametre. V tomto prípade je výhodne zadefinovať funkcii štandardné hodnoty parametrov. Ako štandardné hodnoty môžeme uviesť len typ integer, double a string.

Príklad Vysvetlenie
<?
function umocni($x, $y = 2)
{
$moc = 1;
for ($i=1; $i<=$y; ++$i)
{
$moc = $moc * $x;
}
return $moc;
}
echo umocni(10);
echo umocni(10,3);
?>
funkcia umocni vracia hodnotu xy, ak parameter y neuvedieme, nastaví sa na hodnotu 2

výsledkom skriptu je 100 1000

echo umocni(10);    //vráti 102
echo umocni(10,3); 
//vráti 103

Ak funkcia očakáva n parametrov a pri volaní jej pošleme len r (r <=n) parametrov, tak pre posledných n-r parametrov v hlavičke funkcie musí byť definovaná štandardná hodnota.

 

Rekurzia

Hovoríme, že objekt je rekurzívny, ak sa čiastočne skladá, alebo je definovaný pomocou samého seba. Rekurzívne objekty sú bežnou súčasťou nášho každodenného života. Predstavme si, ako bude vyzerať obraz v jednom z dvoch, proti sebe otočených zrkadiel. Alebo čo budem vidieť v televízore, ktorý zobrazuje záznam z kamery, ktorá sníma televízor. Všetko sú to rekurzívne obrazce, definované (skladajúce sa z časti) zo samých seba.

Typicky matematickým príkladom rekurzie ja napr. faktoriál nezáporného čísla N.

N! = N * (N-1)!, ak N > 0
N! = 1, ak N = 0

Príklad Vysvetlenie
<?
function fak($x)
{
if ($x>0) return $x * fak($x-1);
else return 1;
}
echo fak(5);;
?>
rekurzívna funkcia na výpočet faktoriálu

každá rekurzívna funkcia obsahuje dve časti:
  rekurzívnu časť: v našom príklade return $x * fak($x-1)
  a
  nerekurzívnu časť: v našom prípade return 1;

POZOR! funkciu musíme napísať tak, aby bolo isté že sa vykoná aj nerekurzívna časť, v opačnom prípade vytvoríme nekonečnú (teoreticky) rekurziu, ktorá skončí (prakticky) pretečením zásobníka, teda s chybou