joi, 18 februarie 2016

Structuri de control, structuri repetitive, exemple

Limbajul PHP - Structuri de control, structuri repetitive, exemple



Structuri de control in PHP    

In limbajul PHP, la fel ca in oricare alt limbaj de programare, instructiunile cuprinse intr-o secventa de cod-sursa se executa succesiv, una dupa alta. Exista insa anumite instructiuni care modifica ordinea de executie a liniilor de cod. Din acest motiv ele poarta numele de structuri de control, intrucat ele controleaza fluxul de executie.
Structurile de control din PHP sunt: structura alternativa (instructiunea if cu variantele ei), structura de selectie multipla (switch), structuri repetitive (for, while, do... while, foreach), structuri de intrerupere a fluxului (break, continue, return), structura de salt neconditionat (goto), directivele de includere (include, require) si directiva declare.
O parte din acestea sunt rar folosite in practica (cum ar fi goto sau declare), motiv pentru care nu le vom trata in acest ghid. Restul vor fi prezentate succint in cele ce urmeaza sau in lectia urmatoare.

Structura alternativa if    

Poate cea mai des intalnita structura de control este instructiunea if. Aceasta este folosita pentru a executa o secventa de cod in functie de valoarea de adevar a unei conditii. Sintaxa este prezentata mai jos:
if( conditie ) instructiune 1;
Aceasta forma permite executarea unei instructiuni numai daca este indeplinita o conditie. Conditia poate fi orice expresie de genul "2 mai mic decat 3", "variabila $a este definita", s.a. tradusa in limbajul PHP.
Instructiunea de executat poate fi simpla (o singura instructiune) sau un bloc (mai multe instructiuni delimitate de acolade). Regula este ca atunci cand este nevoie sa se execute mai mult de o instructiune, trebuie obligatoriu creat un bloc (trebuie folosite acoladele).
Exemplu:
<?php
if( 2 < 4 ) print "2 e mai mic decat 4 <br />";
 
if( 3 > 1 ) {
 print "3 e mai mare ca 1 \n";
 print "<br />";
}
?>
Atentie! Daca nu se foloseste un bloc in cadrul instructiunii if, atunci doar prima instructiune dintre cele existente se executa sau nu, in urma evaluarii conditiei, pe cand celelalte se vor executa intotdeauna, indiferent de rezultatul verificarii. De exemplu:
<?php
echo "Este 3 mai mic decat 2? <br />\n";
if( 3 < 2 )
 print "Da, 3 < 2 - prima linie <br />";
 print "Da, 3 < 2 - a doua linie <br />";
?>
Codul de mai sus va afisa:
Este 3 mai mic decat 2? <br />
Da, 3 < 2 - a doua linie <br />
Pentru ca nu am inclus cele 2 instructiuni print intr-un bloc, a doua instructiune s-a executat indiferent de valoarea de adevar a conditiei. Practic, doar prima instructiune print a fost considerata ca facand parte din structura if. Codul corect (din punct de vedere logic) ar fi urmatorul, care contine un bloc de instructiuni:
<?php
echo "Este 3 mai mic decat 2? <br />\n";
if( 3 < 2 ) {
 print "Da, 3 < 2 - prima linia <br />";
 print "Da, 3 < 2 - a doua linie <br />";
}
?>

Instructiunea if - else

De multe ori este nevoie sa se specifice si o operatie ce trebuie efectuata daca nu este indeplinita o conditie. In acest caz se foloseste if - else.
if( conditie ) instructiune 1;
else instructiune 2;
Aceasta forma permite executarea unei instructiuni atunci cand se indeplineste conditia sau executarea alteia diferite in caz contrar. Aceleasi observatii ca si mai sus se aplica.
<?php
echo "Este 3 mai mic decat 2? <br />\n";
if( 3 < 2 ) {
 print "Da, 3 < 2 - prima linia <br />";
 print "Da, 3 < 2 - a doua linie <br />";
} else {
 print "Nu, 3 > 2 - prima linia <br />";
 print "Nu, 3 > 2 - a doua linie <br />";
}
?>

Instructiunea de selectie multipla   

O instructiune ce se aseamana cu if este switch, o structura ce permite executarea uneia sau mai multor linii de cod in functie de valoarea unei expresii. Instructiunea switch este utila in cazurile in care este nevoie sa se verifice mai multe valori posibile ale unei expresii.
<?php
$var = 3;
 
// se vor executa instructiunile de pe ramura care
// corespunde valorii variabilei $var
switch( $var ) {
 case 0:
  print 'zero';
  break;
 case 1:
  print 'unu';
  break;
 case 2:
  print 'doi';
  break;
 case 3:
  print 'trei';  // afisez trei
  break;         // intrerup fluxul executiei switch
 case 4:
  print 'patru';
  break;
 case 5:
  print 'cinci';
  break;
}
 
echo "\n", 'Gata!';
?>
De mentionat este faptul ca, daca nu se foloseste instructiunea de control break, in momentul in care o ramura este selectata, se vor executa atat instructiunile aferente acelei ramuri cat si instructiunile ramurilor urmatoare. Acest lucru poate sa nu fie dorit intotdeauna, de aceea este important ca break sa fie folosita ori de cate ori fluxul de executie al blocului switch trebuie intrerupt.
Exemplul de mai jos va executa instructiunea print 2; si toate celelalte instructiuni print care urmeaza, intrucat fluxul nu este intrerupt prin break.
<?php
$numar = 2;
 
// se vor executa instructiunile de pe ramura care
// corespunde valorii variabilei $numar
switch( $numar ) {
 case 0:
  print 0;
 case 1:
  print 1;
 case 2:
  print 2;
 case 3:
  print 3;
 case 4:
  print 4;
 case 5:
  print 5;
}
 
echo "\n", 'Gata!';
 
// va afisa 2345 Gata
?>

Includerea altor scripturi   

PHP permite referirea unor fisiere PHP externe si includerea lor in fluxul curent de executie folosind functiile include sau require. Important de mentionat, in momentul in care un script este inclus cu una din cele 2 functii, el este imediat si executat (interpretat). Practic, fluxul de executie al scriptului initial (cel in care apare instructiunea include sau require) este intrerupt temporar pentru a executa scriptul inclus, urmand ca dupa finalizarea executiei, fluxul initial sa fie reluat.
Spre exemplu, daca avem doua fisiere ca mai jos, la accesarea scriptului script.php vor fi afisate ambele mesaje - asta pentru ca in urma instructiunii include scriptul config.php este imediat interpretat.
<?php
// fisierul config.php
echo 'Sunt in config.php <br />';
?>
 
<?php
// fisierul script.php
include( 'config.php' );
echo 'Sunt in script.php <br />';
?>
Prin functionalitatea lor, instructiunile include si require devin utile la organizarea codului PHP si la mentinerea unei structuri simple de executie prin folosirea mai multor fisiere pentru o singura activitate. Astfel, putem sa separam codul in scripturi PHP de sine statatoare ce vor fi "puse cap la cap" prin apeluri de include sau require.
Spre exemplu, putem avea niste declaratii de date intr-un script numit config.php si codul propriu-zis intr-un altul, pagina.php. Putem apoi include fisierul de configurari (config.php) direct din scriptul principal (pagina.php), reusind astfel sa mentinem codul aerisit.

Include sau require?

Functia require face acelasi lucru ca si include dar exista o diferenta intre cele doua: daca fisierul solicitat pentru includere nu exista, include va returna un avertisment, continuand executia, pe cand require va returna o eroare iar executia codului va fi intrerupta.
<?php
include( 'fisier_inexistent.php' );  // genereaza un warning si merge mai departe
echo 'Acest mesaj va fi afisat';
 
require( 'fisier_inexistent.php' );  // genereaza o eroare iar executia se intrerupe
echo 'Aceasta instructiune nu va mai fi executata';
 
?>
Cele doua functii au fiecare cate o varianta: include_once respectiv require_once. Aceste forme, dupa cum si numele o spune, includ fisierul specificat o singura data, astfel incat, daca fisierul solicitat a fost deja inclus la o noua apelare a include_once sau require_once acesta nu va fi inclus a doua oara. Aceste forme ale functiilor sunt utile atunci cand fisierle incluse contin declaratii ce trebuie sa fie facute o singura data.

Operatii cu variabile. Structuri repetitive

O structura repetitiva este o secventa de cod ce permite realizarea repetata a aceleiasi operatii de un anumit numar de ori. O structura repetitiva este definita de 2 elemente: operatia care este executata si conditia de oprire a executiei. In unele cazuri se cunoaste si numarul de executii (sau iteratii).
Iata cateva aplicatii care implementeaza anumite tipuri de structuri in PHP:

Structura repetitiva for    7 ! 

Se foloseste atunci cand se cunoaste dinainte numarul de repetitii (numarul de pasi ce se vor executa). Are urmatoarea sintaxa:
for( [instructiune1] ; [conditie] ; [instructiune2] ) {  [instructiune3]  } 
unde:
  • instructiune1 este o instructiune de executat la inceput
  • conditie este o expresie care daca este evaluata ca adevarata va determina repetarea ciclului - este denumita generic conditia de repetare
  • instructiune2 se va executa la fiecare pas al repetarii
  • instructiune3 reprezinta operatia efectiva care se repeta in cadrul FOR-ului
In general, [instructiune1] este o expresie de initializare de forma $i = 1, conditia de repetare este de forma $i <= numarul de pasi si [instructiune2] este o expresie de incrementare $i++.
for( $i = 1; $i <= 10; $i++ ) {
 echo $i; // instructiune3
}
In limbaj natural, intructiunea se traduce prin "plecand de la $i = 1, executa operatia si creste-l pe $i cu o unitate; apoi repeta totul atat timp cat $i <= 10
De retinut: instructiunea din cadrul for-ului se executa doar daca expresia (conditia) este adevarata, deci pot exista situatii cand expresia este falsa si [instructiune3] nu se executa niciodata. Exemplu:
for( $i = 0; $i > 10; $i++ ) {
 echo 'Aceasta instructiune nu se executa niciodata, pentru ca valoarea ' .
      'initiala a lui $i nu este mai mare decat 10';
}

Structura repetitiva while    3 ! 

Instructiunea while este folosita atunci cand nu se cunoaste dinainte numarul de executii. Are o forma mai intuitiva decat for si multe persoane o considera mai usor de folosit. Diferenta dintre while si for este aceea ca prima este mai generala si mai flexibila. Se poate chiar afirma ca for este o situatie particulara a unei structuri while. Sintaxa este urmatoarea:
while( [conditie] ) {  [instructiune]  }
Este probabil usor de inteles ca [instructiune] se executa atata timp cat [conditie] este adevarata. La fel ca si la for, exista posibilitatea ca instructiunea sa nu fie executata niciodata.
Mai jos este un exemplu de structura repetitiva while care are acelasi rezultat ca secventa de cod de mai sus ce foloseste for. Se poate observa ca in cazul structurii while conditia are la baza, de multe ori, o variabila initializata in exterior si modificata in interior. In cazul de mai jos, $i este modificata la fiecare executie, pana cand, la un moment dat, va fi mai mare decat 10 ceea ce va determina iesirea din bucla repetitiva.
$i = 0;
while( $i <= 10 ) {
 echo $i;
 $i++; // la fiecare pas $i creste cu o unitate
}
De retinut: este de datoria programatorului sa includa in blocul din structura repetitiva si codul necesar iesirii din bucla. Daca acest lucru nu se realizeaza, codul se va executa la nesfarsit. Exemplu:
$continua = true;
while( $continua == true ) {
 echo 'La nesfarsit', '<br>';
}
echo 'Aici nu se mai ajunge';
Varianta corecta a exemplului de mai sus este urmatoarea:
$continua = true;
while( $continua == true ) {
 echo 'La nesfarsit', '<br>';
 $continua = false; # modific variabila de testare a conditiei
}
echo 'Acum se ajunge aici';

Structura repetitiva do... while    9 ! 

O alta structura repetitiva este do... while. Diferenta fata de while este ca verificarea de face la final, dupa ce se executa cel putin o data secventa de cod. O traducere in cuvintele noastre ar fi: "executa secventa si, cat timp conditia este adevarata, repet-o".
Structura do... while are urmatoarea forma:
$i = 0;
do {
 echo $i;
 $i++;
} while( $i <= 10 );
Se poate observa o asemanare foarte mare cu structura while, singura diferenta fiind pozitionarea conditiei fata de codul executat, ceea ce asigura minim o executie a codului, chiar daca evaluarea conditiei determina iesirea din bucla. Astfel, daca la for si while este posibil ca secventa de cod din cadrul structurii repetitive sa nu se execute niciodata, in cazul do... while bucla va avea cel putin o executie.
In exemplul de mai jos codul se va executa o data, chiar daca $i nu corespunde conditiei. Verificarea lui se va face oricum dupa executarea blocului din interiorul structurii. Evaluarea conditiei va determina iesirea din structura repetitiva, fara o alta repetare a executiei.
$i = 11;
do {
 echo $i;
 $i++;
} while( $i <= 10 );
Structura do... while este destul de rar folosita in practica, dar este utila pentru situatiile in care este nevoie de minim o executie a codului.
O aplicatie practica de folosire a structurii repetitive do... while este prezentata mai jos. Secventa de cod de mai jos afiseaza prima aparitie a valorii 0 intr-un sir de numere cu lungimea de minim 1.
/* avem un vector cu un numar necunoscut de valori; vrem sa cautam valoarea 0
 * folosind o structura repetitiva. intrucat vectorul are minim 1 element, putem
 * folosi structura do... while, care va face cel putin o repetare */
 
$vector = array( 3, 4, 5, 1, 2, 9, 76, 42, 2, 9, 6, 0, 4, 1, 10 );
 
# operatia: se verifica daca elementul curent al vectorului este 0
# conditia de repetare: elementul curent nu este 0 si nu s-a ajuns la finalul vectorului
# nota: in acest caz putem afla numarul de elemente al vectorului, in functie de care
# putem defini numarul maxim de repetari, deci putem folosi si structura for
# alternativ putem folosi si structura while
 
 
$pozitie = 0; // plecam de la primul element
 
// parcurgem vectorul pana cand ajungem la final sau gasim valoarea 0
do {
 // presupun mai intai ca elementul de la repetarea curenta este 0
 $gasit = true;
 
 // verific daca elementul curent (initial primul element) este diferit de 0
 // cu alte cuvinte, deocamdata nu am gasit ce caut, deci merg mai departe
 if( $vector[ $pozitie ] != 0 ) {
  $gasit = false;
 }
 
 // trec la pozitia urmatoare pentru verificare
 $pozitie++;
 
} while ( !$gasit && $pozitie < count( $vector ) );
 
if( $gasit == true ) print "Am gasit 0 pe pozitia $pozitie";
else print "Nu am gasit 0 in vectorul asta";
 
/* afiseaza 
Am gasit 0 pe pozitia 11 
*/

Iterarea cu foreach    6 ! 

PHP ofera o structura repetitiva foarte puternica si des folosita: foreach. Aceasta permite iterarea prin toate elementele unui vector. Pot fi folositi si vectori simpli si asociativi.
Spre deosebire de celelalte instructiuni, pentru foreach nu trebuie specificata explicit o conditie de oprire, fiind de datoria interpretorului PHP sa opreasca iterarea atunci cand s-a ajuns la finalul vectorului.
// parcurgerea unui vector cu foreach
$vector = array( 3, 4, 5, 1, 2, 9 );
 
// afiseaza: 3 4 5 1 2 9 
foreach( $vector as $element) {
 print "$element ";
}
// parcurgerea unui vector cu foreach, folosind cheile si valorile
$vector = array( 'a', 'b', 'c', 'd', 'e', 'f' );
 
// afiseaza: a b c d e f
foreach( $vector as $cheie => $element) {
 print "$element ";
}
 
// afiseaza: 0 1 2 3 4 5
foreach( $vector as $cheie => $element) {
 print "$cheie ";
}
// Nota: chiar daca $vector nu este asociativ in mod explicit, 
// elementele sale oricum au chei implicite valorile 0, 1, 2, 3 ...
// vector asociativ (definit explicit cu chei)
$zile = array(
 'luni' => 'Mo',
 'marti' => 'Tu',
 'miercuri' => 'We',
 'joi' => 'Th',
 'vineri' => 'Fr',
 'sambata' => 'Sa',
 'duminica' => 'Su'
);
// afiseaza Mo Tu We Th Fr Sa Su
foreach( $zile as $eng) {
 print "$eng ";
}
 
// afiseaza si cheia si valoarea intr-un text
foreach( $zile as $rom => $eng) {
 print "$eng inseamna $rom <br />";
}
 
/* afiseaza 
Mo inseamna luni
Tu inseamna marti
We inseamna miercuri
Th inseamna joi
Fr inseamna vineri
Sa inseamna sambata
Su inseamna duminica
*/

Intreruperea fluxului de executie    0 ! 

In toate structurile repetitive prezentate mai sus, executia poate fi intrerupta, partial sau total, folosind instructiunile continue sau break.

continue

Instructiunea continue permite oprirea iteratiei curente a unei structuri repetitive si trecerea imediata la iteratia urmatoare. Folosind continue toate instructiunile din blocul structurii sunt sarite pentru iteratia curenta, iar executia continua cu iteratia urmatoare. Un exemplu:
for($i = 0; $i < 10; $i++) {
 /* la toate executiile in care $i <= 5, se va "sari" peste
  * instructiunile print; practic, dupa apelul continue, 
  * executia "trece" la pasul urmator, crescandu-l pe $i */
 if( $i <= 5 ) {
  continue;
 }
 print $i;
 print "<br />\n";
}
In exemplul de mai sus avem o structura repetitiva for cu 10 executii (de la 0 la 9). Pentru iteratiile in care $i este sub 6, se va executa instructiunea de control continue, care va sari peste tot ce urmeaza (doua instructiuni print) si va forta trecerea la iteratia urmatoare. Asadar, la finalul executiilor se vor afisa doar numerele de la 6 pana la sfarsit.
De retinut, continue afecteaza doar iteratia curenta; celelalte iteratii se pot executa complet, atat timp catcontinue nu este apelata din nou. Nu este nici o diferenta de la o structura repetitiva la alta (for, while, do while) - continue se comporta la fel.

break

Instructiunea break permite intreruperea totala a executiei structurii curente si trecerea la urmatoarea linie de cod. Folosind break toate instructiunile din blocul structurii sunt sarite pentru toate iteratiile (curenta si cele urmatoare). Practic se "iese" fortat din blocul structurii repetitive, iar fluxul de executie continua cu instructiunea de dupa structura repetitiva.
for($i = 0; $i < 10; $i++) {
 // cand $i == 2, se va "iesi" din structura
 if( $i == 2 ) {
  break;
 }
 print $i;
 print "<br />\n";
}
print "Gata!"; // cand $i == 2 se "sare" direct aici, ignorand celelalte iteratii
Spre deosebire de continue, instructiunea break afecteaza toate iteratiile unei structuri; nici o alta iteratie a blocului structurii nu se mai realizeaza dupa break.
Un apel break are acelasi efect pentru toate structurile repetitive. In plus, instructiunea se poate folosi si in alte structuri de control, cum este switch, avand ca efect "iesirea" din blocul de selectie.

Structuri multiple

In cazul in care exista structuri repetitive multiple, incluse unele in interiorul celorlalte, instructiunile breaksi continue pot primi ca parametru nivelul structurii pe care o afecteaza. Spre exemplu, daca avem 2 for-uri ca in secventa de cod de mai jos, apelul break 1; se refera la for-ul din interior, pe cand break 2; se refera la primul for (cel cu $i).
$n = 7;
for($i = 0; $i < $n; $i++) {
 // la fiecare iteratie a lui $i, avem un alt for
 echo 'Iteratia #', $i, ': ';
 for($j = 0; $j < $n; $j++) {
  if( $i == 4 && $j == 4 ) {
   break 2; // se aplica la for-ul mare
  }
  if( $j >= $n - $i ) {
   continue 1; // se aplica la for-ul din mijloc
  }
  print "$j ";
 }
 print "\n";
}
De obicei, se recomanda evitarea unor astfel de constructii, intrucat codul devine greu de urmarit si pot sa apara usor probleme. De cele mai multe ori, nici nu va fi nevoie sa apelati continue sau break cu parametru, dar in orice caz, incercati sa evitati pe cat posibil intreruper iteratiilor pe mai multe nivele.

Diferenta dintre break si exit

Intrucat am vorbit despre intreruperea executiei, este posibil sa apara confuzii intre break si exit sau die. Este adevarat ca atat break cat si celelalte intrerup executia secventei de cod, doar ca aceasta intrerupere se realizeaza la niveluri diferite. Astfel, break actioneaza doar la nivelul structurii din este apelat, pe candexit si die actioneaza la nivelul intregului script PHP.
Instructiunea break va intrerupe executia structurii care o contine, dar va permite continuarea executiei cu alte instructiuni ce urmeaza. Exit sau die nu mai permit nici o alta executie.

Aplicatii - Structuri repetitive    11 ! 

Mai jos sunt prezentate cateva aplicatii legate de structurile repetitive. Sunt mai degraba portiuni de cod, care nu vor face decat sa va ajute sa va obisnuiti cu particularitatile limbajului PHP. Comentariile sunt binevenite.

Cum definesc un vector ale carui elemente sa aiba valori incrementale?

/* vrem sa construim un vector in care fiecare element sa fie initializat 
 * cu o valoare dinamica si incrementala; avem, asadar, o aceeasi operatie
 * care se repeta de mai multe ori, motiv pentru care vom folosi un for */
 
$vector = array();
$n = 10;
 
# operatia repetitiva: definirea si initializarea unui element al vectorului
# conditia de continuare: inca nu s-au efectuat $n repetari
# nota: in acest caz cunoastem numarul de repetari, dat de variabila $n
 
for( $i = 1; $i <= $n; $i++) { 
 # intre paranteze se specifica expresia de initializare $i = 1
 # conditia de continuare $i <= $x si o expresie de iterare $i++
 
 $vector[ $i ] = "php$i"; # aceasta este operatia
}
 
print_r( $vector );
 
/*afiseaza:
Array
(
    [1] => php1
    [2] => php2
    [3] => php3
    [4] => php4
    [5] => php5
    [6] => php6
    [7] => php7
    [8] => php8
    [9] => php9
    [10] => php10
)
*/

Cum afisez o lista de link-uri?

<?php
/* similar exemplului anterior */
 
# operatia repetitiva: afisarea unui element de tip <li> cu valori dinamice
# conditia de continuare: inca nu s-au efectuat $n repetari
 
# va trebui sa avem lista de link-uri definita intr-un vector.
$links = array( 
 'www.punctsivirgula.ro',
 'php.punctsivirgula.ro',
 'php.punctsivirgula.ro?despre',
 'php.punctsivirgula.ro?legal'
);
 
# determin lungimea listei
$n = count( $links );
 
# avand lungimea, folosesc o structura for pentru a afisa lista
echo '<ul>';
for( $i = 0; $i < $n; $i++ ) {
 echo <<<LINK
   <li>
     <a href="http://{$links[ $i ]}" title="{$links[ $i ]}">{$links[ $i ]}</a>
   </li>
LINK;
}
echo '</ul>';
 
?>
Rezultat:
www.punctsivirgula.rophp.punctsivirgula.rophp.punctsivirgula.ro?desprephp.punctsivirgula.ro?legal

Cum afisez un element de tip select cu valori de la 1 la 100?

/* similar exemplului anterior */
 
$end = 100;
 
# operatia repetitiva: afisarea unui element de tip <option>
# conditia de continuare: inca nu s-au efectuat $end repetari
# nota: ca zi in cazul anterior se cunoaste numarul de repetari
 
print "<select>";
for( $i = 1; $i <= $end; $i++ ) {
 print "<option value=\"$i\">$i</option>\n";
}
print "</select>";
Rezultatul codului de mai sus este urmatorul:

Cum afisez un element de tip select cu toate tarile?

<?php
 
# ne trebuie o lista de tari. Cel mai uzual pastram doar codul tarii, iar numele il afisam doar. 
# Astfel, optiunile vor avea ca "value" codul tarii iar ca "text" - numele.
 
$countries = array(
 'AF'=>'Afghanistan',
 'AL'=>'Albania',
 'DZ'=>'Algeria',
 'AS'=>'American Samoa',
 'AD'=>'Andorra',
 'AO'=>'Angola',
 'AI'=>'Anguilla',
 'AQ'=>'Antarctica',
 'AG'=>'Antigua And Barbuda',
 'AR'=>'Argentina',
 'AM'=>'Armenia',
 /* ... */
 'WS'=>'Western Samoa',
 'YE'=>'Yemen',
 'YU'=>'Yugoslavia',
 'ZM'=>'Zambia',
 'ZW'=>'Zimbabwe'
);
 
# avand un array asociativ, este mai dificil sa-i accesam elementele, asa ca nu vom 
# mai folosi for. Vom folosi in schimb un iterator
 
echo '<select name="tara">', "\n"; # afisez pe alt rand pentru a aseza  in pagina sursa HTML
foreach( $countries as $code => $name ) {
 echo '<option value="', $code, '">', $name, '</option>', "\n";
}
echo "</select>\n";
 
?>
Rezultat:


Cum caut o valoare intr-un vector?

/* avem un vector cu un numar necunoscut de valori; vrem sa cautam valoarea 0
 * folosind o structura repetitiva */
 
$vector = array( 3, 4, 5, 1, 2, 9, 76, 42, 2, 9, 6, 0, 4, 1, 10 );
 
# operatia repetitiva: se verifica daca elementul curent al vectorului este 0
# conditia de oprire: elementul curent este 0 sau s-a ajuns la finalul vectorului
# nota: desi putem afla numarul de elemente al vectorului, in functie de care 
        putem determina numarul maxim de repetari, se va folosi structura while
 
 
$gasit = false;
$pozitie = 0; // plecam de la primul element
 
// parcurgem vectorul pana cand ajungem la final sau gasim valoarea 0
while( !$gasit ) { // echivalent cu while( $gasit == false )
 // verific daca elementul curent (initial primul element) este 0
 if( $vector[ $pozitie ] == 0 ) {
  $gasit = true;
  print "Am gasit 0 pe pozitia $pozitie";
 }
 
 // trec la pozitia urmatoare pentru verificare
 $pozitie++;
 // spre deosebire de "for" incrementarea trebuie realizata explicit
 
 // verific daca am ajuns la sfarsitul verctorului
 if( $pozitie == count( $vector ) ) {
  $gasit = true; // ca sa nu mai repete
  print "Nu am gasit 0 in vectorul asta";
 }
}
 
# in limbaj natural, instructiunea while se poate transpune in "cat timp
# conditia este indeplinita executa operatiunea"
 
/* afiseaza 
Am gasit 0 pe pozitia 11 
*/
Exemplul de mai sus este dat pentru a intelege cand si de ce se foloseste 'while'. Toata verificarea se poate face mult mai rapid folosind o functie oferita de limbaj: array_search.
// alternativa
$vector = array( 3, 4, 5, 1, 2, 9, 76, 42, 2, 9, 6, 0, 4, 1, 10 );
 
$pozitie = array_search(0, $vector );
 
if( $pozitie === false ) print "Nu am gasit 0 in vectorul asta";
else print "Am gasit 0 pe pozitia $pozitie";

Cum validez mai multe email-uri introduse de un utilizator?

<?php
 
# presupunem ca exista mai multe textbox-uri intr-un formular, numite email[] 
$emails = $_POST[ 'email' ]; # pentru detalii despre $_POST vedeti lectia "Formulare"
 
# pentru teste se poate folosi: 
$emails = array( 'ok@test.com', 'zzz', 'test@site', 'test@test.com', 'aaa' );
 
# folosesc o variabila ce actioneaza ca un flag/switch
$gasitInvalid = false;
 
# determin nr de email-uri
$n = count( $emails );
 
# plec de la primul email-uri
$i = 0;
 
// parcurgem vectorul pana cand ajungem la final sau gasim un email invalid
while( $gasitInvalid == false && $i < $n ) {
 // verific daca elementul curent (din iteratia curenta) este invalid
 if( strpos( $emails[ $i ], '@' ) === false || 
     strpos( $emails[ $i ], '.' ) === false ) {
  # un email valid trebuie sa contina @ si un punct
  $gasitInvalid = true;
  echo 'Am gasit un email invalid: ', $emails[ $i ], '<br />';
 
  //break;
  /* pot folosi break dar este inutil pentru ca se va iesi oricum 
  din bucla while datorita variabilei $gasitInvalid care e true */
 }
 $i++; # cresc pe $i
}
 
# daca s-a ajuns la sfarsitul sirului de email-uri si $gasitInvalid este tot false
# inseamna ca nu exista nici un element invalid
if( !$gasitInvalid ) echo 'Toate email-urile sunt valide!<br />';
 
?>
Rezultat:
Am gasit un email invalid: zzz
Nota: se putea folosi si structura repetitiva for pentru ca se cunosteau dinainte numarul de pasi ce trebuiau efectuati. In schimb, folosind aceasta implementare, atunci cand se gaseste un email valid se opreste executia (se iese din bucla while), asadar codul ar putea fi mai performant decat in cazul folosirii for.
Spre exemplu, daca avem un vector cu 15 elemente, iar pe pozitia a doua se afla un email invalid, atunci executia se termina dupa 2 pasi: la primul pas se verifica primul element care este valid, iar la al doilea, gasindu-se un email invalid se iese din ciclul while (din cauza ca $gasitInvalid nu mai este false).

Operatii cu vectori    6 ! 

Operatiile clasice de cautare, sortare, inserare, etc se pot realiza foarte usor cu ajutorul functiilor specializate, fara sa fie necesara parcurgerea manuala a vectorilor. Iata cateva exemple.
$vector = array( 1, 2, 3, 4, 5, 6 );
$vectAs = array(
 'unu' => 'one',
 'doi' => 'two',
 'trei' => 3
);
 
 
// lungimea unui vector (numarul de elemente) 
print count( $vector ); // 6
 
// se gaseste o valoare in vector?
print in_array( 3, $vector ); // true
 
// exista o anumita cheie in vector?
print array_key_exists( 'trei', $vectAs ); // true
 
// returneaza toate cheile din vector:
print_r( array_keys( $vectAs ) ); // Array ( [0] => unu [1] => doi [2] => trei )
 
// returneaza toate valorile din vector:
print_r( array_values( $vectAs ) ); // Array ( [0] => one [1] => two [2] => 3 )
 
// returneaza o parte din vector
print_r( array_slice(  $vector, 3 ) ); // de la pozitia 3 pana la final: 4, 5, 6
print_r( array_slice(  $vector, 3, 2 ) ); // de la pozitia 3, doua elemente: 4, 5
print_r( array_slice(  $vector, -5, 3 ) ); // de la final inapoi 5 pozitii: 2, 3, 4
 
// foloseste cheile unui vector ca variabile:
extract( $vectAs );
print $unu; // one
print $doi; // two
print $trei; // 3
 
// sorteaza un vector
sort( $vector ); // 1, 2, 3, 4, 5, 6
rsort( $vector ); // 6, 5, 4, 3, 2, 1
asort( $vectAs ); // sorteaza valorile si mentine asocierea cheilor
 
// preluare elemente unice din vector
print_r( array_unique( $vector ) );
 
// adauga o valoare la sfarsitul unui vector
$vector[] = 7;
array_push( $vector, 8 );
# nota: cele 2 instructiuni de mai sus sunt echivalente
 
// modifica un anumit element din vector
$vectAs[ 'trei' ] = 'three';

Aplicatie: Sa se afiseze tipul browserului folosit de utilizator    5 ! 

Depanare    0 ! 

// afisarea unui 'dump' al vectorului - o lista cu toate elementele. 
//De obicei se foloseste la depanare:
 
print_r( $vectAs );
/* afiseaza
Array
(
    [unu] => one
    [doi] => two
    [trei] => 3
)
*/
 
 
// se afiseaza la fel ca mai sus o lista cu elementele vectorului, doar 
// ca se specifica si tipul fiecaruia.
 
var_dump( $vectAs );
/* afiseaza
array(3) {
  ["unu"]=>
  string(3) "one"
  ["doi"]=>
  string(3) "two"
  ["trei"]=>
  int(3)
}
*/
Limbajul PHP ofera solutii simple (dar puternice) pentru lucrul cu data si timpul. In versiunile mai noi (dupa 5.1) sunt introduse facilitati avansate cum ar fi DST (Daylight Saving Time), Timezones, Date Intervals, s.a. Inainte de acestea insa lucrul cu timpul se realiza folosind Unix timestamp.
Conceptul de Unix timestamp desemneaza numarul de secunde scurse de la 1 ianuarie 1970 (cand se considera ca a inceput era Unix).
Unix Timestamp-ul curent: 
1452844743
Fiind vorba de un numar pozitiv ce are mereu aceeasi referinta, este usor sa se realizeze operatii cum ar fi scaderea, adunarea sau compararea a doua date reprezentate printr-un Unix timestamp.
Mai jos sunt cateva aplicatii menite sa evidentieze cat de usor se pot manipula date si ore in PHP.
<?php
// data curenta
print date( 'd.m.Y H.i.s' ); // 15.01.2016 09.59.03 
 
// data in format Unix (UNIX timestamp)
print time(); // 1452844743 
 
// alegerea unui fus orar
date_default_timezone_set( 'Europe/Bucharest' );
 
// parsarea unei date
print strtotime("now");
print strtotime('1st January 2004'); //1072915200
?>

Cum aflu o data din trecut sau viitor?    3 ! 

Sunt mai multe posibilitati. Se poate pleaca de la o data cunoscuta (pentru care avem Unix timestamp) si prin adunari/scaderi de secunde se afla data dorita (vezi aplicatia de mai jos). Sau se poate parsa o data folosind strtotime. Aceste solutii nu sunt intotdeauna aplicabile, iar in aceste cazuri se foloseste functiamktime.
Functia mktime primeste ca parametri anul, luna, ziua, ora pentru care se doreste aflarea detaliilor. Rezultatul este un timestamp ce poate fi formatat dupa cum se doreste.
<?php
# care este timestamp-ul pentru 31 januarie 2004, ora 13:00
echo mktime( 13, 0, 0, 1, 31, 2004); // afiseaza 1075546800 
 
# care este timestamp-ul pentru 3 septembrie 2014, ora 10:30
echo mktime( 10, 30, 0, 9, 3, 2014); // afiseaza 1409729400 
 
# ultima zi a unei luni poate fi exprimata ca ziua "0" a lunii urmatoare. 
$ultima = mktime(0, 0, 0, 3, 0, 2000);
echo strftime("Ultima zi din Februarie 2000 este: %d", $ultima );
// afiseaza Ultima zi din Februarie 2000 este: 29
 
# se pot folosi si valori negative
$zi = mktime(0, 0, 0, 3, -3, 2000);
echo strftime("Inainte de Martie 2000 cu 4 zile: %d", $zi );
// afiseaza Inainte de Martie 2000 cu 4 zile: 26
 
?>
Important: inainte de PHP 5.1.0, timestamp-urile negative nu erau suportate in unele sisteme (inclusiv Windows). De aceea domeniul valid al anilor era limitat intre 1970 si 2038.

Cum se formateaza data sau ora?    1 ! 

Formatarea datei sau a orei se poate realiza usor folosind functia date. Cu ajutorul acesteia se pot "extrage" doar acele parti din data care sunt necesare si se poate specifica formatul dorit. Spre exemplu, folosind functia date putem afisa data in format lung (de genul: "marti, 30 septembrie 2001") sau scurt (30.11.2001) sau cu aceeasi functie putem afisa ora sau oricare combinatie a celor doua.
Formatul se specifica print-un text format din caractere ce au o semnificatie anume, transmis ca parametru functiei date. Pentru detalii complete despre fiecare caracter in parte accesatihttp://www.php.net/manual/ro/function.date.php.
<?php
# se preia data/ora curenta
$acum = time(); // $acum este o data in format Unix: 1452844743 
 
# formatarea se realizeaza cu functia date
# daca nu se specifica altfel, functia date va formata data/ora curenta
echo date("H:i:s") . "<br>"; // afiseaza 09:59:03 
echo date("Y-m-d") . "<br>"; // afiseaza 2016-01-15 
echo date("F j, Y, g:i a") . "<br>"; // afiseaza January 15, 2016, 9:59 am 
echo date("l") . "<br>"; // afiseaza Friday 
 
# se poate specifica un al doilea parametru ce reprezinta data/ora care se formateaza
echo date("d-m-Y H:i:s", $acum) . "<br>"; // afiseaza 15-01-2016 09:59:03 
echo date("D, M d, Y", 1072915200) . "<br>"; // afiseaza Thu, Jan 01, 2004 
 
# combinat cu mktime, se pot obtine informatii despre zile din trecut sau viitor
# de exemplu, ce zi a fost pe 4 iulie 2000
$iulie4 = mktime( 0, 0, 0, 7, 4, 2000 ); # aflu timestamp-ul
echo date( 'l', $iulie4 ); # formatez acel timestamp - extrag doar ziua
// afiseaza Tuesday
 
?>

Cum determin ce zi si ora va fi peste 480 ore?    5 ! 

Pentru a efectua usor operatii cu zile si ore, se va folosi formatul de data Unix (UNIX timestamp), returnat de functia time(). Practic, data este afisata ca numarul de secunde scurs de la 1 ianuarie 1970, ora 00:00. Avand aceasta noua perspectiva (de a privi datele ca un numar de secunde), operatiile cu date (de genul 'cat va fi peste 2 zile', 'ce ora a fost acum xxx minute', etc) devin extrem de simple luand forma unor simple scaderi si adunari de secunde.
<?php
// cerinta este: "cat va fi ora peste 480 de ore, adica peste (480 * 60 *60) secunde
 
$acum = time();
$maiTarziu = 480 /*ore*/ * 60 /*minute*/ * 60 /*secunde*/;
 
print "Data ceruta este: " . date( 'd.m.Y H.i.s', $acum + $maiTarziu );
// Data ceruta este: : 04.02.2016 09.59.03 
?>

Cum validez o data sau un timp?    7 ! 

Sunt mai multe modalitati de a valida datele si orele introduse de un utilizator, in functie de formatul acestora. Cel mai uzual insa se folosesc cele 2 functii de aflare a timestamp-ului: mktime si strtotime. Acestea returneaza anumite valori in cazul in care data verificata nu este valida.
<?php
# mktime se foloseste cand avem date bine definite
# de exempleu, verificam daca a existat 29 februarie 2004
$rezultat = mktime( 0, 0, 0, 2, 29, 2004 );
if( $rezultat === FALSE || $rezultat === -1 ) { 
 # daca rezultatul nu este un timestamp inseamna ca data nu e valida
 echo "Data nu exista";
} else {
 echo "Data este valida: " . date( 'd.m.Y', $rezultat);
}
// Rezultat: Data este valida: 29.02.2004
 
 
# strtotime se foloseste cand avem date relative
$rezultat = strtotime( "2 days ago" );
if( $rezultat === FALSE || $rezultat === -1 ) { 
 echo "Data nu exista";
} else {
 echo "Data este valida: " . date( 'd.m.Y', $rezultat);
}
// Rezultat: Data este valida: 13.01.2016
 
?>

Cum afisez un mesaj de salut in functie de ora curenta (a serverului)?    0 ! 

<?php
$t = localtime( time(), true ); // returneaza un vector cu elementele datei si orei locale
$h = $t[ 'tm_hour' ]; // iau doar ora
 
if( $h >= 7 && $h <= 11 ) print "Buna dimineata!";
elseif( $h > 11 && $h < 18 ) print "Buna ziua!";
elseif( $h >= 18 && $h < 22 ) print "Buna seara!";
elseif( $h >= 22 ) print "Noapte buna!";
else print "Ce? Esti treaz(a) la ora asta?";
 
// Buna dimineata! 
?>

Cum afisez luna curenta si toate cele 12 luni in limba romana?    1 ! 

Nota: aceasta secventa de cod depinde de configurarile serverului pe care este executata. Limba romana trebuie instalata pe server pentru a avea rezultatele scontate.
<?php
setlocale( LC_TIME , 'ROM_ROM' );
 
// afiseaza numele celor 12 luni
for( $m = 1; $m <= 12; $m++ ) {
 print strftime( "%B", mktime( 0,0,0, $m, 1, 2008 ) ) . "\n";
}
 
// afiseaza luna curenta
print 'Luna curenta este: ' . strftime( "%B", time() );
?>
Rezultatul (este posibil sa nu fie in limba romana!):
January
February
March
April
May
June
July
August
September
October
November
December

Luna curenta este: January

Cum determin durata de executie a unui script PHP?    0 ! 

<?php
$time_start = microtime(true); # la inceputul codului PHP
 
/* ... codul PHP cu diverse operatii ... */
 
# la final se face diferenta si se afiseaza
$time_end = microtime(true);
 
print "Durata de executie (secunde): " . ( number_format($time_end - $time_start, 6) ); 
// Durata de executie (secunde): 0.001198 
?>

Niciun comentariu:

Trimiteți un comentariu