Introducere: Definitie
Introducere: Definitie
1. Introducere
Definitie PHP (Hypertext Preprocessor) = este un limbaj open source de scripting cu scop general
care este deosebit de potrivit pentru dezvoltarea web și poate fi încorporat în HTML.
Codul PHP este inclus în instrucțiuni speciale de început și sfârșit de procesare <?php și ?>
care permit intrarea și ieșirea din „modul PHP”. Codul este executat pe server, generând HTML
care este apoi trimis către client. Clientul primește rezultatele executării acelui script, dar nu știe
care este codul de bază.
Există două domenii principale în care sunt utilizate scripturile PHP:
• Scripturi server-side. Acesta este cel mai utilizat și principalul domeniu țintă pentru PHP.
Trei lucruri sunt necesare pentru a face acest lucru să funcționeze: analizorul PHP (modulul
CGI sau server), un server web și un browser web. Toate acestea pot rula pe o mașină locală
pentru a experimenta doar cu programarea PHP.
• Scripturi în linia de comandă. Un script PHP poate fi rulat fără niciun server sau browser,
fiind necesar doar analizorul PHP pentru a-l utiliza în acest mod. Acest tip de utilizare este
ideal pentru scripturile executate în mod regulat folosind cron (pe Unix sau macOS) sau
Task Scheduler (pe Windows). Aceste scripturi pot fi utilizate și pentru sarcini simple de
prelucrare a textului.
Important Una dintre cele mai puternice caracteristici ale PHP este modul în care gestionează
formularele HTML. Conceptul de bază care este important de înțeles este că orice element de
formular va fi automat disponibil pentru scripturile PHP.
Exemplu
<form action="[Link]" method="post">
<label for="name">Your name:</label>
<input name="name" id="name" type="text">
Important În afară de părțile htmlspecialchars() și (int), ar trebui să fie evident ce face acest lucru.
htmlspecialchars() se asigură că orice caractere speciale în html sunt codificate corect, astfel încât
oamenii să nu poată injecta etichete HTML sau Javascript în pagina ta. Pentru câmpul de vârstă,
deoarece știm că este un număr, îl putem converti într-un int care va scăpa automat de orice
caractere rătăcite. Variabilele $_POST['nume'] și $_POST['vârstă'] sunt setate automat pentru dvs.
de PHP. Mai devreme am folosit $_SERVER superglobal; mai sus tocmai am introdus superglobalul
$_POST care conține toate datele POST. Observați cum metoda formularului nostru este POST.
Dacă am folosi metoda GET, atunci informațiile noastre din formular ar locui în locul superglobal
$_GET. De asemenea, puteți utiliza superglobalul $_REQUEST, dacă nu vă pasă de sursa datelor
solicitate. Conține informațiile îmbinate ale datelor GET, POST și COOKIE.
Exemplu
<?php echo 'if you want to serve PHP code in XHTML or XML documents, use these tags'; ?>
You can use the short echo tag to <?= 'print this string' ?>. It's equivalent to <?php echo 'print
this string' ?>.
Important Etichetele scurte (exemplul trei) sunt disponibile implicit, dar pot fi dezactivate fie prin
directiva fișierului de configurare short_open_tag [Link], fie sunt dezactivate implicit dacă PHP
este construit cu configurația –disable-short-tags.
Important Dacă un fișier conține doar cod PHP, este de preferat să omiteți eticheta de închidere
PHP la sfârșitul fișierului. Acest lucru previne adăugarea accidentală de spații albe sau de noi linii
după eticheta de închidere PHP, ceea ce poate provoca efecte nedorite, deoarece PHP va începe
bufferingul de ieșire atunci când programatorul nu intenționează să trimită vreo ieșire în acel
moment al scriptului.
Exemplu
<?php
echo "Hello world";
Exemplu
<?php if ($expression == true): ?>
This will show if the expression is true.
<?php else: ?>
Otherwise this will show.
<?php endif; ?>
Important În acest exemplu, PHP va sări peste blocurile în care condiția nu este îndeplinită, chiar
dacă acestea sunt în afara etichetelor PHP open/close; PHP le omite în funcție de condiție, deoarece
interpretul PHP va sări peste blocurile conținute într-o condiție care nu este îndeplinită.
4. Separarea instructiunilor
Important PHP necesită ca instrucțiunile să fie terminate cu un punct și virgulă la sfârșitul fiecărei
instrucțiuni.
Exemplu
<?php echo "Some text"; ?>
No newline
<?= "But newline now" ?>
5. Comentarii
Important Comentariile în php se pot adauga folosit caracterele „//”, „/**/” și „#”. Caracterul „/**/”
aplica comentarii pe mai multe linii de cod, în schimb cele doua doar pe câte o linie.
Exemplu
<?php
echo 'This is a test'; // This is a one-line c++ style comment
/* This is a multi line comment
yet another line of comment */
echo 'This is yet another test';
echo 'One Final Test'; # This is a one-line shell-style comment
?>
6. Tipurile de date
Important Fiecare expresie din PHP are urmatoarele tipuri de date: null, bool, int, float, string,
array, object, callable, resource.
Important Pentru a verifica valoarea și tipul unei expresii, utilizați funcția var_dump(). Pentru a
prelua tipul unei expresii, utilizați funcția get_debug_type(). Cu toate acestea, pentru a verifica dacă
o expresie este de un anumit tip, utilizați în schimb funcțiile is_type.
Important O valoare este considerata scalara daca este de tipul int, float, string sau bool; iar prin
intermediul interfaces, classes sau a enumerations putem defini tipuri customizabile de date. De
exemplu putem defini o clasa Elephant, apoi pot fi instantiate obiecte de tip Elephant, iar o funcție
poate solicita un parametru de tip Elephant.
<?php
$a = 1.234;
$b = 1.2e3;
$c = 7E-10;
$d = 1_234.567; // as of PHP 7.4.0
?>
Important Daca un tip de date este numeric se poate converti la float, iar daca nu este numeric mai
întâi se converteste la int și apoi se converteste la float. Pentru a compara doua valori de tip float a
și b se utilizeaza o limita superioara a erorii relative datorate rotunjirii, valoare cunoscuta sub
denumirea de epsilon. Ex:
<?php
$a = 1.23456789;
$b = 1.23456780;
$epsilon = 0.00001;
Important Unele operații numerice pot avea ca rezultat o valoare reprezentată de constanta NaN.
Acest rezultat reprezintă o valoare nedefinită sau nereprezentabilă în calculele cu virgulă mobilă.
De regula se mai verifica prin utilizarea functiei is_nan().
<?php
echo 'this is a simple string';
echo 'You can also have embedded newlines in
strings this way as it is
okay to do';
Important Dacă șirul este cuprins între ghilimele ("), PHP va interpreta următoarele secvențe de
escape pentru caractere speciale:
\n linefeed (LF or 0x0A (10) in ASCII)
\r carriage return (CR or 0x0D (13) in ASCII)
\t horizontal tab (HT or 0x09 (9) in ASCII)
\v vertical tab (VT or 0x0B (11) in ASCII)
\e escape (ESC or 0x1B (27) in ASCII)
\f form feed (FF or 0x0C (12) in ASCII)
\\ backslash
\$ dollar sign
\" double-quote
Octal: the sequence of characters matching the regular expression [0-7]{1,3}
\[0-7]{1,3} is a character in octal notation (e.g. "\101" === "A"), which silently
overflows to fit in a byte (e.g. "\400" === "\000")
Hexadecimal: the sequence of characters matching the regular expression [0-
\x[0-9A-Fa-
9A-Fa-f]{1,2} is a character in hexadecimal notation (e.g. "\x41" ===
f]{1,2}
"A")
Unicode: the sequence of characters matching the regular expression [0-9A-
\u{[0-9A- Fa-f]+ is a Unicode codepoint, which will be output to the string as that
Fa-f]+} codepoint's UTF-8 representation. The braces are required in the sequence. E.g.
"\u{41}" === "A"
Important Un al treilea mod de a delimita șirurile de caractere este sintaxa heredoc: <<<. După
acest operator, este furnizat un identificator, apoi o nouă linie. Urmează șirul în sine și apoi din nou
același identificator pentru a închide ghilimele.
<?php
$foo = 1 + "10.5"; // $foo is float (11.5)
$foo = 1 + "-1.3e3"; // $foo is float (-1299)
$foo = 1 + "bob-1.3e3"; // TypeError as of PHP 8.0.0, $foo is integer (1) previously
$foo = 1 + "bob3"; // TypeError as of PHP 8.0.0, $foo is integer (1) previously
$foo = 1 + "10 Small Pigs"; // $foo is integer (11) and an E_WARNING is raised in PHP 8.0.0,
E_NOTICE previously
$foo = 4 + "10.2 Little Piggies"; // $foo is float (14.2) and an E_WARNING is raised in PHP 8.0.0,
E_NOTICE previously
$foo = "10.0 pigs " + 1; // $foo is float (11) and an E_WARNING is raised in PHP 8.0.0,
E_NOTICE previously
$foo = "10.0 pigs " + 1.0; // $foo is float (11) and an E_WARNING is raised in PHP 8.0.0,
E_NOTICE previously
?>
Important Atunci când un șir trebuie evaluat ca număr (de exemplu, operații aritmetice, declarație
de tip int etc.), se parcurg următorii pași pentru a determina rezultatul:
• Dacă șirul este numeric, se rezolvă la un int dacă șirul este un șir numeric întreg și se
încadrează în limitele limitelor de tip int (așa cum sunt definite de PHP_INT_MAX), în caz
contrar, se rezolvă la un șir flotant.
• Dacă contextul permite șiruri numerice de început și șirul este unul, rezolvați la un int dacă
partea de început a șirului este un șir numeric întreg și se încadrează în limitele limitelor de
tip int (așa cum sunt definite de PHP_INT_MAX), în caz contrar rezolvați la un plutire. În
plus, este ridicată o eroare de nivel E_WARNING
• Șirul nu este numeric, aruncați un TypeError.
13. Array
Important O matrice (array) în PHP este de fapt o hartă ordonată. O hartă este un tip care asociază
valori cu chei. Acest tip este optimizat pentru mai multe utilizări diferite; poate fi tratat ca o matrice,
listă (vector), tabel hash (o implementare a unei hărți), dicționar, colecție, stivă, coadă și, probabil,
multe altele. Deoarece valorile matricei pot fi alte matrice, sunt posibile și arbori și matrice
multidimensionale.
array(
key => value,
key2 => value2,
key3 => value3,
...)
Important Virgula după ultimul element de matrice este opțională și poate fi omisă.
<?php
$array = array(
"foo" => "bar",
"bar" => "foo",
);
14. Obiecte
Important Pentru a crea un obiect nou, utilizați instrucțiunea nouă pentru a instanția o clasă:
<?php
class foo {
function do_foo() {
echo "Doing foo.";
}
}
15. Enumeratii
Important Enumerările sunt un strat restrictiv deasupra claselor și constantelor de clasă, menite să
ofere o modalitate de a defini un set închis de valori posibile pentru un tip.
<?php
enum Suit
{
case Hearts;
case Diamonds;
case Clubs;
case Spades;
}
16. Resurse
Important O resursă este o variabilă specială, care conține o referință la o resursă externă. Resursele
sunt create și utilizate de funcții speciale. Consultați anexa pentru o listă a tuturor acestor funcții și a
tipurilor de resurse corespunzătoare.
<?php
18. Mixt
Important Tipul mixt acceptă fiecare valoare. Este echivalent cu tipul de unire obiect|resursa|
matrice|string|float|int|bool|null. Disponibil începând cu PHP 8.0.0. Mixt este, în limbajul teoriei
tipurilor, tipul de vârf. Înseamnă că orice alt tip este un subtip al acestuia.
19. Void
Important void este o declarație de tip de returnare care indică faptul că funcția nu returnează o
valoare, dar funcția se poate termina. Prin urmare, nu poate face parte dintr-o declarație de tip
uniune. Disponibil începând cu PHP 7.1.0.
20. Never
Important Never nu este un tip de returnare care indică faptul că funcția nu se termină. Aceasta
înseamnă că fie apelează exit(), aruncă o excepție, fie este o buclă infinită. Prin urmare, nu poate
face parte dintr-o declarație de tip uniune. Never nu este, în limbajul teoriei tipurilor, tipul de jos.
Înseamnă că este subtipul oricărui alt tip și poate înlocui orice alt tip de returnare în timpul
moștenirii.
22. Iterable
Important Iterable este un alias de tip timp de compilare încorporat pentru array|Traversable. Un tip
iterabil poate fi utilizat pentru fiecare și cu randament din interiorul unui generator.
<?php function gen(): iterable { yield 1; yield 2; yield 3; } ?>
23. Variabile
Important Variabilele în PHP sunt reprezentate de un semn dolar urmat de numele variabilei.
Numele variabilei face distincție între majuscule și minuscule. Un nume de variabilă valid începe
cu o literă (A-Z, a-z sau octeții de la 128 la 255) sau liniuță de subliniere, urmată de orice număr de
litere, cifre sau liniuțe de subliniere. Ca expresie regulată, ar fi exprimată astfel: ^[a-zA-Z_\x80-\
xff][a-zA-Z0-9_\x80-\xff]*$
<?php
$var = 'Bob';
$Var = 'Joe';
echo "$var, $Var"; // outputs "Bob, Joe"
<?php
$foo = 'Bob'; // Assign the value 'Bob' to $foo
$bar = &$foo; // Reference $foo via $bar.
$bar = "My name is $bar"; // Alter $bar...
echo $bar;
echo $foo; // $foo is altered too.
?>
<?php
$foo = 25;
$bar = &$foo; // This is a valid assignment.
$bar = &(24 * 7); // Invalid; references an unnamed expression.
function test()
{
return 25;
}
Important Sfera de aplicare a unei variabile este contextul în care este definită. Orice variabilă
definită în afara unei funcții este limitată la domeniul global. Când un fișier este inclus, codul pe
care îl conține moștenește domeniul variabil al liniei pe care are loc includerea.
<?php
$a = 1;
include '[Link]'; // Variable $a will be available within [Link]
?>
<?php
$a = 1; // global scope
function test()
{
echo $a; // Variable $a is undefined as it refers to a local version of $a}
?>
Important Exemplul de mai sus va genera o variabilă nedefinită E_WARNING (sau un E_NOTICE
înainte de PHP 8.0.0). Acest lucru se datorează faptului că instrucțiunea echo se referă la o versiune
locală a variabilei $a și nu i s-a atribuit o valoare în acest domeniu.
Important Cuvântul cheie global este folosit pentru a lega o variabilă dintr-un domeniu global într-
un domeniu local. Cuvântul cheie poate fi folosit cu o listă de variabile sau cu o singură variabilă.
Va fi creată o variabilă locală care face referire la variabila globală cu același nume. Dacă variabila
globală nu există, variabila va fi creată în domeniul global și va fi atribuită nul.
<?php
$a = 1;
$b = 2;
function Sum()
{
global $a, $b;
$b = $a + $b;
}
Sum();
echo $b;
?>
<?php
$a = 1;
$b = 2;
function Sum()
{
$GLOBALS['b'] = $GLOBALS['a'] + $GLOBALS['b'];
}
Sum();
echo $b;
?>
Important Tabloul $GLOBALS este un tablou asociativ cu numele variabilei globale fiind cheia și
conținutul acelei variabile fiind valoarea elementului de matrice.
Important O altă caracteristică importantă a domeniului variabilei este variabila statică. O variabilă
statică există doar într-un domeniu de aplicare local, dar nu își pierde valoarea atunci când execuția
programului părăsește acest domeniu.
<?php
function test()
{
$a = 0; // or static $a = 0;
echo $a;
$a++;
}
?>
Important Uneori este convenabil să poți avea nume de variabile variabile. Adică, un nume de
variabilă care poate fi setat și utilizat dinamic. O variabilă normală este setată cu o instrucțiune
precum:
<?php
$a = 'hello';
?>
Important O variabilă variabilă ia valoarea unei variabile și o tratează ca pe numele unei variabile.
În exemplul de mai sus, salut, poate fi folosit ca nume al unei variabile folosind două semne de
dolar. adică
<?php
$$a = 'world';
?>
Important În acest moment au fost definite și stocate două variabile în arborele simbol PHP: $a cu
conținutul „hello” și $hello cu conținutul „world”. Prin urmare, această afirmație:
<?php
echo "$a {$$a}"; // este echivalent cu echo "$a $hello";
?>
Important Când un formular este trimis la un script PHP, informațiile din formularul respectiv sunt
puse automat la dispoziția scriptului. Există câteva modalități de a accesa aceste informații, de
exemplu:
<?php
echo $_POST['username'];
echo $_REQUEST['username'];
?>
Important Utilizarea unui formular GET este similară, cu excepția faptului că variabila predefinită
GET corespunzătoare poate fi utilizată în schimb. GET se aplică și pentru QUERY_STRING
(informațiile de după „?” dintr-o adresă URL).
Important Când trimiteți un formular, este posibil să utilizați o imagine în locul butonului standard
de trimitere cu o etichetă precum: <input type="image" src="[Link]" name="sub" /> Când
utilizatorul face clic undeva pe imagine, formularul însoțitor va fi transmis serverului cu două
variabile suplimentare, sub_x și sub_y. Acestea conțin coordonatele clicului utilizatorului în
imagine.
Important PHP acceptă în mod transparent cookie-urile HTTP așa cum sunt definite de » RFC
6265. Cookie-urile sunt un mecanism de stocare a datelor în browserul de la distanță și, astfel, de
urmărire sau de identificare a utilizatorilor reveniți. Este posibil să setați cookie-uri folosind funcția
setcookie(). Cookie-urile fac parte din antetul HTTP, astfel încât funcția SetCookie trebuie apelată
înainte ca orice rezultat să fie trimis către browser. Aceasta este aceeași restricție ca și pentru funcția
header(). Datele cookie sunt apoi disponibile în matricele de date cookie corespunzătoare, cum ar fi
$_COOKIE, precum și în $_REQUEST.
<?php
setcookie("MyCookie[foo]", 'Testing 1', time()+3600);
setcookie("MyCookie[bar]", 'Testing 2', time()+3600);
?>
Important Acest lucru va crea două cookie-uri separate, deși MyCookie va fi acum o singură
matrice în script. Dacă un singur cookie ar trebui setat cu mai multe valori, luați în considerare mai
întâi utilizarea serialize() sau explode() pe valoare.
Important Deoarece PHP determină tipurile de variabile și le convertește (în general) după cum
este necesar, nu este întotdeauna evident ce tip este o anumită variabilă la un moment dat. PHP
include mai multe funcții care află ce tip este o variabilă, cum ar fi: gettype(), is_array(), is_float(),
is_int(), is_object() și is_string().
<?php
if (isset($_COOKIE['count'])) {
$count = $_COOKIE['count'] + 1;
} else {
$count = 1;
}
setcookie('count', $count, time()+3600);
setcookie("Cart[$count]", $item, time()+3600);
?>
24. Constante
Important O constantă este un identificator (nume) pentru o valoare simplă. După cum sugerează și
numele, această valoare nu se poate schimba în timpul executării scriptului (cu excepția
constantelor magice, care nu sunt de fapt constante). Constantele sunt sensibile la majuscule. Prin
convenție, identificatorii constantelor sunt întotdeauna majuscule.
Important Numele unei constante urmează aceleași reguli ca orice etichetă în PHP. Un nume de
constantă valid începe cu o literă sau un semn de subliniere, urmat de orice număr de litere, cifre
sau semne de subliniere. Ca expresie regulată, ar fi exprimată astfel: ^[a-zA-Z_\x80-\xff][a-zA-Z0-
9_\x80-\xff]*$.
Important Constantele pot fi definite cu ajutorul cuvântului-cheie const sau prin utilizarea funcției
define(). În timp ce define() permite definirea unei constante într-o expresie arbitrară, cuvântul-
cheie const are restricții, așa cum se subliniază în paragraful următor. Odată ce o constantă este
definită, aceasta nu poate fi niciodată modificată sau nedefinită.
<?php
// Valid constant names
define("FOO", "something");
define("FOO2", "something else");
define("FOO_BAR", "something more");
Important PHP oferă un număr mare de constante predefinite pentru orice script pe care îl rulează.
Cu toate acestea, multe dintre aceste constante sunt create de diverse extensii și vor fi prezente
numai atunci când aceste extensii sunt disponibile, fie prin încărcare dinamică, fie pentru că au fost
compilate.
Important Există câteva constante magice care se schimbă în funcție de locul în care sunt utilizate.
De exemplu, valoarea __LINE__ depinde de linia pe care este utilizată într-un script. Toate aceste
constante „magice” sunt rezolvate la momentul compilării, spre deosebire de constantele obișnuite,
care sunt rezolvate la momentul rulării. Aceste constante speciale sunt insensibile la majuscule și
sunt după cum urmează:
Name Description
__LINE__ Numărul liniei curente din fișier.
Calea completă și numele fișierului, cu rezolvarea legăturilor simbolice.
__FILE__ Dacă este utilizat în interiorul unei incluziuni, este returnat numele fișierului
inclus.
Directorul fișierului. Dacă este utilizat în interiorul unei incluziuni, este
__DIR__ returnat directorul fișierului inclus. Acest lucru este echivalent cu
dirname(__FILE__). Acest nume de director nu are o bară oblică finală, cu
excepția cazului în care este directorul rădăcină.
__FUNCTION__ Numele funcției, sau {closure} pentru funcții anonime.
Numele clasei. Numele clasei include spațiul de nume în care a fost
__CLASS__ declarată (de exemplu, Foo\Bar). Atunci când este utilizat în interiorul unei
metode de trăsătură, __CLASS__ este numele clasei în care este utilizată
trăsătura.
__TRAIT__ Numele trăsăturii. Numele trăsăturii include spațiul de nume în care a fost
declarată (de exemplu, Foo\Bar).
__METHOD__ Numele metodei clasei.
__PROPERTY__ Valabil numai în interiorul unui cârlig de proprietate. Este egal cu numele
proprietății.
__NAMESPACE__ Numele spațiului de nume curent.
ClassName::cla
ss Numele complet calificat al clasei.
25. Expresii
Important Expresiile sunt cele mai importante elemente de bază ale PHP. În PHP, aproape orice
scrieți este o expresie. Cel mai simplu, dar și cel mai precis mod de a defini o expresie este „orice
lucru care are o valoare”.
Important Cele mai de bază forme de expresii sunt constantele și variabilele. Când scrieți $a = 5,
atribuiți 5 în $a. 5, evident, are valoarea 5 sau, cu alte cuvinte, 5 este o expresie cu valoarea 5 (în
acest caz, 5 este o constantă întreagă).
<?php
function foo ()
{
return 5;
}
?>
Important Desigur, valorile în PHP nu trebuie să fie neapărat numere întregi și foarte des nu sunt.
PHP acceptă patru tipuri de valori scalare: valori int, valori în virgulă mobilă (float), valori string și
valori bool (valorile scalare sunt valori pe care nu le puteți „rupe” în bucăți mai mici, spre deosebire
de array-uri, de exemplu). PHP acceptă, de asemenea, două tipuri compuse (nescalare): array-uri și
obiecte. Fiecare dintre aceste tipuri de valori poate fi atribuită în variabile sau returnată din funcții.
Important Mai există o expresie care poate părea ciudată dacă nu ați văzut-o în alte limbi,
operatorul condițional ternar:
<?php $first ? $second : $third ?>
Important Dacă valoarea primei subexpresii este adevărată (diferită de zero), atunci a doua
subexpresie este evaluată și acesta este rezultatul expresiei condiționale. În caz contrar, a treia
subexpresie este evaluată, iar aceasta este valoarea.
<?php
function double($i)
{
return $i*2;
}
$b = $a = 5; /* assign the value five into the variable $a and $b */
$c = $a++; /* post-increment, assign original value of $a
(5) to $c */
$e = $d = ++$b; /* pre-increment, assign the incremented value of
$b (6) to $d and $e */
Important Operatorul de diviziune / returnează o valoare float, cu excepția cazului în care cei doi
operanzi sunt int (sau șiruri numerice care sunt transformate în int), iar numărătorul este un multiplu
al divizorului, caz în care va fi returnată o valoare întreagă. Pentru diviziunea numerelor întregi,
consultați intdiv().
Important Operanzii modulo sunt convertiți în int înainte de prelucrare. Pentru modulo în virgulă
mobilă, consultați fmod().
Important Operatorii bitwise permit evaluarea și manipularea anumitor biți dintr-un număr întreg.
Important Deplasarea biților în PHP este aritmetică. Biturile deplasate de la ambele capete sunt
eliminate. La deplasarea spre stânga, zerourile sunt deplasate în dreapta, în timp ce bitul de semn
este deplasat în stânga, ceea ce înseamnă că semnul unui operand nu este păstrat. În cazul deplasării
spre dreapta, copiile bitului de semn sunt deplasate spre stânga, ceea ce înseamnă că semnul unui
operand este păstrat.
Important Dacă ambii operanzi pentru operatorii &, | și ^ sunt șiruri de caractere, operația va fi
efectuată asupra valorilor ASCII ale caracterelor care alcătuiesc șirurile de caractere, iar rezultatul
va fi un șir de caractere. În toate celelalte cazuri, ambii operanzi vor fi convertiți în numere întregi,
iar rezultatul va fi un număr întreg.
Important Dacă operandul pentru operatorul ~ este un șir de caractere, operația va fi efectuată
asupra valorilor ASCII ale caracterelor care alcătuiesc șirul, iar rezultatul va fi un șir de caractere; în
caz contrar, operandul și rezultatul vor fi tratate ca numere întregi.
Important Atât operanzii, cât și rezultatul pentru operatorii << și >> sunt întotdeauna tratați ca
numere întregi.
Important Operatorii de comparare, după cum sugerează și numele lor, vă permit să comparați două
valori. De asemenea, este posibil să fiți interesat să vizualizați tabelele de comparare a tipurilor,
deoarece acestea prezintă exemple de diverse comparații legate de tipuri.
Important Dacă ambii operanzi sunt șiruri numerice sau unul dintre operanzi este un număr, iar
celălalt este un șir numeric, atunci comparația se face numeric. Aceste reguli se aplică și la
instrucțiunea switch. Conversia de tip nu are loc atunci când comparația este === sau !==, deoarece
aceasta implică compararea tipului, precum și a valorii.
Type of Type of
Result
Operand 1 Operand 2
null or string string Convert null to "", numerical or lexical comparison
bool or null anything Convert both sides to bool, false < true
Built-in classes can define its own comparison, different classes
object object
are incomparable, same class see Object Comparison
string, string,
resource, int or resource, int or Translate strings and resources to numbers, usual math
float float
Array with fewer members is smaller, if key from operand 1 is not
array array found in operand 2 then arrays are incomparable, otherwise -
compare value by value (see following example)
object anything object is always greater
array anything array is always greater
Important Expresia (expr1) ? (expr2) : (expr3) se evaluează la expr2 dacă expr1 se evaluează la
adevărat și la expr3 dacă expr1 se evaluează la fals. Este posibil să se omită partea din mijloc a
operatorului ternar. Expresia expr1 ?: expr3 se evaluează la rezultatul expr1 dacă expr1 se evaluează
la true, și la expr3 în caz contrar. expr1 este evaluată o singură dată în acest caz.
Important Expresia (expr1) ?? (expr2) este evaluată la expr2 dacă expr1 este nul, și la expr1 în caz
contrar. În special, acest operator nu emite o notificare sau un avertisment dacă valoarea din partea
stângă nu există, la fel ca isset(). Acest lucru este util în special în cazul cheilor de array.
Important PHP acceptă un singur operator de control al erorilor: semnul at (@).Atunci când este
atașat unei expresii în PHP, orice diagnostic de eroare care ar putea fi generat de expresia respectivă
va fi suprimat.
Important Dacă o funcție personalizată de gestionare a erorilor este setată cu set_error_handler(),
aceasta va fi apelată în continuare chiar dacă diagnosticul a fost suprimat. Orice mesaj de eroare
generat de expresie este disponibil în elementul „message” al array-ului returnat de error_get_last().
Rezultatul acestei funcții se va schimba la fiecare eroare, deci trebuie verificat din timp.
Important PHP acceptă un singur operator de execuție: ghilimelele (``). Rețineți că acestea nu sunt
ghilimele simple! PHP va încerca să execute conținutul ghilimelelor ca o comandă shell; rezultatul
va fi returnat (adică, nu va fi pur și simplu transferat la ieșire; poate fi atribuit unei variabile).
Utilizarea operatorului backtick este identică cu shell_exec().
<?php
$output = `ls -al`;
echo "<pre>$output</pre>";
?>
Example Name Result
$a and $b And true if both $a and $b are true.
$a or $b Or true if either $a or $b is true.
$a xor $b Xor true if either $a or $b is true, but not both.
! $a Not true if $a is not true.
$a && $b And true if both $a and $b are true.
$a || $b Or true if either $a or $b is true.
Important Există doi operatori de șir de caractere. Primul este operatorul de concatenare ('.'), care
returnează concatenarea argumentelor sale din dreapta și din stânga. Al doilea este operatorul de
atribuire de concatenare ('.='), care anexează argumentul din partea dreaptă la argumentul din partea
stângă. Vă rugăm să citiți Operatori de atribuire pentru mai multe informații.
<?php
$a = "Hello ";
$b = $a . "World!"; // now $b contains "Hello World!"
$a = "Hello ";
$a .= "World!"; // now $a contains "Hello World!"
?>
<?php
$a = array("a" => "apple", "b" => "banana");
$b = array("a" => "pear", "b" => "strawberry", "c" => "cherry");
Important Construcția if este una dintre cele mai importante caracteristici ale multor limbaje,
inclusiv PHP. Aceasta permite executarea condiționată a fragmentelor de cod. PHP dispune de o
structură if similară cu cea din C:
if (expr)
declarație
Important După cum s-a descris în secțiunea despre expresii, expresia este evaluată la valoarea sa
booleană. Dacă expresia este evaluată la true, PHP va executa declarația, iar dacă este evaluată la
false - o va ignora. Mai multe informații despre ce valori evaluează la fals pot fi găsite în secțiunea
„Conversia în boolean”.
Important Instrucțiunea else este executată numai dacă expresia if a fost evaluată la false, iar dacă
există expresii elseif - numai dacă și acestea au fost evaluate la false (a se vedea elseif).
Important elseif, după cum sugerează și numele său, este o combinație de if și else. La fel ca else,
extinde o instrucțiune if pentru a executa o instrucțiune diferită în cazul în care expresia if originală
este evaluată la fals. Cu toate acestea, spre deosebire de else, va executa acea expresie alternativă
numai dacă expresia condițională elseif este evaluată la true.
Important Pot exista mai multe elseif în cadrul aceleiași instrucțiuni if. Prima expresie elseif (dacă
există) care este evaluată la true ar fi executată. În PHP, este posibil să se scrie else if (în două
cuvinte) și comportamentul ar fi identic cu cel al elseif (într-un singur cuvânt). Semnificația
sintactică este ușor diferită (același comportament ca în C), dar concluzia este că ambele ar duce la
exact același comportament.
Important Instrucțiunea elseif este executată numai dacă expresia if anterioară și orice expresie
elseif anterioară au evaluat la false, iar expresia elseif curentă a evaluat la true.
<?php
if ($a > $b) {
echo "a is bigger than b";
} elseif ($a == $b) {
echo "a is equal to b";
} else {
echo "a is smaller than b";
}
?>
Important PHP oferă o sintaxă alternativă pentru unele dintre structurile sale de control; și anume,
if, while, for, foreach și switch. În fiecare caz, forma de bază a sintaxei alternative este schimbarea
parantezei de deschidere cu două puncte (:) și a parantezei de închidere cu endif;, endwhile;,
endfor;, endforeach;, sau endswitch;, respectiv.
Important Buclele while sunt cel mai simplu tip de bucle în PHP. Ele se comportă la fel ca cele din
C. Forma de bază a unei instrucțiuni while este:
while (expr)
instrucțiune
Important Semnificația unei instrucțiuni while este simplă. Aceasta îi spune PHP să execute
declarația (declarațiile) imbricate în mod repetat, atât timp cât expresia while este evaluată la true.
Valoarea expresiei este verificată de fiecare dată la începutul buclei, astfel încât, chiar dacă această
valoare se modifică în timpul executării instrucțiunii (instrucțiunilor) imbricate, execuția nu se va
opri până la sfârșitul iterației (fiecare dată când PHP execută instrucțiunile din buclă este o iterație).
Dacă expresia while este evaluată la false încă de la început, instrucțiunea (instrucțiunile) imbricate
nu vor fi executate nici măcar o dată.
<?php
$i = 1;
while ($i <= 10):
echo $i;
$i++;
endwhile;
?>
Important buclele do-while sunt foarte asemănătoare buclelor while, cu excepția faptului că
expresia adevărului este verificată la sfârșitul fiecărei iterații și nu la început. Principala diferență
față de buclele while obișnuite este că prima iterație a unei bucle do-while are execuția garantată
(expresia adevărului este verificată numai la sfârșitul iterației), în timp ce execuția unei bucle while
obișnuite nu este neapărat garantată (expresia adevărului este verificată la începutul fiecărei iterații;
dacă aceasta este evaluată la fals chiar de la început, execuția buclei se va încheia imediat).
<?php
$i = 0;
do {
echo $i;
} while ($i > 0);
?>
Important buclele for sunt cele mai complexe bucle din PHP. Ele se comportă ca omologii lor din C.
Sintaxa unei bucle for este:
<?php
$i = 1;
for (; ; ) {
if ($i > 10) {
break;
}
echo $i;
$i++;
}
?>
Important Construcția foreach oferă o modalitate ușoară de a itera peste matrici. foreach
funcționează numai pe matrici și obiecte și va produce o eroare atunci când încercați să o utilizați pe
o variabilă cu un tip de date diferit sau pe o variabilă neinițializată. Există două sintaxe:
Important Prima formă traversează iterabilul dat de iterable_expression. La fiecare iterație, valoarea
elementului curent este atribuită lui $value. A doua formă va atribui în plus cheia elementului curent
variabilei $key la fiecare iterație. Rețineți că foreach nu modifică pointerul matricei interne, care
este utilizat de funcții
<?php
$arr = array(1, 2, 3, 4);
foreach ($arr as &$value) {
$value = $value * 2;
}
// $arr is now array(2, 4, 6, 8)
unset($value); // break the reference with the last element
?>
Important break încheie execuția structurii curente for, foreach, while, do-while sau switch. break
acceptă un argument numeric opțional care îi indică numărul de structuri de închidere imbricate din
care trebuie să fie întreruptă. Valoarea implicită este 1, numai structura de închidere imediată este
întreruptă.
<?php
$arr = array('one', 'two', 'three', 'four', 'stop', 'five');
foreach ($arr as $val) {
if ($val == 'stop') {
break; /* You could also write 'break 1;' here. */
}
echo "$val<br />\n";
}
?>
Important continue este utilizat în cadrul structurilor de buclă pentru a sări peste restul iterației
buclei curente și a continua execuția la evaluarea condiției și apoi la începutul iterației următoare.
<?php
$arr = ['zero', 'one', 'two', 'three', 'four', 'five', 'six'];
foreach ($arr as $key => $value) {
if (0 === ($key % 2)) { // skip members with even key
continue;
}
echo $value . "\n";
}
?>
Important Instrucțiunea switch este similară cu o serie de instrucțiuni IF pentru aceeași expresie. În
multe cazuri, este posibil să doriți să comparați aceeași variabilă (sau expresie) cu mai multe valori
diferite și să executați o parte diferită de cod în funcție de valoarea la care este egală. Acesta este
exact scopul instrucțiunii switch.
<?php
// This switch statement:
switch ($i) {
case 0:
echo "i equals 0";
break;
case 1:
echo "i equals 1";
break;
case 2:
echo "i equals 2";
break;
}
// Is equivalent to:
if ($i == 0) {
echo "i equals 0";
} elseif ($i == 1) {
echo "i equals 1";
} elseif ($i == 2) {
echo "i equals 2";
}
?>
Important Un caz special este cazul default. Acest caz se potrivește cu orice lucru care nu a fost
potrivit în celelalte cazuri. De exemplu:
<?php
switch ($i) {
case 0:
echo "i equals 0";
break;
case 1:
echo "i equals 1";
break;
case 2:
echo "i equals 2";
break;
default:
echo "i is not equal to 0, 1 or 2";
}
?>
Important Expresia match ramifică evaluarea pe baza unei verificări a identității unei valori. La fel
ca o instrucțiune switch, o expresie match are o expresie subiect care este comparată cu mai multe
alternative. Spre deosebire de switch, aceasta va fi evaluată la o valoare, la fel ca expresiile ternare.
Spre deosebire de switch, comparația este o verificare a identității (===) mai degrabă decât o
verificare slabă a egalității (==). Expresiile Match sunt disponibile începând cu PHP 8.0.0.
<?php
$return_value = match (subject_expression) {
single_conditional_expression => return_expression,
conditional_expression1, conditional_expression2 => return_expression,
};
?>
Important Expresia match este similară cu o instrucțiune switch, dar are câteva diferențe esențiale:
• O expresie de potrivire compară valorile strict (===) în loc de liber, așa cum face
instrucțiunea switch.
• O expresie match returnează o valoare.
• brațele match nu trec la cazuri ulterioare, așa cum fac instrucțiunile switch.
• O expresie match trebuie să fie exhaustivă.
Important Ca și instrucțiunile switch, expresiile match sunt executate braț cu braț. La început, nu se
execută niciun cod. Expresiile condiționale sunt evaluate numai dacă toate expresiile condiționale
anterioare nu au reușit să corespundă expresiei subiect. Va fi evaluată numai expresia de revenire
corespunzătoare expresiei condiționale potrivite. De exemplu:
<?php
$result = match ($x) {
foo() => ...,
$this->bar() => ..., // $this->bar() isn't called if foo() === $x
$this->baz => beep(), // beep() isn't called unless $x === $this->baz
// etc.
};
?>
Important brațele expresiei de potrivire pot conține mai multe expresii separate prin virgulă. Acesta
este un OR logic și este o prescurtare pentru mai multe brațe de potrivire cu aceeași parte dreaptă.
<?php
$result = match ($x) {
// This match arm:
$a, $b, $c => 5,
// Is equivalent to these three match arms:
$a => 5,
$b => 5,
$c => 5,
};
?>
Important Un caz special este modelul implicit. Acest model se potrivește cu orice lucru care nu a
fost potrivit anterior. De exemplu:
<?php
$condition = 5;
try {
match ($condition) {
1, 2 => foo(),
3, 4 => bar(),
};
} catch (\UnhandledMatchError $e) {
var_dump($e);
}
?>
Important Construcția declare este folosită pentru a seta directive de execuție pentru un bloc de cod.
Sintaxa declare este similară cu sintaxa altor constructe de control al fluxului:
declara (directiva)
declaraţie
<?php
// This is valid:
declare(ticks=1);
// This is invalid:
const TICK_VALUE = 1;
declare(ticks=TICK_VALUE);
?>
Important Partea de instrucțiune a blocului declare va fi executată - cum este executată și ce efecte
secundare apar în timpul execuției pot depinde de directiva setată în blocul de directive.
Important Construcția declare poate fi folosită și în domeniul global, afectând tot codul care îl
urmează (cu toate acestea, dacă fișierul cu declarare a fost inclus, atunci nu afectează fișierul
părinte).
<?php
// these are the same:
Important Un tick este un eveniment care are loc pentru fiecare N instrucțiuni bifabile de nivel
scăzut executate de parser în blocul declare. Valoarea pentru N este specificată folosind ticks=N în
secțiunea de directive a blocului de declarare.
Important Nu toate afirmațiile sunt bifabile. De obicei, expresiile de condiție și expresiile de
argument nu pot fi bifate.
Important Evenimentele care apar pe fiecare bifă sunt specificate folosind funcția
register_tick_function().
Important return returnează controlul programului către modulul apelant. Execuția se reia la
expresia care urmează invocării modulului apelat.
Important Dacă este apelată dintr-o funcție, instrucțiunea return încheie imediat execuția funcției
curente și returnează argumentul acesteia ca valoare a apelului funcției. return încheie, de asemenea,
execuția unei instrucțiuni eval() sau a unui fișier script.
Important Dacă este apelat din domeniul global, atunci execuția fișierului script curent este
încheiată. Dacă fișierul script curent a fost inclus sau necesar, atunci controlul este transmis înapoi
fișierului apelant. În plus, dacă fișierul script curent a fost inclus, atunci valoarea dată pentru
returnare va fi returnată ca valoare a apelului include. Dacă return este apelat din interiorul fișierului
script principal, atunci execuția scriptului se termină. Dacă fișierul script curent a fost denumit de
opțiunile de configurare auto_prepend_file sau auto_append_file din [Link], atunci execuția acelui
fișier script este încheiată.
Important require este identic cu includerea, cu excepția cazului în care va produce, de asemenea, o
eroare fatală la nivel E_COMPILE_ERROR. Cu alte cuvinte, va opri scriptul, în timp ce include
emite doar un avertisment (E_WARNING) care permite script-ului să continue.
Important Expresia include include și evaluează fișierul specificat. Documentația de mai jos se
aplică și pentru solicitarea. Fișierele sunt incluse în funcție de calea fișierului dată sau, dacă nu este
specificată nici una, de calea_include specificată. Dacă fișierul nu este găsit în include_path, include
va verifica în sfârșit propriul director al scriptului de apelare și directorul de lucru curent înainte de
a eșua. Construcția include va emite un E_WARNING dacă nu poate găsi un fișier; acesta este un
comportament diferit de require, care va emite un E_ERROR.
Important Rețineți că ambele includ și necesită ridicarea E_WARNING-uri suplimentare, dacă
fișierul nu poate fi accesat, înainte de a genera E_WARNING sau, respectiv, E_ERROR final.
Important Dacă este definită o cale — fie absolută (începând cu o litera de unitate sau \ pe
Windows, sau / pe sisteme Unix/Linux) sau relativ la directorul curent (începând cu . sau ..) —
include_path va fi ignorată cu totul. De exemplu, dacă un nume de fișier începe cu ../, analizatorul
va căuta în directorul părinte pentru a găsi fișierul solicitat.
Important Când un fișier este inclus, codul pe care îl conține moștenește domeniul variabil al liniei
pe care are loc includerea. Orice variabilă disponibilă la acea linie din fișierul apelant va fi
disponibilă în fișierul apelat, din acel moment înainte. Cu toate acestea, toate funcțiile și clasele
definite în fișierul inclus au domeniul de aplicare global.
Important Dacă includerea are loc în interiorul unei funcții din fișierul apelant, atunci tot codul
conținut în fișierul apelat se va comporta ca și cum ar fi fost definit în interiorul acelei funcții. Deci,
va urma domeniul variabil al acelei funcții. O excepție de la această regulă sunt constantele magice
care sunt evaluate de parser înainte de includerea.
Important Dacă „URL include wrappers” este activat în PHP, puteți specifica fișierul care urmează
să fie inclus folosind o adresă URL (prin HTTP sau alt wrapper acceptat - consultați Protocoale și
Wrappers acceptate pentru o listă de protocoale) în loc de o cale locală. Dacă serverul țintă
interpretează fișierul țintă ca cod PHP, variabilele pot fi transmise fișierului inclus folosind un șir de
solicitare URL așa cum este utilizat cu HTTP GET. Acest lucru nu înseamnă, strict vorbind, același
lucru cu includerea fișierului și ca acesta să moștenească domeniul de aplicare al variabilei fișierului
părinte; scriptul este de fapt rulat pe serverul de la distanță și rezultatul este apoi inclus în scriptul
local.
<?php
$foo = include '[Link]';
echo $foo; // prints 'PHP'
$bar = include '[Link]';
echo $bar; // prints 1
?>
<?php
$string = get_include_contents('[Link]');
function get_include_contents($filename) {
if (is_file($filename)) {
ob_start();
include $filename;
return ob_get_clean();
}
return false;
}
?>
Important Expresia require_once este identică cu require, cu excepția faptului că PHP va verifica
dacă fișierul a fost deja inclus și, dacă da, nu îl va include (require) din nou.
Important Operatorul goto poate fi folosit pentru a trece la o altă secțiune a programului. Punctul
țintă este specificat printr-o etichetă sensibilă la majuscule, urmată de două puncte, iar instrucțiunea
este dată ca goto urmată de eticheta țintă dorită. Acesta nu este un acces complet nerestricționat.
Eticheta țintă trebuie să fie în același fișier și context, ceea ce înseamnă că nu puteți sări dintr-o
funcție sau metodă și nici nu puteți sări într-una. De asemenea, nu puteți sări în nici un fel de buclă
sau structură de comutare. Puteți sări din acestea, iar o utilizare obișnuită este utilizarea unui goto în
locul unei pauze pe mai multe niveluri.
<?php
goto a;
echo 'Foo';
a:
echo 'Bar';
?>
Important Orice cod PHP valid poate apărea în interiorul unei funcții, chiar și alte funcții și definiții
de clasă.
Important Numele funcțiilor urmează aceleași reguli ca și alte etichete în PHP. Un nume valid de
funcție începe cu o literă sau liniuță de subliniere, urmată de orice număr de litere, cifre sau liniuțe
de subliniere. Ca expresie regulată, ar fi exprimată astfel: ^[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\
xff]*$.
<?php
function foo($arg_1, $arg_2, /* ..., */ $arg_n)
{
echo "Example function.\n";
return $retval;
}
?>
Important Funcțiile nu trebuie definite înainte de a fi referite, cu excepția cazului în care o funcție
este definită condiționat, așa cum se arată în cele două exemple de mai jos.
Important Când o funcție este definită într-o manieră condiționată, cum ar fi cele două exemple
prezentate. Definiția sa trebuie procesată înainte de a fi apelată.
Important Toate funcțiile și clasele din PHP au sfera globală - pot fi apelate în afara unei funcții
chiar dacă au fost definite în interior și invers. PHP nu acceptă supraîncărcarea funcțiilor și nici nu
este posibilă nedefinirea sau redefinirea funcțiilor declarate anterior.
Important Parametrii funcției sunt declarați în semnătura funcției. Informațiile pot fi transmise
funcțiilor prin lista de argumente, care este o listă de expresii delimitată prin virgulă. Argumentele
sunt evaluate de la stânga la dreapta și rezultatul este atribuit parametrilor funcției, înainte ca funcția
să fie apelată efectiv (eager evaluation).
Important PHP acceptă transmiterea argumentelor după valoare (implicit), transmiterea prin
referință și valorile argumentelor implicite. Sunt acceptate și listele de argumente cu lungime
variabilă și Argumentele numite.
<?php
function takes_many_args(
$first_arg,
$second_arg,
$a_very_long_argument_name,
$arg_with_default = 5,
$again = 'a default string', // This trailing comma was not permitted before 8.0.0.
)
{
// ...
}
?>
Important În mod implicit, argumentele funcției sunt transmise după valoare (astfel încât, dacă
valoarea argumentului din cadrul funcției este modificată, aceasta nu este modificată în afara
funcției). Pentru a permite unei funcții să își modifice argumentele, acestea trebuie să fie transmise
prin referință.
Important Pentru a avea un argument pentru o funcție transmis întotdeauna prin referință, adăugați
un ampersand (&) la numele parametrului în definiția funcției:
<?php
function add_some_extra(&$string)
{
$string .= 'and something extra.';
}
$str = 'This is a string, ';
add_some_extra($str);
echo $str; // outputs 'This is a string, and something extra.'
?>
Important O funcție poate defini valori implicite pentru parametri folosind o sintaxă similară cu
alocarea unei variabile. Valoarea implicită este utilizată numai atunci când argumentul parametrului
nu este transmis. Rețineți că trecerea null nu atribuie valoarea implicită.
<?php
function makecoffee($type = "cappuccino")
{
return "Making a cup of $type.\n";
}
echo makecoffee();
echo makecoffee(null);
echo makecoffee("espresso");
?>
Important Valorile implicite ale parametrilor pot fi valori scalare, matrice, tipul special null și,
începând cu PHP 8.1.0, obiecte care utilizează noua sintaxă ClassName().
Important Valoarea implicită trebuie să fie o expresie constantă, nu (de exemplu) o variabilă, un
membru al clasei sau un apel de funcție. Rețineți că orice parametri opționali trebuie specificati
după orice parametri solicitați, altfel nu pot fi omisi din apeluri.
<?php
function makecoffee($types = array("cappuccino"), $coffeeMaker = NULL)
{
$device = is_null($coffeeMaker) ? "hands" : $coffeeMaker;
return "Making a cup of ".join(", ", $types)." with $device.\n";
}
echo makecoffee();
echo makecoffee(array("cappuccino", "lavazza"), "teapot");?>
<?php
class DefaultCoffeeMaker {
public function brew() {
return "Making coffee.\n";
}
}
class FancyCoffeeMaker {
public function brew() {
return "Crafting a beautiful coffee just for you.\n";
}
}
function makecoffee($coffeeMaker = new DefaultCoffeeMaker)
{
return $coffeeMaker->brew();
}
echo makecoffee();
echo makecoffee(new FancyCoffeeMaker);
?>
Important Începând cu PHP 8.0.0, argumentele numite pot fi folosite pentru a sări peste mai mulți
parametri opționali.
Important Începând cu PHP 8.0.0, declararea parametrilor obligatorii după parametrii opționali este
depreciată. În general, acest lucru poate fi rezolvat prin eliminarea valorii implicite, deoarece nu va
fi niciodată folosită. O excepție de la această regulă sunt parametrii de forma Type $param = null,
unde implicit nul face ca tipul să fie implicit nul. Această utilizare este depreciată începând cu PHP
8.4.0 și ar trebui folosit un tip explicit nullabil.
<?php
function foo($a = [], $b) {} // Default not used; deprecated as of PHP 8.0.0
function foo($a, $b) {} // Functionally equivalent, no deprecation notice
?>
Important PHP are suport pentru liste de argumente cu lungime variabilă în funcțiile definite de
utilizator prin utilizarea simbolului .... Listele de parametri pot include simbolul ... pentru a indica
faptul că funcția acceptă un număr variabil de argumente. Argumentele vor fi trecute în variabila
dată ca o matrice:
<?php
function sum(...$numbers) {
$acc = 0;
foreach ($numbers as $n) {
$acc += $n;
}
return $acc;
}
<?php
function add($a, $b) {
return $a + $b;
}
$a = [1, 2];
echo add(...$a);
?>
Important Puteți specifica parametrii de poziție normali înainte de simbolul.... În acest caz, numai
argumentele de sfârșit care nu se potrivesc cu un argument pozițional vor fi adăugate la tabloul
generat de .... De asemenea, este posibil să adăugați o declarație de tip înainte de simbolul .... Dacă
acesta este prezent, atunci toate argumentele capturate de... trebuie să se potrivească cu acel tip de
parametru.
Important PHP 8.0.0 a introdus argumente numite ca o extensie a parametrilor poziționali existenți.
Argumentele denumite permit transmiterea argumentelor unei funcții bazate pe numele
parametrului, mai degrabă decât pe poziția parametrului. Acest lucru face ca sensul argumentului să
se auto-documenteze, face ca argumentele să fie independente de ordine și permite sărirea în mod
arbitrar a valorilor implicite.
Important Argumentele numite sunt transmise prin prefixarea valorii cu numele parametrului urmat
de două puncte. Este permisă utilizarea cuvintelor cheie rezervate ca nume de parametri. Numele
parametrului trebuie să fie un identificator, nu este permisă specificarea dinamică.
<?php
myFunction(paramName: $value);
array_foobar(array: $value);
// NOT supported.
function_name($variableStoringParamName: $value);
?>
<?php
// Using positional arguments:
array_fill(0, 100, 50);
<?php
htmlspecialchars($string, double_encode: false);
// Same as
htmlspecialchars($string, ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401, 'UTF-8', false);
?>
Important Trecerea unui argument la același parametru numit de mai multe ori duce la o excepție
Error.
Important Începând cu PHP 8.1.0, este posibil să se utilizeze argumente numite după despachetarea
argumentelor. Un argument numit nu trebuie să suprascrie un argument deja dezambalat.
<?php
function foo($a, $b, $c = 3, $d = 4) {
return $a + $b + $c + $d;
}
var_dump(foo(...[1, 2], b: 20)); // Fatal error. Named parameter $b overwrites previous argument
?>
Important Valorile sunt returnate prin utilizarea instrucțiunii return opționale. Orice tip poate fi
returnat, inclusiv matrice și obiecte. Acest lucru face ca funcția să își încheie imediat execuția și să
treacă controlul înapoi la linia de la care a fost apelată. Consultați retur pentru mai multe informații.
Important O funcție nu poate returna mai multe valori, dar rezultate similare pot fi obținute prin
returnarea unui tablou.
Important Pentru a returna o referință dintr-o funcție, utilizați operatorul de referință & atât în
declarația funcției, cât și atunci când atribuiți valoarea returnată unei variabile:
<?php
function small_numbers()
{
return [0, 1, 2];
}
// Array destructuring will collect each member of the array individually
[$zero, $one, $two] = small_numbers();
// Prior to 7.1.0, the only equivalent alternative is using list() construct
list($zero, $one, $two) = small_numbers();
?>
<?php
function &returns_reference()
{
return $someref;
}
Important PHP suportă conceptul de funcții variabile. Aceasta înseamnă că, dacă un nume de
variabilă are paranteze atașate, PHP va căuta o funcție cu același nume ca oricare la care evaluează
variabila și va încerca să o execute. Printre altele, aceasta poate fi folosită pentru a implementa
apeluri inverse, tabele de funcții și așa mai departe.
Important Funcțiile variabile nu vor funcționa cu constructe de limbaj precum echo, print, unset(),
isset(), empty(), include, require și altele asemenea. Utilizați funcțiile wrapper pentru a utiliza
oricare dintre aceste construcții ca funcții variabile.
<?php
function foo() {
echo "In foo()<br />\n";
}
$func = 'foo';
$func(); // This calls foo()
$func = 'bar';
$func('test'); // This calls bar()
$func = 'echoit';
$func('test'); // This calls echoit()
?>
Important Funcțiile anonime, cunoscute și sub numele de închideri, permit crearea de funcții care
nu au un nume specificat. Ele sunt cele mai utile ca valoare a parametrilor apelabili, dar au multe
alte utilizări.
Important Funcțiile anonime sunt implementate folosind clasa Closure.
Important Închiderile pot fi folosite și ca valori ale variabilelor; PHP convertește automat astfel de
expresii în instanțe ale clasei interne Closure. Atribuirea unei închideri unei variabile folosește
aceeași sintaxă ca orice altă atribuire, inclusiv punctul și virgulă final:
<?php
$greet = function($name) {
printf("Hello %s\r\n", $name);
};
$greet('World');
$greet('PHP');
?>
Important Închiderile pot moșteni și variabile din domeniul părinte. Orice astfel de variabile trebuie
transmise constructului de utilizare a limbajului. Începând cu PHP 7.1, aceste variabile nu trebuie să
includă superglobale, $this sau variabile cu același nume ca parametru. O declarație de tip returnare
a funcției trebuie plasată după clauza de utilizare.
Important Începând cu PHP 8.0.0, lista de variabile moștenite de domeniul de aplicare poate include
o virgulă finală, care va fi ignorată.
Important Moștenirea variabilelor din domeniul părinte nu este același lucru cu utilizarea
variabilelor globale. Variabilele globale există în domeniul global, care este același, indiferent de
funcția care se execută. Sfera părinte a unei închideri este funcția în care a fost declarată închiderea
(nu neapărat funcția de la care a fost apelată). Vezi următorul exemplu:
<?php
// A basic shopping cart which contains a list of added products
// and the quantity of each product. Includes a method which
// calculates the total price of the items in the cart using a
// closure as a callback.
class Cart
{
const PRICE_BUTTER = 1.00;
const PRICE_MILK = 3.00;
const PRICE_EGGS = 6.95;
array_walk($this->products, $callback);
return round($total, 2);
}
}
Important Când este declarată în contextul unei clase, clasa curentă este legată automat de aceasta,
făcând $this disponibil în domeniul de aplicare al funcției. Dacă această legare automată a clasei
curente nu este dorită, atunci pot fi folosite funcții anonime statice.
Important Funcțiile anonime pot fi declarate static. Acest lucru îi împiedică să aibă clasa curentă
legată automat de ei. De asemenea, obiectele pot să nu fie legate de ele în timpul execuției.
<?php
class Foo
{
function __construct()
{
$func = static function() {
var_dump($this);
};
$func();
};
new Foo();
?>
Important Funcțiile săgeți au fost introduse în PHP 7.4 ca o sintaxă mai concisă pentru funcțiile
anonime. Atât funcțiile anonime, cât și funcțiile săgeți sunt implementate folosind clasa Closure.
Funcțiile săgeată au forma de bază fn (argument_list) => expr. Funcțiile săgeată acceptă aceleași
caracteristici ca și funcțiile anonime, cu excepția faptului că utilizarea variabilelor din domeniul
părinte este întotdeauna automată. Când o variabilă utilizată în expresie este definită în domeniul
părinte, aceasta va fi implicit capturată după valoare. În exemplul următor, funcțiile $fn1 și $fn2 se
comportă în același mod.
<?php
$y = 1;
var_export($fn1(3));
?>
Important Similar cu funcțiile anonime, sintaxa funcției săgeată permite semnături de funcții
arbitrare, inclusiv tipuri de parametri și returnări, valori implicite, variadici, precum și trecerea și
returnarea referințelor secundare. Toate următoarele sunt exemple valide de funcții săgeți:
<?php
?>
Important Funcțiile săgeată folosesc legarea variabilelor după valoare. Acest lucru este aproximativ
echivalent cu efectuarea unei utilizări ($x) pentru fiecare variabilă $x utilizată în interiorul funcției
săgeată. O legare a valorii secundare înseamnă că nu este posibil să se modifice nicio valoare din
domeniul exterior. Funcțiile anonime pot fi utilizate în schimb pentru legăturile by-ref.
<?php
$x = 1;
$fn = fn() => $x++; // Has no effect
$fn();
var_export($x); // Outputs 1
?>
Important Sintaxa apelabilă de primă clasă este introdusă începând cu PHP 8.1.0, ca o modalitate de
a crea funcții anonime din apelabile. Acesta înlocuiește sintaxa apelabilă existentă folosind șiruri de
caractere și matrice. Avantajul acestei sintaxe este că este accesibilă analizei statice și utilizează
domeniul de aplicare în punctul în care este achiziționat apelabilul.
Important Sintaxa CallableExpr(...) este folosită pentru a crea un obiect Closure din apelabil.
CallableExpr acceptă orice expresie care poate fi apelată direct în gramatica PHP:
<?php
class Foo {
public function method() {}
public static function staticmethod() {}
public function __invoke() {}
}
$f1 = strlen(...);
$f2 = $obj(...); // invokable object
$f3 = $obj->method(...);
$f4 = $obj->$methodStr(...);
$f5 = Foo::staticmethod(...);
$f6 = $classStr::$staticmethodStr(...);
<?php
class Foo {
public function getPrivateMethod() {
return [$this, 'privateMethod'];
}
class Foo1 {
public function getPrivateMethod() {
/ / Uses the scope where the callable is acquired.
return $this->privateMethod(...); // identical to Closure::fromCallable([$this,
'privateMethod']);
}
Important Crearea de obiecte prin această sintaxă (de exemplu, new Foo(...)) nu este acceptată,
deoarece noua sintaxă Foo() nu este considerată un apel.
Important Sintaxa apelabilă de primă clasă nu poate fi combinată cu operatorul nullsafe. Ambele
următoarele au ca rezultat o eroare la timp de compilare:
Important Definițiile de bază ale clasei încep cu cuvântul cheie class, urmat de un nume de clasă,
urmat de o pereche de acolade care includ definițiile proprietăților și metodelor aparținând clasei.
Important Numele clasei poate fi orice etichetă validă, cu condiția să nu fie un cuvânt rezervat PHP.
Începând cu PHP 8.4.0, utilizarea unui singur caracter de subliniere _ ca nume de clasă este
depreciată. Un nume de clasă valid începe cu o literă sau liniuță de subliniere, urmată de orice
număr de litere, cifre sau liniuțe de subliniere. Ca expresie regulată, ar fi exprimată astfel: ^[a-zA-
Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*$.
Important O clasă poate conține propriile sale constante, variabile (numite „proprietăți”) și funcții
(numite „metode”).
<?php
class SimpleClass
{
// property declaration
public $var = 'a default value';
// method declaration
public function displayVar() {
echo $this->var;
}
}
?>
Important Pseudovariabila $this este disponibilă atunci când o metodă este apelată din contextul
unui obiect. $this este valoarea obiectului apelant.
Important Începând cu PHP 8.2.0, o clasă poate fi marcată cu modificatorul numai citire. Marcarea
unei clase ca doar citire va adăuga modificatorul numai pentru citire la fiecare proprietate declarată
și va împiedica crearea de proprietăți dinamice. Mai mult, este imposibil să adăugați suport pentru
ele utilizând atributul AllowDynamicProperties. Încercarea de a face acest lucru va declanșa o
eroare de compilare.
Important Deoarece nici proprietățile netipizate și nici proprietățile statice nu pot fi marcate cu
modificatorul readonly, nici clasele readonly nu le pot declara:
<?php
#[\AllowDynamicProperties]
readonly class Foo {
}
<?php
readonly class Foo
{
public $bar;
}
<?php
readonly class Foo
{
public static int $bar;
}
Important O clasă numai în citire poate fi extinsă dacă și numai dacă clasa copil este și o clasă
numai în citire.
Important Pentru a crea o instanță a unei clase, trebuie folosit cuvântul cheie nou. Un obiect va fi
creat întotdeauna, cu excepția cazului în care obiectul are un constructor definit care aruncă o
excepție în caz de eroare. Clasele ar trebui definite înainte de instanțiere (și în unele cazuri aceasta
este o cerință).
Important Dacă o variabilă care conține un șir cu numele unei clase este folosită cu new, va fi creată
o nouă instanță a acelei clase. Dacă clasa se află într-un spațiu de nume, numele complet calificat
trebuie utilizat atunci când faceți acest lucru.
<?php
$instance = new SimpleClass();
Important Începând cu PHP 8.0.0, este acceptată utilizarea new cu expresii arbitrare. Acest lucru
permite instanțierea mai complexă dacă expresia produce un șir. Expresiile trebuie împachetate între
paranteze.
<?php
var_dump(new (getSomeClass()));
var_dump(new ('Class' . 'B'));
var_dump(new ('Class' . 'C'));
var_dump(new (ClassD::class));
?>
Important În contextul clasei, este posibil să se creeze un nou obiect de către un nou sine și un nou
părinte.
Important Când atribuiți o instanță deja creată a unei clase unei variabile noi, noua variabilă va
accesa aceeași instanță ca și obiectul care a fost atribuit. Acest comportament este același atunci
când se transmite instanțe unei funcții. O copie a unui obiect deja creat poate fi realizată prin
clonarea acestuia.
<?php
$assigned = $instance;
$reference =& $instance;
var_dump($instance);
var_dump($reference);
var_dump($assigned);
?>
Important Proprietățile și metodele clasei trăiesc în „spații de nume” separate, deci este posibil să
existe o proprietate și o metodă cu același nume. Referirea atât la o proprietate, cât și la o metodă
are aceeași notație și dacă o proprietate va fi accesată sau o metodă va fi apelată, depinde numai de
context, adică dacă utilizarea este un acces variabil sau un apel de funcție.
Important Dacă încercați să atribuiți unei proprietăți inexistente pe un obiect, PHP va crea automat
o proprietate corespunzătoare. Această proprietate creată dinamic va fi disponibilă numai pentru
această instanță de clasă. Proprietățile dinamice sunt depreciate începând cu PHP 8.2.0. Se
recomandă declararea proprietății în schimb. Pentru a gestiona nume de proprietăți arbitrare, clasa
ar trebui să implementeze metodele magice __get() și __set(). În ultimă instanță, clasa poate fi
marcată cu atributul #[\AllowDynamicProperties].
<?php
class Foo
{
public $bar = 'property';
Important Aceasta înseamnă că apelarea unei funcții anonime care a fost atribuită unei proprietăți
nu este direct posibilă. În schimb, proprietatea trebuie să fie atribuită mai întâi unei variabile, de
exemplu. Este posibil să apelați direct o astfel de proprietate prin includerea ei între paranteze.
Important O clasă poate moșteni constantele, metodele și proprietățile unei alte clase folosind
cuvântul cheie extinde în declarația clasei. Nu este posibilă extinderea mai multor clase; o clasă
poate moșteni doar de la o clasă de bază.
Important Constantele, metodele și proprietățile moștenite pot fi suprascrise prin redeclararea lor cu
același nume definit în clasa părinte. Cu toate acestea, dacă clasa părinte a definit o metodă sau
constantă ca finală, acestea nu pot fi suprascrise. Este posibil să accesați metodele suprascrise sau
proprietățile statice, referindu-le cu parent::.
<?php
class ExtendClass extends SimpleClass
{
// Redefine the parent method
function displayVar()
{
echo "Extending class\n";
parent::displayVar();
}
}
Important Când suprascrieți o metodă, semnătura acesteia trebuie să fie compatibilă cu metoda
părinte. În caz contrar, este emisă o eroare fatală sau, înainte de PHP 8.0.0, este generată o eroare la
nivel E_WARNING. O semnătură este compatibilă dacă respectă regulile de variație, face ca un
parametru obligatoriu să fie opțional, adaugă doar noi parametri opționali și nu limitează, ci doar
relaxează vizibilitatea. Acesta este cunoscut sub numele de Liskov Substitution Principle, sau LSP
pe scurt. Constructorul și metodele private sunt scutite de aceste reguli de compatibilitate cu
semnături și, prin urmare, nu vor emite o eroare fatală în cazul unei nepotriviri de semnătură.
<?php
class Base
{
public function foo(int $a) {
echo "Valid\n";
}
}
<?php
class User
{
public int $id;
public ?string $name;
public function __construct(int $id, ?string $name)
{
$this->id = $id;
$this->name = $name;
}
}
var_dump($user->id);
var_dump($user->name);
?>
<?php
class SimpleClass
{
public $var1 = 'hello ' . 'world';
public $var2 = <<<EOD
hello world
EOD;
public $var3 = 1+2;
// invalid property declarations:
public $var4 = self::myStaticMethod();
public $var5 = $myVar;
<?php
class Example
{
private bool $modified = false;
Important Proprietatea $foo se termină cu {}, nu cu punct și virgulă. Asta indică prezența cârligelor.
Sunt definite atât un cârlig get cât și set, deși este permis să se definească doar unul sau altul.
Ambele cârlige au un corp, notat cu {}, care poate conține cod arbitrar.
Important Cârligul set permite suplimentar specificarea tipului și numelui unei valori primite,
folosind aceeași sintaxă ca metodă. Tipul trebuie să fie fie același cu tipul proprietății, fie
contravariant (mai larg) cu acesta. De exemplu, o proprietate de tip șir poate avea un set hook care
acceptă șir|Stringable, dar nu unul care acceptă doar matrice.
Important Cel puțin unul dintre cârlige face referire la $this->foo, proprietatea în sine. Asta
înseamnă că proprietatea va fi „susținută”. Când apelați $example->foo = 'schimbat', șirul furnizat
va fi mai întâi transformat în litere mici, apoi salvat în valoarea de bază. Când citiți din proprietate,
valoarea salvată anterior poate fi adăugată condiționat cu text suplimentar.
Important Există și o serie de variante de sintaxă scurtă pentru a gestiona cazurile obișnuite.
Important Dacă hook-ul get este o singură expresie, atunci {} poate fi omis și înlocuit cu o expresie
săgeată.
Important Dacă tipul de parametru al cârligului setat este același cu tipul de proprietate (care este
tipic), acesta poate fi omis. În acest caz, valoarea de setată primește automat numele $value.
<?php
class Example
{
private bool $modified = false;
set {
$this->foo = strtolower($value);
$this->modified = true;
}
}
}
?>
Important Dacă cârligul setează doar o versiune modificată a valorii transmise, atunci poate fi, de
asemenea, simplificată la o expresie săgeată. Valoarea la care evaluează expresia va fi setată pe
valoarea de suport.
<?php
class Example
{
public string $foo = 'default value' {
get => $this->foo . ($this->modified ? ' (modified)' : '');
set => strtolower($value);
}
}
?>
Important Proprietățile virtuale sunt proprietăți care nu au valoare de suport. O proprietate este
virtuală dacă nici hook-ul său get, nici set nu face referire la proprietatea însăși folosind sintaxa
exactă. Adică, o proprietate numită $foo al cărei cârlig conține $this->foo va fi susținută. Dar
următoarea nu este o proprietate susținută și va returna eroarea:
<?php
class Example
{
public string $foo {
get {
$temp = __PROPERTY__;
return $this->$temp; // Doesn't refer to $this->foo, so it doesn't count.
}
}
}
?>
Important Pentru proprietățile virtuale, dacă un cârlig este omis, atunci acea operație nu există și
încercarea de a o utiliza va produce o eroare. Proprietățile virtuale nu ocupă spațiu de memorie într-
un obiect. Proprietățile virtuale sunt potrivite pentru proprietăți „derivate”, cum ar fi cele care sunt o
combinație a altor două proprietăți.
<?php
readonly class Rectangle
{
// A virtual property.
public int $area {
get => $this->h * $this->w;
}
<?php
class Person {
public string $phone {
set => $this->sanitizePhone($value);
}
if (!preg_match('/\d\d\d\-\d\d\d\-\d\d\d\d/', $value)) {
throw new \InvalidArgumentException();
}
return $value;
}
}
?>
Important Deoarece prezența cârligelor interceptează procesul de citire și scriere pentru proprietăți,
acestea cauzează probleme la achiziționarea unei referințe la o proprietate sau cu modificări
indirecte, cum ar fi $this->arrayProp['key'] = 'value';. Asta pentru că orice încercare de modificare a
valorii prin referință ar ocoli un cârlig setat, dacă este definit unul.
Important În cazul rar în care este necesară obținerea unei referințe la o proprietate care are hook-
uri definite, get hook-ul poate fi prefixat cu & pentru a-l face să revină prin referință. Definirea
ambelor get și &get pe aceeași proprietate este o eroare de sintaxă.
Important Definirea ambelor cârlige &get și set pe o proprietate susținută nu este permisă. După
cum sa menționat mai sus, scrierea la valoarea returnată prin referință ar ocoli cârligul setat. Pe
proprietățile virtuale, nu există o valoare comună necesară împărțită între cele două cârlige, așa că
este permisă definirea ambelor.
Important Scrierea într-un index al unei proprietăți de matrice implică și o referință implicită. Din
acest motiv, scrierea într-o proprietate de matrice susținută cu cârlige definite este permisă dacă și
numai dacă definește doar un cârlig &get. Pe o proprietate virtuală, scrierea în matricea returnată fie
de la get, fie de la &get este legală, dar dacă acest lucru are vreun impact asupra obiectului depinde
de implementarea hook.
Important Suprascrierea întregii proprietăți a matricei este bine și se comportă la fel ca orice altă
proprietate. Numai lucrul cu elemente ale matricei necesită îngrijire specială.
Important O proprietate poate fi, de asemenea, declarată definitivă. O proprietate finală nu poate fi
redeclarată de către o clasă de copii în niciun fel, ceea ce împiedică modificarea cârligelor sau
lărgirea accesului acesteia.
Important Declararea hook-urilor definitive pe o proprietate care este declarată definitivă este
redundantă și va fi ignorată în tăcere. Acesta este același comportament ca și metodele finale.
Important O clasă copil poate defini sau redefini cârlige individuale pe o proprietate prin redefinirea
proprietății și doar cârligele pe care dorește să le depășească. O clasă copil poate adăuga, de
asemenea, cârlige la o proprietate care nu avea niciuna. Acest lucru este în esență același ca și cum
cârligele ar fi metode.
<?php
class User
{
public string $username {
final set => strtolower($value);
}
}
Important Un hook dintr-o clasă copil poate accesa proprietatea clasei părinte folosind cuvântul
cheie parent::$prop, urmat de hook-ul dorit. De exemplu, parent::$propName::get(). Poate fi citit ca
„accesați prop definit în clasa părinte și apoi executați operația de obținere” (sau setați operația,
după caz).
Important Dacă nu este accesat în acest fel, cârligul clasei părinte este ignorat. Acest comportament
este în concordanță cu modul în care funcționează toate metodele. Aceasta oferă, de asemenea, o
modalitate de a accesa spațiul de stocare al clasei părinte, dacă există. Dacă nu există niciun cârlig
pe proprietatea părinte, va fi folosit comportamentul implicit get/set. Cârligele nu pot accesa niciun
alt cârlig, cu excepția propriului părinte pe proprietatea lor.
<?php
class Point
{
public int $x;
public int $y;
}
Important PHP are o serie de moduri diferite prin care un obiect poate fi serializat, fie pentru
consumul public, fie pentru scopuri de depanare. Comportamentul cârligelor variază în funcție de
cazul de utilizare. În unele cazuri, valoarea brută de suport a unei proprietăți va fi utilizată, ocolind
orice cârlige. În altele, proprietatea va fi citită sau scrisă „prin” cârlig, la fel ca orice altă acțiune
normală de citire/scriere.
Important Constanta specială ::class permite rezoluția complet calificată a numelor de clasă în
timpul compilării, aceasta este utilă pentru clasele cu spații de nume:
<?php
namespace foo {
class bar {
}
echo bar::class; // foo\bar
}
?>
<?php
class MyClass
{
const CONSTANT = 'constant value';
function showConstant() {
echo self::CONSTANT . "\n";
}
}
$classname = "MyClass";
echo $classname::CONSTANT . "\n";
echo $class::CONSTANT."\n";
?>
<?php
class Point {
protected int $x;
protected int $y;
Important Înainte de PHP 8.0.0, clasele din spațiul de nume global vor interpreta o metodă numită
la fel ca și clasa ca un constructor de stil vechi. Sintaxa respectivă este depreciată și va avea ca
rezultat o eroare E_DEPRECATED, dar totuși apelează acea funcție ca constructor. Dacă sunt
definite atât __construct() cât și o metodă cu același nume, __construct() va fi apelată.
Important În clasele cu spații de nume sau în orice clasă începând cu PHP 8.0.0, o metodă numită la
fel ca și clasa nu are niciodată vreo semnificație specială.
Important Utilizați întotdeauna __construct() în codul nou.
<?php
// All allowed:
static $x = new Foo;
#[AnAttribute(new Foo)]
class Test {
public function __construct(
public $prop = new Foo,) {}
}
Important PHP acceptă doar un singur constructor per clasă. În unele cazuri, totuși, poate fi de dorit
să se permită ca un obiect să fie construit în moduri diferite cu intrări diferite. Modul recomandat de
a face acest lucru este folosirea metodelor statice ca wrapper-uri de constructor.
<?php
class Product {
Important Constructorul poate fi privat sau protejat pentru a preveni apelarea externă. Dacă da, doar
o metodă statică va putea instanția clasa. Deoarece se află în aceeași definiție de clasă, au acces la
metode private, chiar dacă nu aparțin aceleiași instanțe de obiect. Constructorul privat este opțional
și poate avea sens sau nu, în funcție de cazul de utilizare.
Important Cele trei metode statice publice demonstrează apoi moduri diferite de instanțiere a
obiectului.
• fromBasicData() ia exact parametrii necesari, apoi creează obiectul apelând constructorul și
returnând rezultatul.
• fromJson() acceptă un șir JSON și efectuează o preprocesare pe el însuși pentru a-l converti
în formatul dorit de constructor. Apoi returnează noul obiect.
• fromXml() acceptă un șir XML, îl preprocesează și apoi creează un obiect gol.
Constructorul este încă apelat, dar deoarece toți parametrii sunt opționali, metoda îi omite.
Apoi atribuie valori proprietăților obiectului direct înainte de a returna rezultatul.
Important În toate cele trei cazuri, cuvântul cheie static este tradus în numele clasei în care se află
codul. În acest caz, Product.
Important PHP posedă un concept de destructor similar cu cel al altor limbaje orientate pe obiecte,
cum ar fi C++. Metoda destructorului va fi apelată de îndată ce nu există alte referințe la un anumit
obiect sau în orice ordine în timpul secvenței de oprire.
Important La fel ca constructorii, destructorii părinte nu vor fi apelați implicit de motor. Pentru a
rula un destructor părinte, ar trebui să apelați explicit parent::__destruct() în corpul destructorului.
De asemenea, ca și constructorii, o clasă copil poate moșteni destructorul părintelui dacă nu
implementează unul singur.
Important Destructorul va fi apelat chiar dacă execuția scriptului este oprită folosind exit().
Apelarea exit() într-un destructor va împiedica executarea rutinelor de închidere rămase.
Important Dacă un destructor creează noi referințe la obiectul său, nu va fi apelat a doua oară când
numărul de referințe ajunge din nou la zero sau în timpul secvenței de oprire.
Important Începând cu PHP 8.4.0, când colectarea ciclului are loc în timpul execuției unei Fibre,
destructorii de obiecte programate pentru colectare sunt executați într-o Fibră separată, numită
gc_destructor_fiber. Dacă această Fibră este suspendată, va fi creată una nouă pentru a executa orice
destructori rămași. Gc_destructor_fiber anterior nu va mai fi referit de către colectorul de gunoi și
poate fi colectat dacă nu este referit în altă parte. Obiectele al căror destructor este suspendat nu vor
fi colectate până la întoarcerea destructorului sau până la colectarea Fibrei în sine.
<?php
class MyDestructableClass
{
function __construct() {
print "In constructor\n";
}
function __destruct() {
print "Destroying " . __CLASS__ . "\n";
}
}
Important Vizibilitatea unei proprietăți, a unei metode sau (începând cu PHP 7.1.0) a unei constante
poate fi definită prin prefixarea declarației cu cuvintele cheie public, protected sau private. Membrii
clasei declarați publici pot fi accesați oriunde. Membrii declarați protejați pot fi accesați numai în
cadrul clasei în sine și prin clasele moștenitoare și părinte. Membrii declarați ca privați pot fi
accesați numai de clasa care definește membrul.
Important Proprietățile de clasă pot fi definite ca publice, private sau protejate. Proprietățile
declarate fără niciun cuvânt cheie de vizibilitate explicit sunt definite ca publice.
<?php
/**
* Define MyClass
*/
class MyClass
{
public $public = 'Public';
protected $protected = 'Protected';
private $private = 'Private';
function printHello() {
echo $this->public;
echo $this->protected;
echo $this->private;
}
}
Important Începând cu PHP 8.4, proprietățile pot avea și vizibilitatea setată asimetric, cu un
domeniu diferit de citire (get) și scriere (set). Mai exact, vizibilitatea setată poate fi specificată
separat, cu condiția să nu fie mai permisivă decât vizibilitatea implicită.
<?php
class Book
{
public function __construct(
public private(set) string $title,
public protected(set) string $author,
protected private(set) int $pubYear,
) {}
}
Important Metodele de clasă pot fi definite ca publice, private sau protejate. Metodele declarate fără
niciun cuvânt cheie explicit de vizibilitate sunt definite ca publice.
<?php
/**
* Define MyClass
*/
class MyClass
{
// Declare a public constructor
public function __construct() { }
// This is public
function Foo()
{
$this->MyPublic();
$this->MyProtected();
$this->MyPrivate();
}
}
<?php
/**
* Define MyClass
*/
class MyClass
{
// Declare a public constant
public const MY_PUBLIC = 'public';
Important Moștenirea este un principiu de programare bine stabilit, iar PHP folosește acest
principiu în modelul său obiect. Acest principiu va afecta modul în care multe clase și obiecte se
raportează între ele.
Important De exemplu, la extinderea unei clase, subclasa moștenește toate metodele, proprietățile și
constantele publice și protejate din clasa părinte. Cu excepția cazului în care o clasă înlocuiește
aceste metode, acestea își vor păstra funcționalitatea inițială.
Important Acest lucru este util pentru definirea și abstractizarea funcționalității și permite
implementarea de funcționalități suplimentare în obiecte similare fără a fi nevoie de
reimplementarea tuturor funcționalităților partajate.
Important Metodele private ale unei clase părinte nu sunt accesibile unei clase secundare. Ca
rezultat, clasele copil pot reimplementa o metodă privată, fără a ține cont de regulile normale de
moștenire. Înainte de PHP 8.0.0, totuși, restricțiile finale și statice erau aplicate metodelor private.
Începând cu PHP 8.0.0, singura restricție de metodă privată care este impusă sunt constructorii
finali privați, deoarece aceasta este o modalitate obișnuită de a „dezactiva” constructorul atunci
când se utilizează metode statice din fabrică.
Important Vizibilitatea metodelor, proprietăților și constantelor poate fi relaxată, de ex. o metodă
protejată poate fi marcată ca publică, dar nu poate fi restricționată, de ex. marcarea unei proprietăți
publice ca fiind privată. O excepție sunt constructorii, a căror vizibilitate poate fi restricționată, de
ex. un constructor public poate fi marcat ca privat într-o clasă copil.
<?php
class Foo
{
public function printItem($string)
{
echo 'Foo: ' . $string . PHP_EOL;
}
?>
<?php
class MyClass {
const CONST_VALUE = 'A constant value';
}
$classname = 'MyClass';
echo $classname::CONST_VALUE;
echo MyClass::CONST_VALUE;
?>
Important Trei cuvinte cheie speciale self, parent și static sunt folosite pentru a accesa proprietăți
sau metode din interiorul definiției clasei.
<?php
class OtherClass extends MyClass
{
public static $my_static = 'static var';
$classname = 'OtherClass';
$classname::doubleColon();
OtherClass::doubleColon();
?>
Important Când o clasă extinsă suprascrie definiția părintelui a unei metode, PHP nu va apela
metoda părintelui. Depinde de clasa extinsă dacă este apelată sau nu metoda părintelui. Acest lucru
se aplică și definițiilor metodelor Constructorilor și Destructorilor, Supraîncărcării și Magic.
<?php
class MyClass
{
protected function myFunc() {
echo "MyClass::myFunc()\n";
}
}
Important Declararea proprietăților sau metodelor clasei ca fiind statice le face accesibile fără a fi
nevoie de o instanțiere a clasei. Acestea pot fi, de asemenea, accesate static într-un obiect de clasă
instanțiat.
Important Deoarece metodele statice sunt apelabile fără o instanță a obiectului creat,
pseudovariabila $this nu este disponibilă în cadrul metodelor declarate ca statice.
<?php
class Foo {
public static function aStaticMethod() {
// ...
}
}
Foo::aStaticMethod();
$classname = 'Foo';
$classname::aStaticMethod();
?>
Important Proprietățile statice sunt accesate folosind operatorul de rezoluție scop (::) și nu pot fi
accesate prin operatorul obiect (->). Este posibil să faceți referire la clasă folosind o variabilă.
Valoarea variabilei nu poate fi un cuvânt cheie (de exemplu, sine, părinte și static).
<?php
class Foo
{
public static $my_static = 'foo';
<?php
// Common method
public function printOut()
{
print $this->getValue() . "\n";
}
}
?>
Important Interfețele obiect vă permit să creați cod care specifică ce metode și proprietăți trebuie să
implementeze o clasă, fără a fi nevoie să definiți modul în care aceste metode sau proprietăți sunt
implementate. Interfețele partajează un spațiu de nume cu clase, trăsături și enumerări, astfel încât
nu pot folosi același nume.
Important Interfețele sunt definite în același mod ca o clasă, dar cu cuvântul cheie interfață
înlocuind cuvântul cheie class și fără ca vreuna dintre metode să aibă conținutul definit.
Toate metodele declarate într-o interfață trebuie să fie publice; aceasta este natura unei interfețe.
Important În practică, interfețele servesc două scopuri complementare:
• Pentru a permite dezvoltatorilor să creeze obiecte de clase diferite care pot fi folosite
interschimbabil, deoarece implementează aceeași interfață sau interfețe. Un exemplu comun
este serviciile de acces la baze de date multiple, mai multe gateway-uri de plată sau diferite
strategii de stocare în cache. Diferite implementări pot fi schimbate fără a necesita nicio
modificare a codului care le folosește.
• Pentru a permite unei funcții sau metode să accepte și să opereze pe un parametru care se
conformează unei interfețe, fără să-i pese de ce altceva poate face obiectul sau de cum este
implementat. Aceste interfețe sunt adesea numite ca Iterable, Cacheable, Renderable sau așa
mai departe pentru a descrie semnificația comportamentului.
Important Interfețele pot defini metode magice pentru a solicita clase de implementare pentru a
implementa acele metode.
Important Pentru a implementa o interfață, se folosește operatorul de instrumente. Toate metodele
din interfață trebuie implementate în cadrul unei clase; nerespectarea acestui lucru va duce la o
eroare fatală. Clasele pot implementa mai mult de o interfață dacă se dorește, separând fiecare
interfață cu o virgulă.
Important O clasă care implementează o interfață poate folosi un nume diferit pentru parametrii săi
decât interfața. Cu toate acestea, începând cu PHP 8.0, limbajul acceptă argumente numite, ceea ce
înseamnă că apelanții se pot baza pe numele parametrului din interfață. Din acest motiv, se
recomandă insistent ca dezvoltatorii să folosească aceleași nume de parametri ca și interfața
implementată.
Important Interfețele pot fi extinse ca și clase folosind operatorul extins.
Important Clasa care implementează interfața trebuie să declare toate metodele din interfață cu o
semnătură compatibilă. O clasă poate implementa mai multe interfețe care declară o metodă cu
același nume. În acest caz, implementarea trebuie să respecte regulile de compatibilitate cu
semnături pentru toate interfețele. Deci covarianța și contravarianța pot fi aplicate.
Important Este posibil ca interfețele să aibă constante. Constantele de interfață funcționează exact
ca constantele de clasă. Înainte de PHP 8.1.0, acestea nu pot fi suprascrise de o clasă/interfață care
le moștenește. Proprietăți
Important Începând cu PHP 8.4.0, interfețele pot declara și proprietăți. Dacă o fac, declarația trebuie
să specifice dacă proprietatea trebuie să fie lizibilă, scrisă sau ambele. Declarația de interfață se
aplică numai accesului public de citire și scriere.
Important O clasă poate satisface o proprietate de interfață în mai multe moduri. Poate defini o
proprietate publică. Poate defini o proprietate virtuală publică care implementează doar cârligul
corespunzător. Sau o proprietate de citire poate fi satisfăcută de o proprietate numai de citire. Cu
toate acestea, o proprietate de interfață care poate fi setată nu poate fi doar în citire.
<?php
interface A
{
public function foo();
}
interface B
{
public function bar();
}
interface C extends A, B
{
public function baz();
}
class D implements C
{
public function foo(){}
trait TraitA {
public function sayHello() {
echo 'Hello';
}
}
trait TraitB {
public function sayWorld() {
echo 'World';
}
}
class MyHelloWorld
{
use TraitA, TraitB; // A class can use multiple traits
?>
Important Un membru moștenit dintr-o clasă de bază este suprascris de un membru inserat de o
trăsătură. Ordinea de precedență este aceea că membrii din clasa curentă suprascriu metodele Trait,
care la rândul lor suprascriu metodele moștenite.
Important O metodă moștenită dintr-o clasă de bază este suprascrisă de metoda inserată în
MyHelloWorld din trăsătura SayWorld. Comportamentul este același pentru metodele definite în
clasa MyHelloWorld. Ordinea de prioritate este aceea că metodele din clasa curentă suprascriu
metodele Trait, care la rândul lor suprascriu metodele din clasa de bază.
<?php
class Base {
public function sayHello() {
echo 'Hello ';
}
}
trait SayWorld {
public function sayHello() {
parent::sayHello();
echo 'World!';
}
}
class MyHelloWorld extends Base {
use SayWorld;
}
$o = new MyHelloWorld();
$o->sayHello();
?>
Important Mai multe trăsături pot fi inserate într-o clasă, listându-le în instrucțiunea de utilizare,
separate prin virgule.
<?php
trait Hello {
public function sayHello() {
echo 'Hello ';
}
}
trait World {
public function sayWorld() {
echo 'World';
}
}
class MyHelloWorld {
use Hello, World;
public function sayExclamationMark() {
echo '!';
}
}
$o = new MyHelloWorld();
$o->sayHello();
$o->sayWorld();
$o->sayExclamationMark();
?>
Important Dacă două Trăsături introduc o metodă cu același nume, se produce o eroare fatală, dacă
conflictul nu este rezolvat în mod explicit.
Important Pentru a rezolva conflictele de denumire între trăsăturile utilizate în aceeași clasă,
operatorul insteadof trebuie să fie folosit pentru a alege exact una dintre metodele conflictuale.
Important În acest exemplu, Talker folosește trăsăturile A și B. Deoarece A și B au metode
conflictuale, definește utilizarea variantei smallTalk din trăsătura B și varianta bigTalk din trăsătura
A.
<?php
trait A {
public function smallTalk() {
echo 'a';
}
public function bigTalk() {
echo 'A';
}
}
trait B {
public function smallTalk() {
echo 'b';
}
public function bigTalk() {
echo 'B';
}
}
class Talker {
use A, B {
B::smallTalk insteadof A;
A::bigTalk insteadof B;
}
}
class Aliased_Talker {
use A, B {
B::smallTalk insteadof A;
A::bigTalk insteadof B;
B::bigTalk as talk;
}
}
?>
Important Așa cum clasele pot folosi trăsături, la fel pot face și alte trăsături. Folosind una sau mai
multe trăsături într-o definiție de trăsătură, aceasta poate fi compusă parțial sau în întregime din
membrii definiți în acele alte trăsături.
<?php
trait Hello {
public function sayHello() {
echo 'Hello ';
}
}
trait World {
public function sayWorld() {
echo 'World!';
}
}
trait HelloWorld {
use Hello, World;
}
class MyHelloWorld {
use HelloWorld;
}
$o = new MyHelloWorld();
$o->sayHello();
$o->sayWorld();
?>
Important Trăsăturile sprijină utilizarea metodelor abstracte pentru a impune cerințe clasei
expozante. Sunt acceptate metode publice, protejate și private. Înainte de PHP 8.0.0, erau acceptate
numai metode abstracte publice și protejate.
<?php
trait Hello {
public function sayHelloWorld() {
echo 'Hello'.$this->getWorld();
}
abstract public function getWorld();
}
class MyHelloWorld {
private $world;
use Hello;
public function getWorld() {
return $this->world;
}
public function setWorld($val) {
$this->world = $val;
}
}
?>
Important Trăsăturile pot defini variabile statice, metode statice și proprietăți statice.
<?php
trait Counter
{
public function inc()
{
static $c = 0;
$c = $c + 1;
echo "$c\n";
}
}
class C1
{
use Counter;
}
class C2
{
use Counter;
}
$o = new C1();
$o->inc();
$p = new C2();
$p->inc();
?>
<?php
trait PropertiesTrait
{
public $x = 1;
}
class PropertiesExample
{
use PropertiesTrait;
}
?>
Important Dacă o trăsătură definește o proprietate, atunci o clasă nu poate defini o proprietate cu
același nume decât dacă aceasta este compatibilă (aceeași vizibilitate și tip, modificator numai
pentru citire și valoare inițială), în caz contrar, este emisă o eroare fatală.
<?php
trait PropertiesTrait {
public $same = true;
public $different1 = false;
public bool $different2;
public bool $different3;
}
class PropertiesExample {
use PropertiesTrait;
public $same = true;
public $different1 = true; // Fatal error
public string $different2; // Fatal error
readonly protected bool $different3; // Fatal error
}
?>
Important Începând cu PHP 8.2.0, trăsăturile pot defini și constante.
<?php
trait ConstantsTrait {
public const FLAG_MUTABLE = 1;
final public const FLAG_IMMUTABLE = 5;
}
class ConstantsExample {
use ConstantsTrait;
}
Important Dacă o trăsătură definește o constantă, atunci o clasă nu poate defini o constantă cu
același nume decât dacă este compatibilă (aceeași vizibilitate, valoare inițială și finalitate), în caz
contrar este emisă o eroare fatală.
<?php
trait ConstantsTrait {
public const FLAG_MUTABLE = 1;
final public const FLAG_IMMUTABLE = 5;
}
class ConstantsExample {
use ConstantsTrait;
public const FLAG_IMMUTABLE = 5; // Fatal error
}
?>
Important Începând cu PHP 8.3.0, modificatorul final poate fi aplicat folosind operatorul as pentru
metodele importate din trăsături. Acest lucru poate fi folosit pentru a preveni ca clasele copil să
suprascrie metodei. Cu toate acestea, clasa care folosește trăsătura poate încă suprascrie metoda.
<?php
trait CommonTrait
{
public function method()
{
echo 'Hello';
}
}
class FinalExampleA
{
use CommonTrait {
CommonTrait::method as final; // The 'final' prevents child classes from overriding
the method
}
}
class FinalExampleB extends FinalExampleA
{public function method() {}}
?>
Important Clasele anonime sunt utile atunci când trebuie create obiecte simple, unice.
<?php
$util->setLogger(new Logger());
Important Ei pot transmite argumente către constructorii lor, pot extinde alte clase, pot implementa
interfețe și pot folosi trăsături la fel ca o clasă normală:
<?php
class SomeClass {}
interface SomeInterface {}
trait SomeTrait {}
use SomeTrait;
});
Important Imbricarea unei clase anonime într-o altă clasă nu îi oferă acces la nicio metodă sau
proprietăți private sau protejate ale acelei clase exterioare. Pentru a utiliza proprietățile sau
metodele protejate ale clasei exterioare, clasa anonimă poate extinde clasa exterioară. Pentru a
utiliza proprietățile private ale clasei exterioare în clasa anonimă, acestea trebuie să fie trecute prin
constructorul său:
<?php
class Outer
{
private $prop = 1;
protected $prop2 = 2;
Important Începând cu PHP 8.3.0, modificatorul numai citire poate fi aplicat claselor anonime.
<?php
__set() este rulat atunci când scrieți date pe proprietăți inaccesibile (protejate sau private) sau
inexistente.
__get() este utilizat pentru citirea datelor din proprietăți inaccesibile (protejate sau private) sau
inexistente.
__isset() este declanșat prin apelarea isset() sau empty() pe proprietăți inaccesibile (protejate sau
private) sau inexistente.
__unset() este invocat atunci când unset() este folosit pe proprietăți inaccesibile (protejate sau
private) sau inexistente.
<?php
class PropertyTest
{
/** Location for overloaded data. */
private $data = array();
/** Overloading only used on this when accessed outside the class. */
private $hidden = 2;
$trace = debug_backtrace();
trigger_error(
'Undefined property via __get(): ' . $name .
' in ' . $trace[0]['file'] .
' on line ' . $trace[0]['line'],
E_USER_NOTICE);
return null;
}
echo "<pre>\n";
$obj->a = 1;
echo $obj->a . "\n\n";
var_dump(isset($obj->a));
unset($obj->a);
var_dump(isset($obj->a));
echo "\n";
<?php
class MethodTest
{
public function __call($name, $arguments)
{
// Note: value of $name is case sensitive.
echo "Calling object method '$name' ". implode(', ', $arguments). "\n";
}
Important PHP oferă o modalitate prin care obiectele să fie definite, astfel încât să fie posibilă
iterarea printr-o listă de elemente, cu, de exemplu, o instrucțiune foreach. În mod implicit, toate
proprietățile vizibile vor fi utilizate pentru iterație.
<?php
class MyClass
{
public $var1 = 'value 1';
public $var2 = 'value 2';
public $var3 = 'value 3';
function iterateVisible() {
echo "MyClass::iterateVisible:\n";
foreach ($this as $key => $value) {
print "$key => $value\n";
}
}
}
Important Magic methods are special methods which override PHP's default's action when certain
actions are performed on an object.
Important Următoarele nume de metode sunt considerate magice: __construct(), __destruct(),
__call(), __callStatic(), __get(), __set(), __isset(), __unset(), __sleep(), __wakeup(), __serialize( ),
__unserialize(), __toString(), __invoke(), __set_state(), __clone() și __debugInfo().
Important serialize() verifică dacă clasa are o funcție cu numele magic __sleep(). Dacă da, acea
funcție este executată înainte de orice serializare. Poate curăța obiectul și ar trebui să returneze o
matrice cu numele tuturor variabilelor acelui obiect care ar trebui serializate. Dacă metoda nu
returnează nimic, atunci null este serializat și E_NOTICE este emis.
Important Utilizarea intenționată a __sleep() este să comite date în așteptare sau să efectueze sarcini
de curățare similare. De asemenea, funcția este utilă dacă un obiect foarte mare nu trebuie să fie
salvat complet.
Important În schimb, unserialize() verifică prezența unei funcții cu numele magic __wakeup(). Dacă
este prezentă, această funcție poate reconstrui orice resurse pe care le poate avea obiectul.
Important Utilizarea intenționată a __wakeup() este de a restabili orice conexiuni de bază de date
care s-ar fi putut pierde în timpul serializării și de a efectua alte sarcini de reinițializare.
<?php
class Connection
{
protected $link;
private $dsn, $username, $password;
Important serialize() verifică dacă clasa are o funcție cu numele magic __serialize(). Dacă da, acea
funcție este executată înainte de orice serializare. Trebuie să construiască și să returneze o matrice
asociativă de perechi cheie/valoare care reprezintă forma serializată a obiectului. Dacă nu se
returnează nicio matrice, va fi aruncată o TypeError.
Important Utilizarea intenționată a lui __serialize() este de a defini o reprezentare arbitrară
prietenoasă cu serializarea a obiectului. Elementele matricei pot corespunde proprietăților
obiectului, dar acest lucru nu este necesar.
Important În schimb, unserialize() verifică prezența unei funcții cu numele magic __unserialize().
Dacă este prezentă, acestei funcții i se va trece matricea restaurată care a fost returnată de la
__serialize(). Apoi, poate restabili proprietățile obiectului din acea matrice, după caz.
Important Dacă atât __unserialize() cât și __wakeup() sunt definite în același obiect, va fi apelat
doar __unserialize(). __wakeup() va fi ignorat.
<?php
class Connection
{
protected $link;
private $dsn, $username, $password;
<?php
// Declare a simple class
class TestClass
{
public $foo;
<?php
class CallableClass
{
public function __invoke($x)
{
var_dump($x);
}
}
$obj = new CallableClass;
$obj(5);
var_dump(is_callable($obj));
?>
<?php
class A
{
public $var1;
public $var2;
$a = new A;
$a->var1 = 5;
$a->var2 = 'foo';
$b = var_export($a, true);
var_dump($b);
eval('$c = ' . $b . ';');
var_dump($c);
?>
__debugInfo(): array
Această metodă este apelată de var_dump() atunci când aruncați un obiect pentru a obține
proprietățile care ar trebui să fie afișate. Dacă metoda nu este definită pe un obiect, atunci toate
proprietățile publice, protejate și private vor fi afișate.
<?php
class C {
private $prop;
var_dump(new C(42));
?>
Important Cuvântul cheie final împiedică clasele copil să suprascrie o metodă, o proprietate sau o
constantă prin prefixarea definiției cu final. Dacă clasa în sine este definită finală, atunci nu poate fi
extinsă.
<?php
class BaseClass {
public function test() {
echo "BaseClass::test() called\n";
}
Important O copie a obiectului este creată utilizând cuvântul cheie clone (care apelează metoda
__clone() a obiectului, dacă este posibil).
$copie_obiect = clona $obiect;
Important Când un obiect este clonat, PHP va efectua o copie superficială a tuturor proprietăților
obiectului. Orice proprietăți care sunt referințe la alte variabile vor rămâne referințe. __clone(): nul
Important Odată ce clonarea este completă, dacă este definită o metodă __clone(), atunci metoda
__clone() a obiectului nou creat va fi apelată, pentru a permite orice proprietăți necesare care
trebuie modificate.
<?php
class SubObject
{
static $instances = 0;
public $instance;
class MyCloneable
{
public $object1;
public $object2;
function __clone()
{
// Force a copy of this->object, otherwise
// it will point to same object.
$this->object1 = clone $this->object1;
}
}
?>
Este posibil să accesați un membru al unui obiect proaspăt clonat într-o singură expresie:
<?php
$dateTime = new DateTime();
echo (clone $dateTime)->format('Y');
?>
Important Când se utilizează operatorul de comparare (==), variabilele obiect sunt comparate într-
un mod simplu, și anume: Două instanțe de obiect sunt egale dacă au aceleași atribute și valori
(valorile sunt comparate cu ==) și sunt instanțe ale aceleiași clase .
Important Când se utilizează operatorul de identitate (===), variabilele obiect sunt identice dacă și
numai dacă se referă la aceeași instanță a aceleiași clase.
<?php
function bool2str($bool)
{
if ($bool === false) {
return 'FALSE';
} else {
return 'TRUE';
}
}
class Flag
{
public $flag;
class OtherFlag
{
public $flag;
$o = new Flag();
$p = new Flag();
$q = $o;
$r = new OtherFlag();
Important PHP implementează o caracteristică numită legături statice tardive care poate fi folosită
pentru a face referire la clasa apelată într-un context de moștenire statică.
Important Mai precis, legăturile statice tardive funcționează prin stocarea clasei numite în ultimul
„apel fără redirecționare”. În cazul apelurilor de metode statice, aceasta este clasa denumită în mod
explicit (de obicei cea din stânga operatorului ::); în cazul apelurilor de metode non-statice, aceasta
este clasa obiectului. Un „apel de redirecționare” este unul static care este introdus de self::,
parent::, static:: sau, dacă urcă în ierarhia clasei, forward_static_call(). Funcția get_called_class()
poate fi folosită pentru a prelua un șir cu numele clasei apelate și static:: introduce domeniul său de
aplicare.
Important Această caracteristică a fost numită „legături statice tardive” având în vedere o
perspectivă internă. „Legarea tardivă” provine din faptul că static:: nu va fi rezolvată folosind clasa
în care este definită metoda, ci mai degrabă va fi calculată folosind informațiile de rulare. A fost
numită și „legare statică”, deoarece poate fi folosită pentru (dar nu se limitează la) apeluri de
metode statice.
Important Referințele statice la clasa curentă, cum ar fi self:: sau __CLASS__, sunt rezolvate
folosind clasa căreia îi aparține funcția, așa cum a fost definită:
<?php
class A {
public static function who() {
echo __CLASS__;
}
public static function test() {
self::who();
}
}
class B extends A {
public static function who() {
echo __CLASS__;
}
}
B::test();
?>
Important Legăturile statice tardive încearcă să rezolve această limitare prin introducerea unui
cuvânt cheie care face referire la clasa care a fost inițial apelată în timpul execuției. Practic, un
cuvânt cheie care ar permite referirea B din test() în exemplul anterior. S-a decis să nu se introducă
un cuvânt cheie nou, ci mai degrabă să se folosească static care era deja rezervat.
<?php
class A {
public static function who() {
echo __CLASS__;
}
public static function test() {
static::who(); // Here comes Late Static Bindings
}
}
class B extends A {
public static function who() {
echo __CLASS__;
}
}
B::test();
?>
Important În contexte non-statice, clasa apelată va fi clasa instanței obiectului. Deoarece $this-> va
încerca să apeleze metode private din același domeniu, utilizarea static:: poate da rezultate diferite.
O altă diferență este că static:: se poate referi doar la proprietăți statice.
<?php
class A {
private function foo() {
echo "success!\n";
}
public function test() {
$this->foo();
static::foo();
}
}
class B extends A {
/* foo() will be copied to B, hence its scope will still be A and
* the call be successful */
}
class C extends A {
private function foo() {
/* original method is replaced; the scope of the new one is C */
}
}
$b = new B();
$b->test();
$c = new C();
$c->test(); //fails
?>
Important Unul dintre punctele cheie ale PHP OOP care este adesea menționat este că „obiectele
sunt transmise prin referințe în mod implicit”. Acest lucru nu este complet adevărat. Această
secțiune rectifică această gândire generală folosind câteva exemple.
Important O referință PHP este un alias, care permite a două variabile diferite să scrie la aceeași
valoare. În PHP, o variabilă obiect nu conține obiectul în sine ca valoare. Conține doar un
identificator de obiect care permite accesoriilor obiectului să găsească obiectul real. Când un obiect
este trimis prin argument, returnat sau atribuit unei alte variabile, diferitele variabile nu sunt alias-
uri: ele dețin o copie a identificatorului, care indică același obiect.
<?php
class A {public $foo = 1;}
$a = new A;
$b = $a; // $a and $b are copies of the same identifier
// ($a) = ($b) = <id>
$b->foo = 2;
echo $a->foo."\n";
$c = new A;
$d = &$c; // $c and $d are references
// ($c,$d) = <id>
$d->foo = 2;
echo $c->foo."\n";
$e = new A;
function foo($obj) {
// ($obj) = ($e) = <id>
$obj->foo = 2;
}
foo($e);
echo $e->foo."\n";
?>
Important serialize() returnează un șir care conține o reprezentare în flux de octeți a oricărei valori
care poate fi stocată în PHP. unserialize() poate folosi acest șir pentru a recrea valorile variabilelor
originale. Utilizarea serializei pentru a salva un obiect va salva toate variabilele dintr-un obiect.
Metodele dintr-un obiect nu vor fi salvate, ci doar numele clasei.
Important Pentru a putea deserializa() un obiect, trebuie definită clasa acelui obiect. Adică, dacă
aveți un obiect din clasa A și îl serializați, veți obține un șir care se referă la clasa A și conține toate
valorile variabilelor conținute în acesta. Dacă doriți să puteți deserializa acest lucru într-un alt fișier,
un obiect din clasa A, definiția clasei A trebuie să fie mai întâi prezentă în acel fișier. Acest lucru se
poate face, de exemplu, prin stocarea definiției de clasă a clasei A într-un fișier include și includerea
acestui fișier sau folosind funcția spl_autoload_register().
Important Se recomandă insistent ca, dacă o aplicație serializează obiecte, pentru a fi utilizate
ulterior în aplicație, aplicația să includă definiția clasei pentru acel obiect în întreaga aplicație. Dacă
nu faceți acest lucru, un obiect poate fi deserializat fără o definiție de clasă, ceea ce va avea ca
rezultat PHP să dea obiectului o clasă de __PHP_Incomplete_Class_Name, care nu are metode și ar
face obiectul inutil.
Important Deci, dacă în exemplul de mai sus $a a devenit parte a unei sesiuni prin adăugarea unei
noi chei la matricea superglobală $_SESSION, ar trebui să includeți fișierul [Link] pe toate paginile
dvs., nu numai [Link] și [Link].
Important Covarianța permite metodei unui copil să returneze un tip mai specific decât tipul de
returnare al metodei părintelui său. Contravarianța permite unui tip de parametru să fie mai puțin
specific într-o metodă copil decât cea a părintelui său.
Important O declarație de tip este considerată mai specifică în următorul caz:
• Un tip este eliminat dintr-un tip de uniune
• Un tip este adăugat unui tip de intersecție
• Un tip de clasă este schimbat într-un tip de clasă copil
• iterable este schimbat în array sau Traversable
<?php
class Animal {}
class Dog extends Animal {}
class Poodle extends Dog {}
interface PetOwner
{
// Only a get operation is required, so this may be covariant.
public Animal $pet { get; }
}
Important Un obiect leneș este un obiect a cărui inițializare este amânată până când starea sa este
observată sau modificată. Unele exemple de cazuri de utilizare includ componente de injecție de
dependență care oferă servicii lene inițializate complet numai dacă este necesar, ORM-uri care oferă
entități leneșe care se hidratează din baza de date numai atunci când sunt accesate sau un parser
JSON care întârzie analizarea până când elementele sunt accesate.
Important Sunt acceptate două strategii de obiecte leneșe: obiecte fantomă și proxy virtuale,
denumite în continuare „fantome leneșe” și „proxy leneși”. În ambele strategii, obiectul leneș este
atașat unui inițializator sau fabrică care este apelat automat atunci când starea sa este observată sau
modificată pentru prima dată. Din punct de vedere al abstractizării, obiectele fantomă leneșe nu se
pot distinge de cele neleneșe: pot fi folosite fără să știe că sunt leneși, permițându-le să fie transmise
și folosite de un cod care nu este conștient de lene. Proxy-urile lazy sunt la fel de transparente, dar
trebuie avut grijă când se utilizează identitatea lor, deoarece proxy-ul și instanța sa reală au
identități diferite.
Important Este posibil să creați o instanță leneșă a oricărei clase definite de utilizator sau a clasei
stdClass (alte clase interne nu sunt acceptate) sau să resetați o instanță a acestor clase pentru a o
face leneșă. Punctele de intrare pentru crearea unui obiect leneș sunt metodele
ReflectionClass::newLazyGhost() și ReflectionClass::newLazyProxy().
Important Ambele metode acceptă o funcție care este apelată atunci când obiectul necesită
inițializare. Comportamentul așteptat al funcției variază în funcție de strategia utilizată, așa cum
este descris în documentația de referință pentru fiecare metodă.
<?php
class Example
{
public function __construct(public int $prop)
{
echo __METHOD__, "\n";
}
}
var_dump($lazyObject);
var_dump(get_class($lazyObject));
// Triggers initialization
var_dump($lazyObject->prop);
?>
Important Fantomele leneșe sunt obiecte care se inițializează în loc și, odată inițializate, nu se pot
distinge de un obiect care nu a fost niciodată leneș. Această strategie este potrivită atunci când
controlăm atât instanțiarea, cât și inițializarea obiectului, făcându-l nepotrivit dacă oricare dintre
acestea este gestionat de o altă parte.
Important Proxy-urile lazy, odată inițializate, acționează ca proxy pentru o instanță reală: orice
operație pe un proxy leneș inițializat este redirecționată către instanța reală. Crearea instanței reale
poate fi delegată unei alte părți, făcând această strategie utilă în cazurile în care fantomele leneșe
sunt nepotrivite. Deși proxy-urile leneșe sunt aproape la fel de transparente ca fantomele leneșe,
este necesară prudență atunci când se utilizează identitatea lor, deoarece proxy-ul și instanța sa reală
au identități distincte.
Important Obiectele lazy sunt concepute pentru a fi complet transparente pentru consumatorii lor,
astfel încât operațiunile normale care observă sau modifică starea obiectului vor declanșa automat
inițializarea înainte de efectuarea operației. Aceasta include, dar nu se limitează la, următoarele
operațiuni:
• Citirea sau scrierea unei proprietăți.
• Testarea dacă o proprietate este setată sau dezactivată.
• Accesarea sau modificarea unei proprietăți prin ReflectionProperty::getValue(),
ReflectionProperty::getRawValue(), ReflectionProperty::setValue() sau
ReflectionProperty::setRawValue().
• Listarea proprietăților cu ReflectionObject::getProperties(), ReflectionObject::getProperty(),
get_object_vars().
• Iterarea asupra proprietăților unui obiect care nu implementează Iterator sau
IteratorAggregate folosind foreach.
• Serializarea obiectului cu serialize(), json_encode(), etc.
• Clonarea obiectului.
Important Apelurile de metodă care nu accesează starea obiectului nu vor declanșa inițializarea. În
mod similar, interacțiunile cu obiectul care invocă metode magice sau funcții hook nu vor declanșa
inițializarea dacă aceste metode sau funcții nu accesează starea obiectului.
Important Următoarele metode specifice sau operațiuni de nivel scăzut permit accesul sau
modificarea obiectelor leneșe fără a declanșa inițializarea:
• Marcarea proprietăților ca non-lene cu ReflectionProperty::skipLazyInitialization() sau
ReflectionProperty::setRawValueWithoutLazyInitialization().
• Preluarea reprezentării interne a proprietăților folosind get_mangled_object_vars() sau prin
turnarea obiectului într-o matrice.
• Utilizarea serialize() când ReflectionClass::SKIP_INITIALIZATION_ON_SERIALIZE este
setat, cu excepția cazului în care __serialize() sau __sleep() declanșează inițializarea.
• Apelarea la ReflectionObject::__toString().
• Folosind var_dump() sau debug_zval_dump(), cu excepția cazului în care __debugInfo()
declanșează inițializarea.
Important Clonarea unui obiect leneș declanșează inițializarea acestuia înainte ca clona să fie creată,
rezultând un obiect inițializat.
Important Pentru obiectele proxy, atât proxy-ul, cât și instanța sa reală sunt clonate, iar clona proxy-
ului este returnată. Metoda __clone este apelată pe instanța reală, nu pe proxy. Proxy-ul clonat și
instanța reală sunt legate așa cum sunt în timpul inițializării, astfel încât accesele la clona proxy sunt
redirecționate către clona instanței reale.
Important Acest comportament asigură că clona și obiectul original mențin stări separate.
Modificările aduse obiectului original sau stării inițializatorului său după clonare nu afectează
clona. Clonarea atât a proxy-ului, cât și a instanței sale reale, în loc să returneze o clonă a instanței
reale, asigură că operația de clonare returnează în mod constant un obiect din aceeași clasă.
Important Pentru fantomele leneșe, destructorul este apelat doar dacă obiectul a fost inițializat.
Pentru proxy, destructorul este apelat doar în instanța reală, dacă există unul.
Important Metodele ReflectionClass::resetAsLazyGhost() și ReflectionClass::resetAsLazyProxy()
pot invoca destructorul obiectului resetat.
28. Namespace
Important Ce sunt spațiile de nume? În cea mai largă definiție, spațiile de nume sunt o modalitate de
încapsulare a elementelor. Acesta poate fi văzut ca un concept abstract în multe locuri. De exemplu,
în orice sistem de operare, directoarele servesc la gruparea fișierelor asociate și acționează ca un
spațiu de nume pentru fișierele din ele. Ca exemplu concret, fișierul [Link] poate exista atât în
directorul /home/greg, cât și în /home/other, dar două copii ale [Link] nu pot coexista în același
director. În plus, pentru a accesa fișierul [Link] în afara directorului /home/greg, trebuie să
introducem numele directorului înaintea numelui fișierului folosind separatorul de director pentru a
obține /home/greg/[Link]. Același principiu se extinde la spațiile de nume din lumea programării.
Important În lumea PHP, spațiile de nume sunt concepute pentru a rezolva două probleme pe care
autorii de biblioteci și aplicații le întâmpină atunci când creează elemente de cod reutilizabile, cum
ar fi clase sau funcții:
• Ciocnirile de nume dintre codul pe care îl creați și clasele/funcțiile/constantele PHP interne
sau clasele/funcțiile/constantele terțe.
• Abilitatea de a alias (sau de a scurta) Extra_Long_Names conceput pentru a atenua prima
problemă, îmbunătățind lizibilitatea codului sursă.
<?php
namespace my\name; // see "Defining Namespaces" section
class MyClass {}
function myfunction() {}
const MYCONST = 1;
$a = new MyClass;
$c = new \my\name\MyClass; // see "Global Space" section
Important Deși orice cod PHP valid poate fi conținut într-un spațiu de nume, numai următoarele
tipuri de cod sunt afectate de spații de nume: clase (inclusiv rezumate și trăsături), interfețe, funcții
și constante.
Important Spațiile de nume sunt declarate folosind cuvântul cheie namespace. Un fișier care conține
un spațiu de nume trebuie să declare spațiul de nume din partea de sus a fișierului înainte de orice
alt cod - cu o excepție: cuvântul cheie declare.
<?php
namespace MyProject;
const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */ }
?>
Important Singura construcție de cod permisă înaintea unei declarații de spațiu de nume este
instrucțiunea declare, pentru definirea codificării unui fișier sursă. În plus, nici un cod non-PHP nu
poate precede o declarație de spațiu de nume, inclusiv spații albe suplimentare:
<?php
namespace MyProject; // fatal error - namespace must be the first statement in the script
?>
Important La fel ca directoarele și fișierele, spațiile de nume PHP conțin și capacitatea de a
specifica o ierarhie de nume de spații de nume. Astfel, un nume de spațiu de nume poate fi definit
cu sub-niveluri:
<?php
namespace MyProject\Sub\Level;
const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */ }
?>
Important Mai multe spații de nume pot fi, de asemenea, declarate în același fișier. Există două
sintaxe permise.
<?php
namespace MyProject;
const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */ }
namespace AnotherProject;
const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */ }
?>
Important Această sintaxă nu este recomandată pentru combinarea spațiilor de nume într-un singur
fișier. În schimb, este recomandat să utilizați sintaxa alternativă între paranteze.
<?php
namespace MyProject {
const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */ }
}
namespace AnotherProject {
const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */ }}?>
Important Pentru a combina codul global fără spații de nume cu codul cu spații de nume, este
acceptată numai sintaxa între paranteze. Codul global ar trebui să fie inclus într-o instrucțiune de
spațiu de nume fără nume de spațiu de nume, ca în:
<?php
namespace MyProject {
const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */ }
}
Important Niciun cod PHP nu poate exista în afara parantezelor spațiului de nume, cu excepția unei
declarații de deschidere.
<?php
declare(encoding='UTF-8');
namespace MyProject {
const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */ }
}
Important Înainte de a discuta despre utilizarea spațiilor de nume, este important să înțelegeți cum
PHP știe ce element cu spații de nume solicită codul dvs. Se poate face o analogie simplă între
spațiile de nume PHP și un sistem de fișiere. Există trei moduri de a accesa un fișier într-un sistem
de fișiere:
• Nume relativ al fișierului, cum ar fi [Link]. Acest lucru se rezolvă la currentdirectory/[Link]
unde currentdirectory este directorul ocupat în prezent. Deci, dacă directorul curent este
/home/foo, numele se rezolvă în /home/foo/[Link].
• Nume relativ de cale, cum ar fi subdirector/[Link]. Acest lucru se rezolvă la
actualdirectory/subdirectory/[Link].
• Nume absolut de cale, cum ar fi /main/[Link]. Aceasta se rezolvă în /main/[Link].
Important Același principiu poate fi aplicat elementelor cu spații de nume în PHP. De exemplu, un
nume de clasă poate fi referit în trei moduri:
• Nume necalificat, sau un nume de clasă fără prefix, cum ar fi $a = new foo(); sau
foo::staticmethod();. Dacă spațiul de nume curent este spațiul de nume curent, acesta se
rezolvă la spațiul de nume curent\foo. Dacă codul este cod global, fără spații de nume,
acesta se rezolvă în foo. O avertizare: numele necalificate pentru funcții și constante se vor
rezolva în funcții și constante globale dacă funcția sau constanta cu spațiu de nume nu este
definită. Consultați Utilizarea spațiilor de nume: alternativă la funcția/constantele globale
pentru detalii.
• Nume calificat, sau un nume de clasă prefixat, cum ar fi $a = new subnamespace\foo(); sau
subnamespace\foo::staticmethod();. Dacă spațiul de nume curent este spațiu de nume curent,
acesta se rezolvă la spațiu de nume curent\subnamespace\foo. Dacă codul este cod global,
fără spații de nume, acesta se rezolvă în subnamespace\foo.
• Nume complet calificat, sau un nume prefixat cu operator de prefix global, cum ar fi $a =
new \currentnamespace\foo(); sau \currentnamespace\foo::staticmethod();. Aceasta se
rezolvă întotdeauna la numele literal specificat în cod, currentnamespace\foo.
<?php
namespace Foo\Bar\subnamespace;
const FOO = 1;
function foo() {}
class foo
{
static function staticmethod() {}
}
?>
Important Implementarea de către PHP a spațiilor de nume este influențată de natura sa dinamică ca
limbaj de programare. Astfel, pentru a converti codul ca exemplul următor în cod spațial de nume:
<?php
class classname
{
function __construct()
{
echo __METHOD__,"\n";
}
}
function funcname()
{
echo __FUNCTION__,"\n";
}
const constname = "global";
$a = 'classname';
$obj = new $a; // prints classname::__construct
$b = 'funcname';
$b(); // prints funcname
echo constant('constname'), "\n"; // prints global
?>
Important Trebuie să utilizați numele complet calificat (nume de clasă cu prefix de spațiu de nume).
Rețineți că, deoarece nu există nicio diferență între un nume calificat și unul complet calificat în
interiorul unui nume de clasă dinamică, un nume de funcție sau un nume constant, bara oblică
inversă nu este necesară.
<?php
namespace namespacename;
class classname
{
function __construct()
{
echo __METHOD__,"\n";
}
}
function funcname()
{
echo __FUNCTION__,"\n";
}
const constname = "namespaced";
Important PHP acceptă două moduri de accesare abstractă a elementelor din spațiul de nume curent,
constanta magică __NAMESPACE__ și cuvântul cheie pentru spațiul de nume. Valoarea lui
__NAMESPACE__ este un șir care conține numele actual al spațiului de nume. În codul global, fără
spații de nume, acesta conține un șir gol.
<?php
namespace MyProject;
<?php
function get($classname)
{
$a = __NAMESPACE__ . '\\' . $classname;
return new $a;
}
?>
Important Cuvântul cheie namespace poate fi folosit pentru a solicita în mod explicit un element din
spațiul de nume curent sau dintr-un sub-spațiu de nume. Este echivalentul spațiului de nume al
operatorului self pentru clase.
<?php
namespace MyProject;
<?php
Important Abilitatea de a face referire la un nume extern complet calificat cu un alias, sau de a
importa, este o caracteristică importantă a spațiilor de nume. Acest lucru este similar cu capacitatea
sistemelor de fișiere bazate pe Unix de a crea legături simbolice către un fișier sau către un director.
Important PHP poate alias(/import) constante, funcții, clase, interfețe, trăsături, enumerari și spații
de nume.
Important Aliasarea se realizează cu operatorul de utilizare. Iată un exemplu care arată toate cele 5
tipuri de import:
<?php
namespace foo;
use My\Full\Classname as Another;
// importing a function
use function My\Full\functionName;
// aliasing a function
use function My\Full\functionName as func;
// importing a constant
use const My\Full\CONSTANT;
Important PHP acceptă în plus o comandă rapidă convenabilă pentru a plasa mai multe instrucțiuni
de utilizare pe aceeași linie
<?php
use My\Full\Classname as Another, My\Full\NSname;
<?php
use My\Full\Classname as Another, My\Full\NSname;
Important Cuvântul cheie use trebuie declarat în sfera cea mai exterioară a unui fișier (sfera
globală) sau în declarațiile de spațiu de nume. Acest lucru se datorează faptului că importul se face
în timpul compilării și nu în timpul rulării, deci nu poate fi blocat. Următorul exemplu va arăta o
utilizare ilegală a cuvântului cheie use:
<?php
namespace Languages;
function toGreenlandic()
{ use Languages\Danish;// ...}
?>
Important Clasele, funcțiile și constantele importate din același spațiu de nume pot fi grupate într-o
singură instrucțiune de utilizare.
<?php
use some\namespace\ClassA;
use some\namespace\ClassB;
use some\namespace\ClassC as C;
Important Fără nicio definiție a spațiului de nume, toate definițiile de clasă și funcții sunt plasate în
spațiul global - așa cum era în PHP înainte ca spațiile de nume să fie suportate. Prefixarea unui
nume cu \ va specifica faptul că numele este necesar din spațiul global chiar și în contextul spațiului
de nume.
<?php
namespace A\B\C;
Important În interiorul unui spațiu de nume, când PHP întâlnește un nume necalificat într-un nume
de clasă, funcție sau context constant, le rezolvă cu priorități diferite. Numele claselor se rezolvă
întotdeauna la numele actual al spațiului de nume. Astfel, pentru a accesa clase de utilizatori interne
sau fără spații de nume, trebuie să faceți referire la ele cu numele lor complet calificat, ca în:
<?php
namespace A\B\C;
class Exception extends \Exception {}
<?php
namespace A\B\C;
Nume necalificat
Acesta este un identificator fără un separator de spațiu de nume, cum ar fi Foo
Nume calificat
Acesta este un identificator cu un separator de spațiu de nume, cum ar fi Foo\Bar
Nume complet calificat
Acesta este un identificator cu un separator de spațiu de nume care începe cu un separator de
spațiu de nume, cum ar fi \Foo\Bar. Spațiul de nume \Foo este, de asemenea, un nume complet
calificat.
Nume relativ
Acesta este un identificator care începe cu namespace, cum ar fi namespace\Foo\Bar.
Numele sunt rezolvate urmând aceste reguli de rezoluție:
• Numele complet calificate se rezolvă întotdeauna la nume fără separator principal de spațiu
de nume. De exemplu, \A\B se rezolvă în A\B.
• Numele relative se rezolvă întotdeauna la numele cu spațiul de nume înlocuit cu spațiul de
nume curent. Dacă numele apare în spațiul de nume global, prefixul de spațiu de nume\ este
eliminat. De exemplu, namespace\A din interiorul namespace X\Y se rezolvă în X\Y\A.
Același nume în interiorul spațiului de nume global se rezolvă în A.
• Pentru numele calificate, primul segment al numelui este tradus conform tabelului curent de
import de clasă/spațiu de nume. De exemplu, dacă spațiul de nume A\B\C este importat ca
C, numele C\D\E este tradus în A\B\C\D\E.
• Pentru numele calificate, dacă nu se aplică nicio regulă de import, spațiul de nume curent
este adăugat înaintea numelui. De exemplu, numele C\D\E din spațiul de nume A\B, se
rezolvă în A\B\C\D\E.
• Pentru numele necalificate, numele este tradus conform tabelului de import curent pentru
tipul de simbol respectiv. Aceasta înseamnă că numele de clasă sunt traduse conform
tabelului de import clasă/spațiu de nume, numele funcțiilor conform tabelului de import al
funcției și constantele conform tabelului de import constant. De exemplu, după utilizarea A\
B\C; o utilizare precum noul C() se rezolvă la numele A\B\C(). În mod similar, după
utilizare funcția A\B\foo; o utilizare precum foo() se rezolvă la numele A\B\foo.
• Pentru numele necalificate, dacă nu se aplică nicio regulă de import și numele se referă la un
simbol asemănător clasei, spațiul de nume curent este adăugat înainte. De exemplu, noul C()
în spațiul de nume A\B se rezolvă la numele A\B\C.
• Pentru numele necalificate, dacă nu se aplică nicio regulă de import și numele se referă la o
funcție sau constantă și codul se află în afara spațiului de nume global, numele este rezolvat
în timpul execuției. Presupunând că codul se află în spațiul de nume A\B, iată cum este
rezolvat un apel la funcția foo():
◦ Caută o funcție din spațiul de nume curent: A\B\foo().
◦ Încearcă să găsească și să apeleze funcția globală foo().
<?php
namespace A;
use B\D, C\E as F;
// function calls
// class references
new D(); // using import rules, creates object of class "D" defined in namespace "B"
// if not found, it tries to autoload class "B\D"
new F(); // using import rules, creates object of class "E" defined in namespace "C"
// if not found, it tries to autoload class "C\E"
D::foo(); // using import rules, calls method "foo" of class "D" defined in namespace "B"
// if class "B\D" not found, it tries to autoload class "B\D"
29. Enumerarile
Important Enumerările, sau „Enumări”, permit unui dezvoltator să definească un tip personalizat
care este limitat la una dintr-un număr discret de valori posibile. Acest lucru poate fi deosebit de util
la definirea unui model de domeniu, deoarece permite „facerea stărilor nevalide nereprezentabile”.
Important Enumerările apar în multe limbi cu o varietate de caracteristici diferite. În PHP, Enums-
urile sunt un tip special de obiect. Enum în sine este o clasă, iar cazurile sale posibile sunt toate
obiecte cu o singură instanță ale acelei clase. Aceasta înseamnă că cazurile Enum sunt obiecte
valide și pot fi folosite oriunde poate fi folosit un obiect, inclusiv verificări de tip.
Important Cel mai popular exemplu de enumerare este tipul boolean încorporat, care este un tip
enumerat cu valori legale true și false. Enums permite dezvoltatorilor să-și definească propriile
enumerari arbitrar robuste.
Important Enumerările sunt similare cu clasele și au aceleași spații de nume ca și clasele, interfețele
și trăsăturile. De asemenea, sunt autoîncărcabile în același mod. O Enum definește un nou tip, care
are un număr fix, limitat de valori legale posibile.
<?php
enum Suit
{
case Hearts;
case Diamonds;
case Clubs;
case Spades;
}
?>
Important Această declarație creează un nou tip enumerat numit Suit, care are patru și doar patru
valori legale: Suit::Hearts, Suit::Diamonds, Suit::Clubs și Suit::Spades. Variabilele pot fi atribuite
uneia dintre aceste valori legale. O funcție poate fi verificată cu un tip enumerat, caz în care pot fi
transmise numai valorile acelui tip.
Important O enumerare poate avea zero sau mai multe definiții de caz, fără maxim. O enumerare cu
cazuri zero este validă din punct de vedere sintactic, chiar dacă mai degrabă inutilă.
Important În mod implicit, cazurile nu sunt susținute intrinsec de o valoare scalară. Adică,
Suit::Hearts nu este egal cu „0”. În schimb, fiecare caz este susținut de un obiect singleton cu acel
nume. Asta înseamnă că:
<?php
$a = Suit::Spades;
$b = Suit::Spades;
Important De asemenea, înseamnă că valorile enumerate nu sunt niciodată < sau > una pe cealaltă,
deoarece acele comparații nu sunt semnificative pentru obiecte. Aceste comparații vor returna
întotdeauna false atunci când se lucrează cu valori enumerate.
Important Acest tip de caz, fără date aferente, se numește „caz pur”. O Enum care conține doar
cazuri pure se numește Enum pur.
Important Toate cazurile pure sunt implementate ca instanțe de tipul lor de enumerare. Tipul de
enumerare este reprezentat intern ca o clasă.
Important Toate cazurile au o proprietate de numai citire, nume, adică numele casei în sine care face
distincție între majuscule și minuscule.
<?php
print Suit::Spades->name;
// prints "Spades"
?>
Important De asemenea, este posibil să utilizați funcțiile definite() și constant() pentru a verifica
existența sau pentru a citi un caz de enumerare dacă numele este obținut dinamic. Acest lucru este,
totuși, descurajat, deoarece utilizarea enumărilor susținute ar trebui să funcționeze pentru
majoritatea cazurilor de utilizare.
Important În mod implicit, cazurile enumerate nu au echivalent scalar. Sunt pur și simplu obiecte
singleton. Cu toate acestea, există cazuri ample în care un caz enumerat trebuie să poată merge dus-
întors la o bază de date sau un depozit de date similar, astfel încât este util să existe un echivalent
scalar încorporat (și astfel trivial serializabil) definit intrinsec. Pentru a defini un echivalent scalar
pentru o Enumerare, sintaxa este următoarea:
<?php
Important Un caz care are un echivalent scalar se numește un caz susținut, deoarece este „susținut”
de o valoare mai simplă. O enumerare care conține toate cazurile susținute se numește „Enumerare
susținută”. O enumerare susținută poate conține doar cazuri susținute. O enumerare pură poate
conține doar cazuri pure.
Important O enumerare susținută poate fi susținută de tipuri de int sau șir, iar o enumerare dată
acceptă doar un singur tip la un moment dat (adică, nicio unire a int|șir). Dacă o enumerare este
marcată ca având un echivalent scalar, atunci toate cazurile trebuie să aibă un echivalent scalar unic
definit în mod explicit. Nu există echivalente scalare autogenerate (de exemplu, numere întregi
secvențiale). Carcasele susținute trebuie să fie unice; este posibil ca două cazuri de enumerare
susținute să nu aibă același echivalent scalar. Cu toate acestea, o constantă se poate referi la un caz,
creând efectiv un alias. Consultați Constante de enumerare.
Important Valorile echivalente trebuie să fie literale sau expresii literale. Constantele și expresiile
constante nu sunt acceptate. Adică, 1 + 1 este permis, dar 1 + SOME_CONST nu este.
Important Carcasele susținute au o proprietate suplimentară de numai citire, value, care este
valoarea specificată în definiție.
<?php
print Suit::Clubs->value;
// Prints "C"
?>
<?php
$suit = Suit::Clubs;
$ref = &$suit->value;
// Error: Cannot acquire reference to property Suit::$value
?>
Enumerările susținute implementează o interfață internă BackedEnum, care expune două metode
suplimentare:
• from(int|string): self va lua un scalar și va returna Enum Case corespunzătoare. Dacă nu se
găsește unul, va arunca o valoare ValueError. Acest lucru este util în principal în cazurile în
care scalarul de intrare este de încredere și o valoare de enumerare lipsă ar trebui considerată
o eroare de oprire a aplicației.
• tryFrom(int|string): ?self va lua un scalar și va returna Enum Case corespunzătoare. Dacă nu
se găsește unul, va returna null. Acest lucru este util în principal în cazurile în care scalarul
de intrare nu este de încredere și apelantul dorește să-și implementeze propria lor gestionare
a erorilor sau logica valorii implicite.
Important Metodele from() și tryFrom() urmează regulile standard de tastare slabe/puternice. În
modul de tastare slabă, trecerea unui număr întreg sau șir este acceptabilă și sistemul va forța
valoarea în consecință. De asemenea, trecerea unui flotor va funcționa și va fi forțată. În modul de
tastare strictă, trecerea unui număr întreg la from() pe o enumerare susținută de șir (sau invers) va
avea ca rezultat o TypeError, la fel ca un float în toate circumstanțele. Toate celelalte tipuri de
parametri vor genera o TypeError în ambele moduri.
<?php
$record = get_stuff_from_database($id);
print $record['suit'];
$suit = Suit::from($record['suit']);
// Invalid data throws a ValueError: "X" is not a valid scalar value for enum "Suit"
print $suit->value;
$suit = Suit::tryFrom('A') ?? Suit::Spades;
// Invalid data returns null, so Suit::Spades is used instead.
print $suit->value;
?>
Important Enumerările (atât Pure Enums, cât și Backed Enums) pot conține metode și pot
implementa interfețe. Dacă o Enum implementează o interfață, atunci orice verificare de tip pentru
acea interfață va accepta, de asemenea, toate cazurile acelei Enum.
<?php
interface Colorful
{
public function color(): string;
}
paint(Suit::Clubs); // Works
Important În acest exemplu, toate cele patru instanțe ale lui Suit au două metode, color() și shape().
În ceea ce privește codul de apelare și verificările de tip, acestea se comportă exact la fel ca orice
altă instanță de obiect. Pe o enumerare susținută, declarația interfeței merge după declarația tipului
de suport.
Important În acest exemplu, toate cele patru instanțe ale lui Suit au două metode, color() și shape().
În ceea ce privește codul de apelare și verificările de tip, acestea se comportă exact la fel ca orice
altă instanță de obiect. Pe o enumerare susținută, declarația interfeței merge după declarația tipului
de suport.
<?php
interface Colorful
{
public function color(): string;
}
Important În interiorul unei metode, variabila $this este definită și se referă la instanța Case.
Metodele pot fi în mod arbitrar complexe, dar în practică vor returna de obicei o valoare statică sau
potrivire pe $this pentru a oferi rezultate diferite pentru cazuri diferite.
<?php
interface Colorful
{
public function color(): string;
}
Important Metodele pot fi publice, private sau protejate, deși în practică private și protejate sunt
echivalente, deoarece moștenirea nu este permisă.
Important Enumerările pot avea și metode statice. Utilizarea metodelor statice pe enumerarea în
sine este în primul rând pentru constructori alternativi. de ex.:
<?php
enum Size
{
case Small;
case Medium;
case Large;
Important Metodele statice pot fi publice, private sau protejate, deși în practică private și protejate
sunt echivalente, deoarece moștenirea nu este permisă.
Important Enumerările pot include constante, care pot fi publice, private sau protejate, deși în
practică private și protejate sunt echivalente, deoarece moștenirea nu este permisă. O constantă de
enumerare se poate referi la un caz de enumerare:
<?php
enum Size
{
case Small;
case Medium;
case Large;
public const Huge = self::Large;
}
?>
Important Enumerările pot folosi trăsături, care se vor comporta la fel ca la clase. Avertismentul
este că trăsăturile utilizate într-o enumerare nu trebuie să conțină proprietăți. Acestea pot include
numai metode și metode statice. O trăsătură cu proprietăți va duce la o eroare fatală.
<?php
interface Colorful
{
public function color(): string;
}
trait Rectangle
{
public function shape(): string {
return "Rectangle";
}
}
case Hearts;
case Diamonds;
case Clubs;
case Spades;
Important Deoarece cazurile sunt reprezentate ca constante pe enumerarea în sine, ele pot fi
utilizate ca valori statice în majoritatea expresiilor constante: valorile implicite ale proprietăților,
valorile implicite ale variabilelor statice, valorile implicite ale parametrilor, valorile globale și
constante de clasă. Ele nu pot fi utilizate în alte valori de caz enumerare, dar constantele normale se
pot referi la un caz enumerare.
Important Cu toate acestea, apelurile implicite de metode magice, cum ar fi ArrayAccess pe
enumerari, nu sunt permise în definițiile statice sau constante, deoarece nu putem garanta în mod
absolut că valoarea rezultată este deterministă sau că invocarea metodei este lipsită de efecte
secundare. Apelurile de funcții, apelurile de metode și accesul la proprietate continuă să fie operații
nevalide în expresiile constante.
<?php
// This is an entirely legal Enum definition.
enum Direction implements ArrayAccess
{
case Up;
case Down;
public function offsetExists($offset): bool
{
return false;
}
public function offsetGet($offset): mixed
{
return null;
}
public function offsetSet($offset, $value): void
{
throw new Exception();
}
public function offsetUnset($offset): void
{
throw new Exception();
}
}
class Foo
{
// This is allowed.
const DOWN = Direction::Down;
// This is disallowed, as it may not be deterministic.
const UP = Direction::Up['short'];
// Fatal error: Cannot use [] on enums in constant expression
}
// This is entirely legal, because it's not a constant expression.
$x = Direction::Up['short'];
var_dump("\$x is " . var_export($x, true));
Important Deși Enum-urile sunt construite pe clase și obiecte, ele nu acceptă toate funcționalitățile
legate de obiecte. În special, cazurile Enum sunt interzise de a avea stat.
• Constructorii și Destructorii sunt interzise.
• Moștenirea nu este acceptată. Enumerările nu pot fi extinse sau extinse.
• Proprietățile statice sau ale obiectului nu sunt permise.
• Clonarea unui caz Enum nu este acceptată, deoarece cazurile trebuie să fie instanțe
singleton.
• Metodele magice, cu excepția celor enumerate mai jos, sunt interzise.
• Enumerările trebuie întotdeauna declarate înainte de a fi utilizate.
Important Constanta magică ::class pe un tip Enum evaluează numele tipului, inclusiv orice spațiu
de nume, exact la fel ca un obiect. Constanta magică ::class pe o instanță Case evaluează, de
asemenea, tipul Enum, deoarece este o instanță de acel tip.
Important În plus, cazurile enumerate nu pot fi instanțiate direct cu new, nici cu
ReflectionClass::newInstanceWithoutConstructor() în reflectare. Ambele vor avea ca rezultat o
eroare.
<?php
Important Atât Pure Enums, cât și Backed Enums implementează o interfață internă numită
UnitEnum. UnitEnum include o metodă statică case(). cases() returnează o matrice împachetată cu
toate cazurile definite în ordinea declarației.
<?php
Suit::cases();
// Produces: [Suit::Hearts, Suit::Diamonds, Suit::Clubs, Suit::Spades]
?>
Important Enumerările sunt serializate diferit de obiecte. Mai exact, au un nou cod de serializare,
„E”, care specifică numele cazului de enumerare. Rutina de deserializare este apoi capabilă să o
folosească pentru a seta o variabilă la valoarea singleton existentă. Aceasta asigură că:
<?php
print serialize(Suit::Hearts);
// E:11:"Suit:Hearts";
?>
<?php
enum Foo {
case Bar;
}
print_r(Foo::Bar);
print_r(Baz::Beep);
/* Produces
Foo Enum (
[name] => Bar
)
Baz Enum:int {
[name] => Beep
[value] => 5
}
*/
?>
<?php
class A {}
class B extends A {}
function foo(A $a) {}
function bar(B $b) {
foo($b);
}
?>
Important Acest cod este sigur de tip, deoarece B urmează contractul lui A, iar prin magia
co/contra-varianță, orice așteptare pe care cineva o poate avea de la metode va fi păstrată, cu
excepții.
Important Enumerările au contracte pentru cazurile lor, nu metode:
<?php
enum ErrorCode {
case SOMETHING_BROKE;
}
?>
Important Declarația de potrivire din funcția quux poate fi analizată static pentru a acoperi toate
cazurile din ErrorCode.
Important Dar imaginați-vă că era permisă extinderea enumerarilor:
<?php
fot(MoreErrorCode::PEBKAC);
?>
Important Conform regulilor normale de moștenire, o clasă care extinde alta va trece verificarea de
tip. Problema ar fi că declarația de potrivire din quux() nu mai acoperă toate cazurile. Deoarece nu
știe despre MoreErrorCode::PEBKAC, meciul va arunca o excepție. Din acest motiv, enumerarile
sunt definitive si nu pot fi extinse.
29. Erori
Important PHP raportează erori ca răspuns la o serie de condiții interne de eroare. Acestea pot fi
utilizate pentru a semnala o serie de condiții diferite și pot fi afișate și/sau înregistrate după cum
este necesar.
Important Fiecare eroare generată de PHP include un tip. Este disponibilă o listă a acestor tipuri de
erori, împreună cu o scurtă descriere a comportamentului lor și a modului în care pot fi cauzate.
Important Dacă nu este setat niciun handler de erori, atunci PHP va gestiona orice erori care apar
conform configurației sale. Ce erori sunt raportate și care sunt ignorate este controlată de directiva
error_reporting [Link] sau în timpul execuției apelând error_reporting(). Cu toate acestea, este
recomandat ca directiva de configurare să fie setată, deoarece pot apărea unele erori înainte de a
începe execuția scriptului.
Important Într-un mediu de dezvoltare, ar trebui să setați întotdeauna error_reporting la E_ALL,
deoarece trebuie să fiți conștient și să remediați problemele ridicate de PHP. În producție, este
posibil să doriți să setați acest lucru la un nivel mai puțin pronunțat, cum ar fi E_ALL &
~E_NOTICE & ~E_DEPRECATED, dar în multe cazuri E_ALL este, de asemenea, adecvat,
deoarece poate oferi o avertizare timpurie a potențialelor probleme.
Important Ce face PHP cu aceste erori depinde de alte două directive [Link]. display_errors
controlează dacă eroarea este afișată ca parte a ieșirii scriptului. Acest lucru ar trebui să fie
întotdeauna dezactivat într-un mediu de producție, deoarece poate include informații confidențiale,
cum ar fi parolele bazei de date, dar este adesea util pentru activare în dezvoltare, deoarece asigură
raportarea imediată a problemelor.
Important Pe lângă afișarea erorilor, PHP poate înregistra erori atunci când directiva log_errors este
activată. Aceasta va înregistra orice erori în fișierul sau syslog definit de error_log. Acest lucru
poate fi extrem de util într-un mediu de producție, deoarece puteți înregistra erorile care apar și apoi
puteți genera rapoarte pe baza acestor erori.
Important Dacă gestionarea implicită a erorilor PHP este inadecvată, puteți, de asemenea, să
gestionați multe tipuri de erori cu propriul dvs. handler personalizat de erori, instalându-l cu
set_error_handler(). În timp ce unele tipuri de erori nu pot fi gestionate în acest fel, cele care pot fi
tratate pot fi apoi tratate în modul în care scriptul dvs. consideră potrivit: de exemplu, aceasta poate
fi folosită pentru a afișa utilizatorului o pagină de eroare personalizată și apoi pentru a raporta mai
direct decât printr-un jurnal, cum ar fi prin trimiterea unui e-mail.
30. Exceptii
Important PHP are un model de excepție similar cu cel al altor limbaje de programare. O excepție
poate fi aruncată și prinsă ("prinsă") în PHP. Codul poate fi înconjurat într-un bloc de încercare,
pentru a facilita identificarea potențialelor excepții. Fiecare încercare trebuie să aibă cel puțin o
captură corespunzătoare sau un bloc în final.
Important Dacă se aruncă o excepție și domeniul său de aplicare curent al funcției nu are nici un
bloc catch, excepția va „bulbota” stiva de apeluri către funcția de apelare până când va găsi un bloc
catch care se potrivește. Toate blocurile pe care le întâlnește în cele din urmă pe parcurs vor fi
executate. Dacă stiva de apeluri este derulată până la sfera globală fără a întâlni un bloc catch care
se potrivește, programul se va termina cu o eroare fatală, dacă nu a fost setat un handler global de
excepții.
Important Obiectul aruncat trebuie să fie o instanță a Throwable. Încercarea de a arunca un obiect
care nu este, va avea ca rezultat o eroare fatală PHP.
Important Începând cu PHP 8.0.0, cuvântul cheie throw este o expresie și poate fi folosit în orice
context de expresie. În versiunile anterioare, era o declarație și trebuia să fie pe propria linie.
Important Un bloc catch definește modul de răspuns la o excepție aruncată. Un bloc catch definește
unul sau mai multe tipuri de excepții sau erori pe care le poate gestiona și, opțional, o variabilă
căreia să îi atribuie excepția. (Variabila era necesară înainte de PHP 8.0.0.) Primul bloc de captură
pe care o întâlnește o excepție sau o eroare aruncată care se potrivește cu tipul obiectului aruncat se
va ocupa de obiect.
Important Mai multe blocuri de captură pot fi utilizate pentru a prinde diferite clase de excepții.
Execuția normală (când nu se aruncă nicio excepție în blocul try) va continua după ultimul bloc
catch definit în secvență. Excepțiile pot fi aruncate (sau re-aruncate) în cadrul unui bloc de captură.
Dacă nu, execuția va continua după blocul catch care a fost declanșat.
Important Când se aruncă o excepție, codul care urmează instrucțiunii nu va fi executat și PHP va
încerca să găsească primul bloc catch potrivit. Dacă o excepție nu este capturată, o eroare fatală
PHP va fi emisă cu un mesaj „Uncaught Exception...”, cu excepția cazului în care un handler a fost
definit cu set_exception_handler().
Important Începând cu PHP 7.1.0, un bloc catch poate specifica mai multe excepții folosind
caracterul pipe (|). Acest lucru este util atunci când diferite excepții din diferite ierarhii de clasă sunt
tratate la fel.
Important Începând cu PHP 8.0.0, numele variabilei pentru o excepție capturată este opțional. Dacă
nu este specificat, blocul catch se va executa în continuare, dar nu va avea acces la obiectul aruncat.
Important Un bloc final poate fi, de asemenea, specificat după sau în locul blocurilor catch. Codul
din blocul finally va fi întotdeauna executat după blocurile try and catch, indiferent dacă a fost
aruncată o excepție și înainte de reluarea execuției normale.
Important O interacțiune notabilă este între blocul final și o instrucțiune return. Dacă în interiorul
blocurilor try sau catch este întâlnită o instrucțiune return, blocul final va fi în continuare executat.
Mai mult, instrucțiunea return este evaluată atunci când este întâlnită, dar rezultatul va fi returnat
după executarea blocului final. În plus, dacă blocul finally conține și o instrucțiune return, valoarea
din blocul finally este returnată.
Important Dacă o excepție este permisă să ajungă la sfera globală, aceasta poate fi capturată de un
handler global de excepții dacă este setată. Funcția set_exception_handler() poate seta o funcție care
va fi apelată în locul unui bloc catch dacă nu este invocat niciun alt bloc. Efectul este în esență
același ca și cum întregul program ar fi înfășurat într-un bloc try-catch cu acea funcție ca catch.
<?php
function exceptions_error_handler($severity, $message, $filename, $lineno) {
throw new ErrorException($message, 0, $severity, $filename, $lineno);
}
set_error_handler('exceptions_error_handler');
?>
<?php
function inverse($x) {
if (!$x) {
throw new Exception('Division by zero.');
}
return 1/$x;
}
try {
echo inverse(5) . "\n";
echo inverse(0) . "\n";
} catch (Exception $e) {
echo 'Caught exception: ', $e->getMessage(), "\n";
}
// Continue execution
echo "Hello World\n";
?>
<?php
function inverse($x) {
if (!$x) {
throw new Exception('Division by zero.');
}
return 1/$x;
}
try {
echo inverse(5) . "\n";
} catch (Exception $e) {
echo 'Caught exception: ', $e->getMessage(), "\n";
} finally {
echo "First finally.\n";
}
try {
echo inverse(0) . "\n";
} catch (Exception $e) {
echo 'Caught exception: ', $e->getMessage(), "\n";
} finally {
echo "Second finally.\n";
}
// Continue execution
echo "Hello World\n";
?>
Important O clasă de excepție definită de utilizator poate fi definită prin extinderea clasei de
excepție încorporate. Membrii și proprietățile de mai jos arată ceea ce este accesibil în clasa copil
care derivă din clasa încorporată Exception.
<?php
class Exception implements Throwable
{
protected $message = 'Unknown exception'; // exception message
private $string; // __toString cache
protected $code = 0; // user defined exception code
protected $file; // source filename of exception
protected $line; // source line of exception
private $trace; // backtrace
private $previous; // previous exception if nested exception
// Overrideable
public function __toString(); // formatted string for display
}
?>
Important Dacă o clasă extinde clasa de excepție încorporată și redefinește constructorul, este foarte
recomandat să apeleze și parent::__construct() pentru a se asigura că toate datele disponibile au fost
alocate corect. Metoda __toString() poate fi suprascrisă pentru a oferi o ieșire personalizată atunci
când obiectul este prezentat ca șir.
<?php
/**
* Define a custom exception class
*/
class MyException extends Exception
{
// Redefine the exception so message isn't optional
public function __construct($message, $code = 0, Throwable $previous = null) {
// some code
/**
* Create a class to test the exception
*/
class TestException
{
public $var;
const THROW_NONE = 0;
const THROW_CUSTOM = 1;
const THROW_DEFAULT = 2;
switch ($avalue) {
case self::THROW_CUSTOM:
// throw custom exception
throw new MyException('1 is an invalid parameter', 5);
break;
case self::THROW_DEFAULT:
// throw default one.
throw new Exception('2 is not allowed as a parameter', 6);
break;
default:
// No exception, object will be created.
$this->var = $avalue;
break;
}
}
}
// Example 1
try {
$o = new TestException(TestException::THROW_CUSTOM);
} catch (MyException $e) { // Will be caught
echo "Caught my exception\n", $e;
$e->customFunction();
} catch (Exception $e) { // Skipped
echo "Caught Default Exception\n", $e;
}
// Continue execution
var_dump($o); // Null
echo "\n\n";
// Example 2
try {
$o = new TestException(TestException::THROW_DEFAULT);
} catch (MyException $e) { // Doesn't match this type
echo "Caught my exception\n", $e;
$e->customFunction();
} catch (Exception $e) { // Will be caught
echo "Caught Default Exception\n", $e;
}
// Continue execution
var_dump($o); // Null
echo "\n\n";
// Example 3
try {
$o = new TestException(TestException::THROW_CUSTOM);
} catch (Exception $e) { // Will be caught
echo "Default Exception caught\n", $e;
}
// Continue execution
var_dump($o); // Null
echo "\n\n";
// Example 4
try {
$o = new TestException();
} catch (Exception $e) { // Skipped, no exception
echo "Default Exception caught\n", $e;
}
// Continue execution
var_dump($o); // TestException
echo "\n\n";
?>
31. Fibrele
Important Fibrele reprezintă funcții full-stack, întreruptibile. Fibrele pot fi suspendate de oriunde în
stiva de apeluri, întrerupând execuția în interiorul fibrei până când fibra este reluată la un moment
ulterior. Fibrele pun în pauză întreaga stivă de execuție, astfel încât apelantul direct al funcției nu
trebuie să schimbe modul în care invocă funcția. Execuția poate fi întreruptă oriunde în stiva de
apeluri folosind Fiber::suspend() (adică apelul la Fiber::suspend() poate fi într-o funcție profund
imbricată sau chiar să nu existe deloc).
Important Spre deosebire de generatoarele fără stivă, fiecare fibră are propria sa stivă de apeluri,
permițându-le să fie întrerupte în apeluri de funcții imbricate profund. O funcție care declară un
punct de întrerupere (adică apelând Fiber::suspend()) nu trebuie să își schimbe tipul de returnare,
spre deosebire de o funcție care utilizează yield care trebuie să returneze o instanță Generator.
Important Fibrele pot fi suspendate în orice apel de funcție, inclusiv cele apelate din cadrul PHP
VM, cum ar fi funcțiile furnizate către array_map() sau metodele apelate de foreach pe un obiect
Iterator.
Important Odată suspendată, execuția fibrei poate fi reluată cu orice valoare folosind
Fiber::resume() sau prin aruncarea unei excepții în fibră folosind Fiber::throw(). Valoarea este
returnată (sau o excepție aruncată) din Fiber::suspend().
<?php
$fiber = new Fiber(function (): void {
$value = Fiber::suspend('fiber');
echo "Value used to resume fiber: ", $value, PHP_EOL;
});
$value = $fiber->start();
$fiber->resume('test');
?>
31. Generatoarele
Important Generatoarele oferă o modalitate ușoară de implementare a iteratoarelor simple, fără
costul general sau complexitatea implementării unei clase care implementează interfața Iterator.
Important Un generator oferă o modalitate convenabilă de a furniza date pentru fiecare bucle fără a
fi nevoie să construiți o matrice în memorie înainte de timp, ceea ce poate face ca programul să
depășească o limită de memorie sau să necesite o cantitate considerabilă de timp de procesare
pentru a genera. În schimb, poate fi utilizată o funcție de generator, care este aceeași cu o funcție
normală, cu excepția faptului că, în loc să revină o dată, un generator poate produce de câte ori este
nevoie pentru a furniza valorile pe care să le iterați. Ca și în cazul iteratoarelor, accesul la date
aleatoriu nu este posibil.
Important Un exemplu simplu în acest sens este reimplementarea funcției range() ca generator.
Funcția standard range() trebuie să genereze o matrice cu fiecare valoare din ea și să o returneze,
ceea ce poate duce la matrice mari: de exemplu, apelarea range(0, 1000000) va avea ca rezultat
folosirea a peste 100 MB de memorie.
Important Ca alternativă, putem implementa un generator xrange(), care va avea nevoie doar de
suficientă memorie pentru a crea un obiect Iterator și a urmări starea curentă a generatorului în
interior, care se dovedește a fi mai mică de 1 kilobyte.
<?php
function xrange($start, $limit, $step = 1) {
if ($start <= $limit) {
if ($step <= 0) {
throw new LogicException('Step must be positive');
}
Important O funcție de generator arată exact ca o funcție normală, cu excepția faptului că, în loc să
returneze o valoare, un generator dă atâtea valori cât are nevoie. Orice funcție care conține
randament este o funcție generatoare.
Important Când o funcție generatoare este apelată, returnează un obiect care poate fi iterat. Când
iterați peste acel obiect (de exemplu, printr-o buclă foreach), PHP va apela metodele de iterație ale
obiectului de fiecare dată când are nevoie de o valoare, apoi salvează starea generatorului când
generatorul dă o valoare, astfel încât aceasta să poată fi reluată când este necesară următoarea
valoare.
Important Odată ce nu mai sunt valori care să fie date, atunci generatorul se poate întoarce pur și
simplu, iar codul de apel continuă exact ca și cum o matrice a rămas fără valori.
Important Inima unei funcții generatoare este cuvântul cheie yield. În forma sa cea mai simplă, o
instrucțiune yield seamănă mult cu o instrucțiune return, cu excepția faptului că, în loc să oprească
execuția funcției și să revină, yield oferă o valoare buclei codului peste generator și întrerupe
execuția funcției generatorului.
<?php
function gen_one_to_three() {
for ($i = 1; $i <= 3; $i++) {
// Note that $i is preserved between yields.
yield $i;
}
}
$generator = gen_one_to_three();
foreach ($generator as $value) {
echo "$value\n";
}
?>
Important PHP suportă, de asemenea, matrice asociative, iar generatoarele nu sunt diferite. Pe lângă
obținerea unor valori simple, așa cum se arată mai sus, puteți obține și o cheie în același timp.
<?php
/*
* The input is semi-colon separated fields, with the first
* field being an ID to use as a key.
*/
$input = <<<'EOF'
1;PHP;Likes dollar signs
2;Python;Likes whitespace
3;Ruby;Likes blocks
EOF;
function input_parser($input) {
foreach (explode("\n", $input) as $line) {
$fields = explode(';', $line);
$id = array_shift($fields);
yield $id => $fields;
}
}
Important Yield poate fi apelat fără un argument pentru a produce o valoare nulă cu o cheie
automată.
<?php
function gen_three_nulls() {
foreach (range(1, 3) as $i) {
yield;
}
}
var_dump(iterator_to_array(gen_three_nulls()));
?>
Important Funcțiile generatorului sunt capabile să furnizeze valori atât prin referință, cât și prin
valoare. Acest lucru se face în același mod ca și returnarea referințelor din funcții: prin adăugarea
unui ampersand la numele funcției.
<?php
function &gen_reference() {
$value = 3;
/*
* Note that we can change $number within the loop, and
* because the generator is yielding references, $value
* within gen_reference() changes.
*/
foreach (gen_reference() as &$number) {
echo (--$number).'... ';
}
?>
<?php
function inner() {
yield 1; // key 0
yield 2; // key 1
yield 3; // key 2
}
function gen() {
yield 0; // key 0
yield from inner(); // keys 0-2
yield 4; // key 1
}
// pass false as second parameter to get an array [0, 1, 2, 3, 4]
var_dump(iterator_to_array(gen()));
?>
<?php
function count_to_ten() {
yield 1;
yield 2;
yield from [3, 4];
yield from new ArrayIterator([5, 6]);
yield from seven_eight();
yield 9;
yield 10;
}
function seven_eight() {
yield 7;
yield from eight();
}
function eight() {
yield 8;
}
foreach (count_to_ten() as $num) {
echo "$num ";
}
?>
Important Avantajul principal al generatoarelor este simplitatea lor. Trebuie scris mult mai puțin cod
standard în comparație cu implementarea unei clase Iterator, iar codul este în general mult mai
lizibil. De exemplu, următoarele funcție și clasă sunt echivalente:
<?php
function getLinesFromFile($fileName) {
if (!$fileHandle = fopen($fileName, 'r')) {
return;
}
fclose($fileHandle);
}
// versus...
Important Cu toate acestea, această flexibilitate are un cost: generatoarele sunt iteratoare doar
înainte și nu pot fi rebobinate odată ce iterația a început. Aceasta înseamnă, de asemenea, că același
generator nu poate fi repetat de mai multe ori: generatorul va trebui reconstruit apelând din nou
funcția generator.
31. Atributele
Important Atributele oferă posibilitatea de a adăuga informații de metadate structurate, citibile de
mașină, despre declarațiile din cod: Clasele, metodele, funcțiile, parametrii, proprietățile și
constantele de clasă pot fi ținta unui atribut. Metadatele definite de atribute pot fi apoi inspectate în
timpul execuției folosind API-urile Reflection. Prin urmare, atributele ar putea fi gândite ca un
limbaj de configurare încorporat direct în cod.
Important Cu atribute, implementarea generică a unei caracteristici și utilizarea sa concretă într-o
aplicație pot fi decuplate. Într-un fel, este comparabil cu interfețele și implementările acestora. Dar
acolo unde interfețele și implementările sunt despre cod, atributele se referă la adnotarea
informațiilor suplimentare și a configurației. Interfețele pot fi implementate prin clase, dar atributele
pot fi declarate și pe metode, funcții, parametri, proprietăți și constante de clasă. Ca atare, ele sunt
mai flexibile decât interfețele.
Important Un exemplu simplu de utilizare a atributelor este convertirea unei interfețe care are
metode opționale de utilizare a atributelor. Să presupunem o interfață ActionHandler reprezentând o
operație într-o aplicație, unde unele implementări ale unui handler de acțiuni necesită setare, iar
altele nu. În loc să ceară tuturor claselor care implementează ActionHandler să implementeze o
metodă setUp(), poate fi folosit un atribut. Un avantaj al acestei abordări este că putem folosi
atributul de mai multe ori.
<?php
interface ActionHandler
{
public function execute();
}
#[Attribute]
class SetUp {}
$actionHandler->execute();
}
executeAction($copyAction);
Important Există mai multe părți în sintaxa atributelor. În primul rând, o declarație de atribut este
întotdeauna inclusă cu un început #[ și o sfârșit corespunzătoare]. În interior, sunt listate unul sau
mai multe atribute, separate prin virgulă. Numele atributului este un nume necalificat, calificat sau
complet calificat, așa cum este descris în Noțiuni de bază despre utilizarea spațiilor de nume.
Argumentele pentru atribut sunt opționale, dar sunt incluse în parantezele obișnuite (). Argumentele
la atribute pot fi doar valori literale sau expresii constante. Pot fi utilizate atât sintaxa argumentelor
poziționale, cât și denumite.
Important Numele atributelor și argumentele lor sunt rezolvate într-o clasă, iar argumentele sunt
transmise constructorului acesteia, atunci când o instanță a atributului este solicitată prin API-ul
Reflection. Ca atare, ar trebui introdusă o clasă pentru fiecare atribut.
<?php
// [Link]
namespace MyExample;
use Attribute;
#[Attribute]
class MyAttribute
{
const VALUE = 'value';
private $value;
// [Link]
namespace Another;
use MyExample\MyAttribute;
#[MyAttribute]
#[\MyExample\MyAttribute]
#[MyAttribute(1234)]
#[MyAttribute(value: 1234)]
#[MyAttribute(MyAttribute::VALUE)]
#[MyAttribute(array("key" => "value"))]
#[MyAttribute(100 + 200)]
class Thing
{
}
#[MyAttribute(1234), MyAttribute(5678)]
class AnotherThing
{}
Important Pentru a accesa atribute din clase, metode, funcții, parametri, proprietăți și constante de
clasă, API-ul Reflection oferă metoda getAttributes() pentru fiecare dintre obiectele Reflection
corespunzătoare. Această metodă returnează o serie de instanțe ReflectionAttribute care pot fi
interogate pentru numele atributului, argumente și pentru a instanția o instanță a atributului
reprezentat.
Important Această separare a reprezentării atributelor reflectate de instanța reală mărește controlul
programatorului pentru a gestiona erorile privind clasele de atribute lipsă, argumentele greșite sau
lipsa. Numai după apelarea ReflectionAttribute::newInstance(), obiectele clasei de atribute sunt
instanțiate și potrivirea corectă a argumentelor este validată, nu mai devreme.
<?php
#[Attribute]
class MyAttribute
{
public $value;
#[MyAttribute(value: 1234)]
class Thing
{
}
function dumpAttributeData($reflection) {
$attributes = $reflection->getAttributes();
dumpAttributeData(new ReflectionClass(Thing::class));
/*
string(11) "MyAttribute"
array(1) {
["value"]=>
int(1234)
}
object(MyAttribute)#3 (1) {
["value"]=>
int(1234)
}
*/
Important În loc să iterați toate atributele din instanța de reflectare, numai cele ale unei anumite
clase de atribute pot fi preluate prin trecerea numelui clasei de atribute căutate ca argument.
<?php
function dumpMyAttributeData($reflection) {
$attributes = $reflection->getAttributes(MyAttribute::class);
foreach ($attributes as $attribute) {
var_dump($attribute->getName());
var_dump($attribute->getArguments());
var_dump($attribute->newInstance());
}
}
dumpMyAttributeData(new ReflectionClass(Thing::class));
Important Deși nu este strict necesar, se recomandă crearea unei clase reale pentru fiecare atribut. În
cel mai simplu caz este necesară doar o clasă goală cu atributul #[Attribut] declarat, care poate fi
importat din spațiul de nume global cu o instrucțiune use
<?php
namespace Example;
use Attribute;
#[Attribute]
class MyAttribute
{
}
Important Pentru a restricționa tipul de declarație căruia i se poate atribui un atribut, o mască de biți
poate fi transmisă ca prim argument în declarația #[Atribut].
<?php
namespace Example;
use Attribute;
#[Attribute(Attribute::TARGET_METHOD | Attribute::TARGET_FUNCTION)]
class MyAttribute
{
}
Important Declararea MyAttribute pe alt tip va genera acum o excepție în timpul apelului la
ReflectionAttribute::newInstance()
Important Pot fi specificate următoarele obiective:
Attribute::TARGET_CLASS
• Attribute::TARGET_FUNCTION
• Attribute::TARGET_METHOD
• Attribute::TARGET_PROPERTY
• Attribute::TARGET_CLASS_CONSTANT
• Attribute::TARGET_PARAMETER
• Attribute::TARGET_ALL
Important În mod implicit, un atribut poate fi folosit o singură dată pe declarație. Dacă atributul ar
trebui să fie repetabil în declarații, acesta trebuie specificat ca parte a măștii de biți în declarația
#[Atribut].
<?php
namespace Example;
use Attribute;
#[Attribute(Attribute::TARGET_METHOD | Attribute::TARGET_FUNCTION |
Attribute::IS_REPEATABLE)]
class MyAttribute
{
}
33. Referintele
Important Referințele în PHP sunt un mijloc de a accesa același conținut variabil cu nume diferite.
Nu sunt ca pointerii C; de exemplu, nu puteți efectua aritmetica pointer folosindu-le, nu sunt adrese
de memorie reale și așa mai departe.
Important După cum s-a spus anterior, referințele nu sunt indicatoare. Aceasta înseamnă că
următorul construct nu va face ceea ce vă așteptați:
<?php
function foo(&$var)
{
$var =& $GLOBALS["baz"];
}
foo($bar);
?>
Important Ce se întâmplă este că $var în foo va fi legat cu $bar în apelant, dar apoi relegat cu
$GLOBALS["baz"]. Nu există nicio modalitate de a lega $bar în domeniul de apelare la altceva
folosind mecanismul de referință, deoarece $bar nu este disponibil în funcția foo (este reprezentat
de $var, dar $var are doar conținut variabil și nu nume-to- valoarea obligatorie în tabelul cu
simboluri de apelare). Puteți utiliza referințe returnate la variabilele de referință selectate de funcție.
Important Există trei operații de bază efectuate folosind referințe: atribuirea prin referință, trecerea
prin referință și returnarea prin referință.
Important Referințele PHP vă permit să faceți două variabile să se refere la același conținut. Adică
$a și $b indică același conținut daca:
Important Dacă atribuiți, transmiteți sau returnați o variabilă nedefinită prin referință, aceasta va fi
creată.
<?php
function foo(&$var) {}
$b = array();
foo($b['b']);
var_dump(array_key_exists('b', $b)); // bool(true)
$c = new stdClass();
foo($c->d);
var_dump(property_exists($c, 'd')); // bool(true)
?>
Important Dacă atribuiți o referință unei variabile declarate globală în interiorul unei funcții,
referința va fi vizibilă numai în interiorul funcției. Puteți evita acest lucru folosind matricea
$GLOBALS.
<?php
function global_references($use_globals)
{
global $var1, $var2;
if (!$use_globals) {
$var2 =& $var1; // visible only inside the function
} else {
$GLOBALS["var2"] =& $var1; // visible also in global context
}
}
global_references(false);
echo "var2 is set to '$var2'\n"; // var2 is set to ''
global_references(true);
echo "var2 is set to '$var2'\n"; // var2 is set to 'Example variable'
?>
Important Dacă atribuiți o valoare unei variabile cu referințe într-o instrucțiune foreach, referințele
sunt și ele modificate.
<?php
$ref = 0;
$row =& $ref;
?>
Important Deși nu sunt strict o atribuire prin referință, expresiile create cu limbajul construct array()
se pot comporta și ca atare prin prefixarea & la elementul de matrice de adăugat. Exemplu:
<?php
$a = 1;
$b = array(2, 3);
$arr = array(&$a, &$b[0], &$b[1]);
$arr[0]++;
$arr[1]++;
$arr[2]++;
/* $a == 2, $b == array(3, 4); */
?>
Important Rețineți, totuși, că referințele din interiorul matricelor sunt potențial periculoase.
Efectuarea unei asignari normale (nu prin referință) cu o referință în partea dreaptă nu transformă
partea stângă într-o referință, dar referințele din interiorul matricelor sunt păstrate în aceste atribuiri
normale.
<?php
?>
<?php
function foo(&$var)
{
$var++;
}
function &bar()
{
$a = 5;
return $a;
}
foo(bar());
?>
Important Revenirea prin referință este utilă atunci când doriți să utilizați o funcție pentru a găsi la
ce variabilă trebuie legată o referință. Nu utilizați returnarea prin referință pentru a crește
performanța. Motorul va optimiza automat acest lucru singur. Returnați referințele numai atunci
când aveți un motiv tehnic valid pentru a face acest lucru. Pentru a returna referințe, utilizați această
sintaxă:
<?php
class Foo
{
public $value = 42;
?>
Important Spre deosebire de transmiterea parametrilor, aici trebuie să utilizați & în ambele locuri -
pentru a indica că doriți să returnați prin referință, nu o copie, și pentru a indica că legarea
referințelor, mai degrabă decât atribuirea obișnuită, ar trebui făcută pentru $myValue.
Important Dacă încercați să returnați o referință dintr-o funcție cu sintaxa: return ($this->value);
acest lucru nu va funcționa deoarece încercați să returnați rezultatul unei expresii, și nu o variabilă,
prin referință. Puteți returna variabile doar prin referință dintr-o funcție - nimic altceva.
<?php
function &collector()
{
static $collection = array();
return $collection;
}
$collection = &collector();
$collection[] = 'foo';
?>
Important Pentru a transmite referința returnată unei alte funcții care așteaptă o referință, puteți
utiliza această sintaxă:
<?php
function &collector()
{
static $collection = array();
return $collection;
}
array_push(collector(), 'foo');
?>
Important Când anulați referința, doar întrerupeți legătura dintre numele variabilei și conținutul
variabilei. Acest lucru nu înseamnă că conținutul variabil va fi distrus. De exemplu, nu va anula $b,
doar $a.:
<?php
$a = 1;
$b =& $a;
unset($a);
?>
Important Multe construcții de sintaxă în PHP sunt implementate prin mecanisme de referință, așa
că tot ce este menționat aici despre legarea referințelor se aplică și acestor construcții. Unele
constructe, cum ar fi trecerea și întoarcerea prin referință, sunt menționate mai sus. Alte constructe
care folosesc referințe sunt:
<?php
?>
Important Folosirea PHP ca binar CGI este o opțiune pentru setările care, dintr-un motiv oarecare,
nu doresc să integreze PHP ca modul în software-ul server (cum ar fi Apache), sau vor folosi PHP
cu diferite tipuri de wrapper CGI pentru a crea medii sigure pentru chroot și setuid. scenarii.
Această configurare implică de obicei instalarea binarului php executabil în directorul serverului
web cgi-bin. Aviz CERT » CA-96.11 nu recomandă plasarea oricăror interpreți în cgi-bin. Chiar
dacă binarul php poate fi folosit ca interpret independent, PHP este conceput pentru a preveni
atacurile pe care această configurare le face posibile:
• Accesarea fișierelor de sistem: [Link] Informațiile de
interogare dintr-un URL după semnul întrebării (?) sunt transmise interpretului ca argumente
de linie de comandă de către interfața CGI. De obicei, interpreții deschid și execută fișierul
specificat ca prim argument pe linia de comandă. Când este invocat ca binar CGI, php
refuză să interpreteze argumentele liniei de comandă.
• Accesarea oricărui document web de pe server: [Link]
Partea cu informații despre cale a adresei URL după numele binar PHP, /secret/[Link] este
utilizată în mod convențional pentru a specifica numele fișierului care urmează să fie
deschis și interpretat de programul CGI. De obicei, unele directive de configurare a
serverului web (Apache: Action) sunt folosite pentru a redirecționa cererile către documente
precum [Link] către interpretul PHP. Cu această configurare,
serverul web verifică mai întâi permisiunile de acces la directorul /secret, iar după aceea
creează cererea redirecționată [Link] Din păcate, dacă
cererea este dată inițial în acest formular, serverul web nu face verificări de acces pentru
fișierul /secret/[Link], ci doar pentru fișierul /cgi-bin/php. În acest fel, orice utilizator
care poate accesa /cgi-bin/php poate accesa orice document protejat de pe serverul web. În
PHP, directivele de configurare a runtimei cgi.force_redirect, doc_root și user_dir pot fi
folosite pentru a preveni acest atac, dacă arborele documentului serverului are directoare cu
restricții de acces. Vezi mai jos explicația completă a diferitelor combinații.
Important Dacă serverul dvs. nu are niciun conținut care nu este restricționat de parolă sau de
controlul accesului bazat pe IP, nu este nevoie de aceste opțiuni de configurare. Dacă serverul dvs.
web nu vă permite să faceți redirecționări sau serverul nu are o modalitate de a comunica binarului
PHP că cererea este o solicitare redirecționată în siguranță, puteți activa directiva ini
cgi.force_redirect. Încă trebuie să vă asigurați că scripturile dvs. PHP nu se bazează pe una sau alta
modalitate de a apela scriptul, nici prin [Link] nici prin
redirecționarea http:/ /[Link]/dir/[Link].
Important Puteți seta rădăcina documentului de script PHP prin directiva de configurare doc_root
din fișierul de configurare sau puteți seta variabila de mediu PHP_DOCUMENT_ROOT. Dacă este
setată, versiunea CGI a PHP va construi întotdeauna numele fișierului de deschis cu acest doc_root
și informațiile de cale din cerere, astfel încât să puteți fi sigur că nu este executat niciun script în
afara acestui director (cu excepția user_dir de mai jos).
Important O altă opțiune utilizabilă aici este user_dir. Când user_dir este nesetat, singurul lucru care
controlează numele fișierului deschis este doc_root. Deschiderea unei adrese URL precum
[Link] nu are ca rezultat deschiderea unui fișier în directorul principal al
utilizatorilor, ci a unui fișier numit ~user/[Link] sub doc_root (da, un nume de director care începe
cu o tildă [~]).
Important Dacă user_dir este setat, de exemplu, la public_php, o solicitare precum
[Link] va deschide un fișier numit [Link] în directorul denumit public_php
din directorul principal al utilizatorului. Dacă domiciliul utilizatorului este /home/user, fișierul
executat este /home/user/public_php/[Link].
Important Extinderea user_dir are loc indiferent de setarea doc_root, astfel încât puteți controla
separat accesul la rădăcina documentului și la directorul utilizatorului.
Important O opțiune foarte sigură este să puneți binarul parser PHP undeva în afara arborelui web al
fișierelor. În /usr/local/bin, de exemplu. Singurul dezavantaj real al acestei opțiuni este că acum va
trebui să puneți o linie similară cu: #!/usr/local/bin/php ca prima linie a oricărui fișier care conține
etichete PHP. De asemenea, va trebui să faceți fișierul executabil. Adică, tratați-l exact așa cum ați
trata orice alt script CGI scris în Perl sau sh sau orice alt limbaj de scripting comun care utilizează
#! mecanism de evacuare a carcasei pentru lansare.
Important Pentru ca PHP să gestioneze corect informațiile PATH_INFO și PATH_TRANSLATED
cu această setare, directiva ini cgi.discard_path trebuie să fie activată.
Important Deoarece PHP a fost conceput pentru a permite accesul la nivel de utilizator la sistemul
de fișiere, este complet posibil să scrieți un script PHP care vă va permite să citiți fișiere de sistem,
cum ar fi /etc/passwd, să vă modificați conexiunile Ethernet, să trimiteți lucrări masive de
imprimantă etc. are unele implicații evidente, prin aceea că trebuie să vă asigurați că fișierele din
care citiți și în care scrieți sunt cele adecvate.
<?php
unlink("$homedir/$userfile");
?>
Important Deoarece numele de utilizator și numele fișierului pot fi postate dintr-un formular de
utilizator, aceștia pot trimite un nume de utilizator și un nume de fișier aparținând altcuiva și le pot
șterge chiar dacă nu ar trebui să li se permită să facă acest lucru. În acest caz, ați dori să utilizați o
altă formă de autentificare. Luați în considerare ce s-ar putea întâmpla dacă variabilele trimise ar fi
„../etc/” și „passwd”. Codul ar citi în mod efectiv:
<?php
unlink("$homedir/$userfile"); // "/home/../etc/passwd"
?>
Important Există două măsuri importante pe care ar trebui să le luați pentru a preveni aceste
probleme.
• Permiteți numai permisiuni limitate pentru binarul utilizatorului web PHP.
• Verificați toate variabilele care sunt trimise.
<?php
$filepath = "$homedir/$userfile";
?>
Important Cu toate acestea, chiar și acest lucru nu este lipsit de defecte. Dacă sistemul dvs. de
autentificare a permis utilizatorilor să-și creeze propriile autentificări de utilizator și un utilizator a
ales autentificarea „../etc/”, sistemul este din nou expus. Din acest motiv, este posibil să preferați să
scrieți un cec mai personalizat:
<?php
$filepath = "$homedir/$userfile";
// etc.
?>
Important În funcție de sistemul dvs. de operare, există o mare varietate de fișiere de care ar trebui
să vă îngrijorați, inclusiv intrările dispozitivului (/dev/ sau COM1), fișierele de configurare
(fișiere /etc/ și fișierele .ini), zone de stocare a fișierelor bine cunoscute. (/home/, Documentele
mele), etc. Din acest motiv, este de obicei mai ușor să creați o politică în care interziceți totul, cu
excepția a ceea ce permiteți în mod explicit.
Important Primul pas este întotdeauna să creați baza de date, cu excepția cazului în care doriți să
utilizați una de la o terță parte. Atunci când o bază de date este creată, aceasta este atribuită unui
proprietar, care a executat instrucțiunea de creare. De obicei, doar proprietarul (sau un
superutilizator) poate face orice cu obiectele din acea bază de date, iar pentru a permite altor
utilizatori să o folosească, trebuie acordate privilegii.
Important Aplicațiile nu ar trebui să se conecteze niciodată la baza de date ca proprietar sau
superutilizator, deoarece acești utilizatori pot executa orice interogare după bunul plac, de exemplu,
modificând schema (de exemplu, eliminarea tabelelor) sau ștergerea întregului conținut.
Important SSL/SSH protejează datele care călătoresc de la client la server: SSL/SSH nu protejează
datele persistente stocate într-o bază de date. SSL este un protocol on-the-wire.
Important Odată ce un atacator obține acces direct la baza ta de date (ocolind serverul web), datele
sensibile stocate pot fi expuse sau utilizate greșit, cu excepția cazului în care informațiile sunt
protejate de baza de date în sine. Criptarea datelor este o modalitate bună de a atenua această
amenințare, dar foarte puține baze de date oferă acest tip de criptare a datelor.
Important În cazul datelor cu adevărat ascunse, dacă reprezentarea lor brută nu este necesară (adică
nu va fi afișată), ar trebui să se ia în considerare hashingul. Exemplul binecunoscut de hashing este
stocarea hash-ului criptografic al unei parole într-o bază de date, în locul parolei în sine.
Important Funcțiile de parolă oferă o modalitate convenabilă de hashare a datelor sensibile și de a
lucra cu aceste hashuri.
Important password_hash() este folosită pentru a distribui un anumit șir folosind cel mai puternic
algoritm disponibil în prezent și password_verify() verifică dacă parola dată se potrivește cu hash-ul
stocat în baza de date.
<?php
?>
Important Injecția SQL este o tehnică în care un atacator exploatează defecte în codul aplicației
responsabil pentru construirea de interogări SQL dinamice. Atacatorul poate obține acces la
secțiunile privilegiate ale aplicației, poate prelua toate informațiile din baza de date, poate modifica
datele existente sau chiar poate executa comenzi periculoase la nivel de sistem pe gazda bazei de
date. Vulnerabilitatea apare atunci când dezvoltatorii concatenează sau interpolează intrări arbitrare
în instrucțiunile lor SQL.
<?php
?>
Important Utilizatorii obișnuiți dau clic pe linkurile „următorul”, „prev” unde $offset-ul este
codificat în adresa URL. Scriptul se așteaptă ca $offset-ul primit să fie un număr. Cu toate acestea,
ce se întâmplă dacă cineva încearcă să intre adăugând următoarele la adresa URL.
Important O modalitate fezabilă de a obține parole este să ocoliți paginile cu rezultatele căutării.
Singurul lucru pe care trebuie să-l facă atacatorul este să vadă dacă există variabile trimise utilizate
în instrucțiunile SQL care nu sunt gestionate corect. Aceste filtre pot fi setate în mod obișnuit într-o
formă anterioară pentru a personaliza clauzele WHERE, ORDER BY, LIMIT și OFFSET în
instrucțiunile SELECT. Dacă baza de date acceptă construcția UNION, atacatorul poate încerca să
atașeze o interogare întreagă la cea originală pentru a lista parolele dintr-un tabel arbitrar. Se
recomandă insistent să stocați numai coduri hash securizate ale parolelor în loc de parolele în sine.
<?php
$query = "SELECT id, name, inserted, size FROM products
WHERE size = '$size'";
$result = odbc_exec($conn, $query);
?>
Important Dacă un utilizator rău intenționat trimite valoarea „sau uid like”%admin% la $uid pentru
a schimba parola administratorului sau pur și simplu setează $pwd la hehehe', trusted=100,
admin='yes pentru a obține mai multe privilegii, atunci interogarea va fi fi răsucit:
<?php
?>
Important Deși rămâne evident că un atacator trebuie să posede cel puțin cunoștințe despre
arhitectura bazei de date pentru a efectua un atac cu succes, obținerea acestor informații este adesea
foarte simplă. De exemplu, codul poate face parte dintr-un software open-source și poate fi
disponibil public. Aceste informații pot fi, de asemenea, divulgate prin cod sursă închisă - chiar
dacă sunt codificate, ofucate sau compilate - și chiar prin propriul cod prin afișarea mesajelor de
eroare. Alte metode includ utilizarea numelor tipice de tabele și coloane. De exemplu, un formular
de conectare care utilizează un tabel „utilizatori” cu nume de coloană „id”, „nume utilizator” și
„parolă”.
<?php
?>
Important Dacă atacatorul trimite valoarea a%' exec master..xp_cmdshell 'net user test testpass
/ADD' -- la $prod, atunci $query va fi:
<?php
?>
Important MSSQL Server execută instrucțiunile SQL în lot, inclusiv o comandă pentru a adăuga un
nou utilizator la baza de date locală de conturi. Dacă această aplicație rula ca sa și serviciul
MSSQLSERVER rula cu suficiente privilegii, atacatorul ar avea acum un cont cu care să acceseze
această mașină.
Important Modul recomandat de a evita injectarea SQL este legarea tuturor datelor prin instrucțiuni
pregătite. Utilizarea interogărilor parametrizate nu este suficientă pentru a evita complet injecția
SQL, dar este cea mai ușoară și mai sigură modalitate de a furniza instrucțiuni SQL. Toate literalele
de date dinamice din clauzele WHERE, SET și VALUES trebuie înlocuite cu substituenți. Datele
reale vor fi legate în timpul execuției și trimise separat de comanda SQL.
Important Legarea parametrilor poate fi utilizată numai pentru date. Alte părți dinamice ale
interogării SQL trebuie filtrate în funcție de o listă cunoscută de valori permise.
<?php
?>
Important Atacurile cu injecție SQL se bazează în principal pe exploatarea codului, care nu este
scris cu minte securitate. Nu aveți încredere niciodată în nicio intrare, în special din partea
clientului, chiar dacă aceasta provine dintr-o casetă de selectare, un câmp de intrare ascuns sau un
cookie. Primul exemplu arată că o interogare atât de simplă poate provoca dezastre.
Important O strategie de apărare în profunzime implică câteva bune practici de codificare:
• Nu vă conectați niciodată la baza de date ca superutilizator sau ca proprietar al bazei de date.
Utilizați întotdeauna utilizatori personalizați cu privilegii minime.
• Verificați dacă intrarea dată are tipul de date așteptat. PHP are o gamă largă de funcții de
validare a intrărilor, de la cele mai simple găsite în Funcțiile variabile și în Funcțiile tip
caracter (de exemplu, is_numeric(), respectiv ctype_digit()) și până la suportul pentru
expresii regulate compatibile cu Perl.
• Dacă aplicația așteaptă intrare numerică, luați în considerare verificarea datelor cu
ctype_digit(), schimbați tipul în tăcere folosind settype() sau folosiți reprezentarea numerică
prin sprintf().
• Dacă stratul bazei de date nu acceptă variabile de legare, atunci citați fiecare valoare
nenumerică furnizată de utilizator care este transmisă bazei de date cu funcția de evadare a
șirurilor specifice bazei de date (de exemplu, mysql_real_escape_string(),
sqlite_escape_string(), etc.). Funcțiile generice precum addslashes() sunt utile doar într-un
mediu foarte specific (de exemplu, MySQL într-un set de caractere pe un singur octet cu
NO_BACKSLASH_ESCAPES dezactivat), așa că este mai bine să le evitați.
• Nu tipăriți informații specifice bazei de date, în special despre schemă, prin mijloace corecte
sau greșite. Consultați și Funcțiile de raportare a erorilor și de tratare și înregistrare a
erorilor.
Important Pe lângă acestea, beneficiezi de interogări de jurnalizare fie în cadrul scriptului tău, fie
prin baza de date în sine, dacă acceptă înregistrarea în jurnal. Evident, înregistrarea nu poate preveni
orice încercare dăunătoare, dar poate fi util să urmăriți ce aplicație a fost ocolită. Jurnalul nu este
util în sine, ci prin informațiile pe care le conține. Mai multe detalii sunt în general mai bune decât
mai puține.
Important O tactică standard de atac implică profilarea unui sistem prin furnizarea de date
necorespunzătoare și verificarea tipurilor și contextelor erorilor care sunt returnate. Acest lucru
permite cracker-ului sistemului să caute informații despre server, pentru a determina posibilele
puncte slabe. De exemplu, dacă un atacator a adunat informații despre o pagină pe baza unei
trimiteri anterioare a unui formular, poate încerca să înlocuiască variabilele sau să le modifice:
<form method="post" action="attacktarget?username=badfoo&password=badfoo">
<input type="hidden" name="username" value="badfoo" />
<input type="hidden" name="password" value="badfoo" />
</form>
Important Erorile PHP care sunt returnate în mod normal pot fi de mare ajutor pentru un dezvoltator
care încearcă să depaneze un script, indicând lucruri precum funcția sau fișierul care a eșuat, fișierul
PHP în care a eșuat și numărul liniei în care a avut loc eșecul. Acestea sunt toate informațiile care
pot fi exploatate. Nu este neobișnuit ca un dezvoltator php să folosească show_source(),
highlight_string() sau highlight_file() ca măsură de depanare, dar într-un site live, acest lucru poate
expune variabile ascunse, sintaxa neverificată și alte informații periculoase. Mai ales periculoasă
este rularea codului din surse cunoscute cu handlere de depanare încorporate sau utilizarea
tehnicilor obișnuite de depanare. Dacă atacatorul poate determina ce tehnică generală utilizați,
acesta poate încerca să forțeze brute o pagină, trimițând diverse șiruri comune de depanare:
Important O eroare de funcție poate indica dacă un sistem poate rula un anumit motor de bază de
date sau poate oferi indicii despre modul în care o pagină web a fost programată sau proiectată.
Acest lucru permite investigarea mai profundă a porturilor de baze de date deschise sau căutarea
unor erori sau slăbiciuni specifice într-o pagină web. Prin furnizarea diferitelor date proaste, de
exemplu, un atacator poate determina ordinea de autentificare într-un script (din erorile de număr de
linie), precum și să cerceteze exploit-urile care pot fi exploatate în diferite locații din script.
Important O eroare de sistem de fișiere sau generală PHP poate indica ce permisiuni are serverul
web, precum și structura și organizarea fișierelor de pe serverul web. Codul de eroare scris de
dezvoltator poate agrava această problemă, ducând la exploatarea ușoară a informațiilor „ascunse”
anterior.
Important Există trei soluții majore la această problemă. Primul este de a examina toate funcțiile și
de a încerca să compensezi cea mai mare parte a erorilor. Al doilea este de a dezactiva complet
raportarea erorilor pe codul de rulare. Al treilea este să utilizați funcțiile personalizate de gestionare
a erorilor PHP pentru a vă crea propriul handler de erori. În funcție de politica dvs. de securitate,
este posibil să găsiți că toate trei sunt aplicabile situației dvs.
Important O modalitate de a rezolva această problemă din timp este să utilizați propriul
error_reporting() al PHP, pentru a vă ajuta să vă asigurați codul și să găsiți utilizarea variabilelor
care ar putea fi periculoase. Testând codul dvs., înainte de implementare, cu E_ALL, puteți găsi
rapid zone în care variabilele dvs. pot fi deschise otrăvirii sau modificării în alte moduri. Odată ce
sunteți pregătit pentru implementare, ar trebui fie să dezactivați complet raportarea erorilor setând
error_reporting() la 0, fie să dezactivați afișarea erorilor folosind opțiunea [Link] display_errors,
pentru a izola codul de sondare. Dacă alegeți să faceți aceasta din urmă, ar trebui să definiți și calea
către fișierul jurnal folosind directiva error_log ini și să activați log_errors.
<?php
if ($username) { // Not initialized or checked before usage
$good_login = 1;
}
if ($good_login == 1) { // If above test fails, not initialized or checked before usage
readfile ("/highly/sensitive/data/[Link]");
}
?>
<?php
// remove a file from the user's home directory... or maybe
// somebody else's?
unlink ($evil_var);
?>
Important În general, securitatea prin obscuritate este una dintre cele mai slabe forme de securitate.
Dar, în unele cazuri, fiecare pic de securitate suplimentară este de dorit.
Important Câteva tehnici simple pot ajuta la ascunderea PHP-ului, posibil încetinind un atacator
care încearcă să descopere punctele slabe ale sistemului dumneavoastră. Setând expose_php la off
în fișierul [Link], reduceți cantitatea de informații disponibile pentru ei.
Important O altă tactică este să configurați servere web precum apache pentru a analiza diferite
tipuri de fișiere prin PHP, fie cu o directivă .htaccess, fie în fișierul de configurare apache însuși.
Apoi puteți utiliza extensii de fișiere înșelătoare:
34. Caracteristici
Important Este posibil să utilizați funcția header() pentru a trimite un mesaj „Autentificare
necesară” către browser-ul clientului, determinând o fereastră de introducere a numelui de
utilizator/parolă. Odată ce utilizatorul a completat un nume de utilizator și o parolă, URL-ul care
conține scriptul PHP va fi apelat din nou cu variabilele predefinite PHP_AUTH_USER,
PHP_AUTH_PW și AUTH_TYPE setate la numele de utilizator, parola și respectiv tipul de
autentificare. Aceste variabile predefinite se găsesc în tabloul $_SERVER. Numai metoda de
autentificare „de bază” este acceptată.
<?php
if (!isset($_SERVER['PHP_AUTH_USER'])) {
header('WWW-Authenticate: Basic realm="My Realm"');
header('HTTP/1.0 401 Unauthorized');
echo 'Text to send if user hits Cancel button';
exit;
} else {
echo "<p>Hello {$_SERVER['PHP_AUTH_USER']}.</p>";
echo "<p>You entered {$_SERVER['PHP_AUTH_PW']} as your password.</p>";
}
?>
Important În loc să imprimați pur și simplu PHP_AUTH_USER și PHP_AUTH_PW, așa cum s-a
făcut în exemplul de mai sus, poate doriți să verificați validitatea numelui de utilizator și a parolei.
Poate trimițând o interogare la o bază de date sau căutând utilizatorul într-un fișier dbm.
Important Atenție la browserele Internet Explorer cu erori. Par foarte pretențioși în ceea ce privește
ordinea antetelor. Trimiterea antetului WWW-Authenticate înainte de antetul HTTP/1.0 401 pare să
facă truc pentru moment.
<?php
function authenticate() {
header('WWW-Authenticate: Basic realm="Test Authentication System"');
header('HTTP/1.0 401 Unauthorized');
echo "You must enter a valid login ID and password to access this resource\n";
exit;
}
if (!isset($_SERVER['PHP_AUTH_USER']) ||
($_POST['SeenBefore'] == 1 && $_POST['OldAuth'] == $_SERVER['PHP_AUTH_USER'])) {
authenticate();
} else {
echo "<p>Welcome: " . htmlspecialchars($_SERVER['PHP_AUTH_USER']) . "<br />";
echo "Old: " . htmlspecialchars($_REQUEST['OldAuth']);
echo "<form action='' method='post'>\n";
echo "<input type='hidden' name='SeenBefore' value='1' />\n";
echo "<input type='hidden' name='OldAuth' value=\"" .
htmlspecialchars($_SERVER['PHP_AUTH_USER']) . "\" />\n";
echo "<input type='submit' value='Re Authenticate' />\n";
echo "</form></p>\n";
}
?>
Important Acest comportament nu este cerut de standardul de autentificare HTTP Basic, așa că nu
ar trebui să depindeți niciodată de acest lucru. Testarea cu Lynx a arătat că Lynx nu șterge
acreditările de autentificare cu un răspuns de server 401, așa că apăsând înapoi și apoi înainte din
nou va deschide resursa atâta timp cât cerințele de autentificare nu s-au schimbat. Cu toate acestea,
utilizatorul poate apăsa tasta „_” pentru a-și șterge informațiile de autentificare.
Important Pentru ca autentificarea HTTP să funcționeze folosind serverul IIS cu versiunea CGI a
PHP, trebuie să editați configurația IIS „Securitate director”. Faceți clic pe „Editare” și bifați doar
„Acces anonim”, toate celelalte câmpuri ar trebui lăsate nebifate.
Important PHP acceptă în mod transparent cookie-urile HTTP. Cookie-urile sunt un mecanism de
stocare a datelor în browserul de la distanță și, astfel, de urmărire sau de identificare a utilizatorilor
reveniți. Puteți seta cookie-uri folosind funcția setcookie() sau setrawcookie(). Cookie-urile fac
parte din antetul HTTP, așa că setcookie() trebuie apelat înainte ca orice rezultat să fie trimis către
browser. Aceasta este aceeași limitare pe care o are header(). Puteți utiliza funcțiile de buffering de
ieșire pentru a întârzia ieșirea scriptului până când ați decis dacă setați sau nu cookie-uri sau
trimiteți orice antet.
Important Orice cookie-uri trimise către server de la client vor fi incluse automat într-o matrice
auto-globală $_COOKIE dacă variables_order conține „C”. Dacă doriți să atribuiți mai multe valori
unui singur cookie, trebuie doar să adăugați [] la numele cookie-ului.
Important Suportul pentru sesiuni în PHP constă într-o modalitate de a păstra anumite date în
accesările ulterioare. Acest lucru vă permite să creați aplicații mai personalizate și să creșteți
atractivitatea site-ului dvs. web. Toate informațiile sunt în secțiunea Referință sesiune.
<!-- The data encoding type, enctype, MUST be specified as below -->
<form enctype="multipart/form-data" action="__URL__" method="POST">
<!-- MAX_FILE_SIZE must precede the file input field -->
<input type="hidden" name="MAX_FILE_SIZE" value="30000" />
<!-- Name of input element determines name in $_FILES array -->
Send this file: <input name="userfile" type="file" />
<input type="submit" value="Send File" />
</form>
Important Elementul MAX_FILE_SIZE nu poate specifica o dimensiune a fișierului mai mare decât
dimensiunea fișierului care a fost setată în upload_max_filesize din fișierul [Link]. Valoarea
implicită este de 2 megaocteți. Dacă este activată o limită de memorie, poate fi necesară o limită de
memorie mai mare. Asigurați-vă că setați memory_limit suficient de mare. Dacă
max_execution_time este setat prea mic, execuția scriptului poate fi depășită cu valoarea. Asigurați-
vă că setați max_execution_time suficient de mare.
Important Dacă post_max_size este setat prea mic, fișierele mari nu pot fi încărcate. Asigurați-vă că
setați post_max_size suficient de mare. Setarea de configurare max_file_uploads controlează
numărul maxim de fișiere care pot fi încărcate într-o singură solicitare. Dacă sunt încărcate mai
multe fișiere decât limita, atunci $_FILES va opri procesarea fișierelor odată ce limita este atinsă.
De exemplu, dacă max_file_uploads este setat la 10, atunci $_FILES nu va conține niciodată mai
mult de 10 elemente.
Important De asemenea, este posibil să încărcați mai multe fișiere simultan și să aveți informațiile
organizate automat în matrice pentru dvs. Pentru a face acest lucru, trebuie să utilizați aceeași
sintaxă de trimitere a matricei în formularul HTML ca și cu mai multe selectări și casete de
selectare:
Important Când este trimis formularul de mai sus, matricele $_FILES['userfile'], $_FILES['userfile']
['nume'] și $_FILES['userfile']['size'] vor fi inițializate. De exemplu, să presupunem că numele de
fișiere /home/test/[Link] și /home/test/[Link] sunt trimise. În acest caz, $_FILES['userfile']
['name'][0] va conține valoarea [Link], iar $_FILES['userfile']['name'][1] va conține valoarea
[Link] . În mod similar, $_FILES['userfile']['size'][0] ar conține dimensiunea fișierului
[Link] și așa mai departe. $_FILES['userfile']['name'][0], $_FILES['userfile']['tmp_name'][0],
$_FILES['userfile']['size'][0] și $ _FILES['userfile']['type'][0] sunt de asemenea setate.
Important PHP oferă suport pentru metoda HTTP PUT folosită de unii clienți pentru a stoca fișiere
pe un server. Solicitările PUT sunt mult mai simple decât încărcarea unui fișier folosind solicitări
POST și arată cam așa:
PUT /path/[Link] HTTP/1.1
Important Acest lucru ar însemna în mod normal că clientul de la distanță ar dori să salveze
conținutul care urmează ca: /cale/numefiș[Link] în arborele dvs. web. În mod evident, nu este o
idee bună ca Apache sau PHP să permită tuturor să suprascrie automat orice fișier din arborele web.
Deci, pentru a gestiona o astfel de solicitare, trebuie mai întâi să spuneți serverului dvs. web că
doriți ca un anumit script PHP să gestioneze cererea. În Apache faci asta cu directiva Script. Poate fi
plasat aproape oriunde în fișierul dvs. de configurare Apache. Un loc obișnuit este în interiorul unui
bloc <Directory> sau poate într-un bloc <VirtualHost>. O linie ca aceasta ar face treaba:
Important Atâta timp cât allow_url_fopen este activat în [Link], puteți utiliza URL-uri HTTP și
FTP cu majoritatea funcțiilor care iau un nume de fișier ca parametru. În plus, adresele URL pot fi
utilizate cu instrucțiunile include, include_once, require și require_once (allow_url_include trebuie
să fie activat pentru acestea). Consultați Protocoale și Wrapper-uri acceptate pentru mai multe
informații despre protocoalele acceptate de PHP.
Important De exemplu, puteți utiliza acest lucru pentru a deschide un fișier pe un server web la
distanță, a analiza rezultatul pentru datele dorite și apoi a utiliza acele date într-o interogare de bază
de date sau pur și simplu pentru a-l scoate într-un stil care se potrivește cu restul site-ului dvs. .
<?php
$file = fopen ("[Link] "r");
if (!$file) {
echo "<p>Unable to open remote file.\n";
exit;
}
while (!feof ($file)) {
$line = fgets ($file, 1024);
/* This only works if the title and its tags are on one line */
if (preg_match ("@\<title\>(.*)\</title\>@i", $line, $out)) {
$title = $out[1];
break;
}
}
fclose($file);
?>
Important De asemenea, puteți scrie în fișiere de pe un server FTP (cu condiția să fiți conectat ca
utilizator cu drepturi de acces corecte). Puteți crea fișiere noi numai folosind această metodă; dacă
încercați să suprascrieți un fișier care există deja, apelul fopen() va eșua.
Important Pentru a vă conecta ca alt utilizator decât „anonim”, trebuie să specificați numele de
utilizator (și eventual parola) în adresa URL, cum ar fi
„[Link] (Puteți folosi același tip de sintaxă pentru a
accesa fișierele prin HTTP atunci când necesită autentificare de bază.)
<?php
$file = fopen ("[Link] "w");
if (!$file) {
echo "<p>Unable to open remote file for writing.\n";
exit;
}
/* Write the data here. */
fwrite ($file, $_SERVER['HTTP_USER_AGENT'] . "\n");
fclose ($file);
?>
Important Conexiunile persistente în PHP rămân deschise după finalizarea unui script, fiind
reutilizate pentru cereri ulterioare dacă se potrivesc cu aceleași credențiale (gazdă, utilizator,
parolă). Ele sunt utile pentru eficiență, reducând costurile de conectare repetată la un server SQL,
dar nu adaugă funcționalitate nouă față de conexiunile nepersistente.
Important Acestea pot avea dezavantaje, cum ar fi:
• Depășirea limitelor de conexiuni simultane ale bazei de date.
• Probleme cauzate de blocări de tabele sau tranzacții nefinalizate, ce pot afecta scripturile
ulterioare.
Important Este recomandat să evitați utilizarea lor în scenarii cu tranzacții sau blocări frecvente și
să implementați funcții de curățare cu register_shutdown_function(). Conexiunile persistente
îmbunătățesc eficiența, dar trebuie utilizate cu prudență pentru a evita blocajele și suprasolicitarea
serverului SQL.
Important CLI SAPI este utilizat pentru dezvoltarea aplicațiilor shell cu PHP și este diferit de alte
SAPI-uri, cum ar fi CGI, deși împărtășesc unele comportamente. Este activat implicit cu --enable-
cli (poate fi dezactivat cu --disable-cli).
Instalare și configurare:
• Binarele CLI și CGI sunt generate implicit la compilare, fiind plasate în directoarele
sapi/cli/php și sapi/cgi/php-cgi.
• În timpul instalării, binarul copiat depinde de configurația aleasă. De exemplu:
• Cu --with-apxs, CLI este copiat ca {PREFIX}/bin/php.
• Pentru a instala doar CLI, folosiți make install-cli după make install.
• Utilizați --disable-cgi pentru a exclude CGI.
Platforma Windows:
• CLI este distribuit ca [Link], CGI ca [Link], iar [Link] este o variantă CLI fără
consolă, activată cu --enable-cli-win32.
Determinarea SAPI-ului:
• Comanda php -v indică dacă PHP rulează ca CLI sau CGI.
• Puteți verifica și cu funcția php_sapi_name() sau constanta PHP_SAPI.
Alte resurse:
Pe Unix, comanda man php oferă documentație pentru CLI.
default
Directive Comment
value
Valoarea implicită la false, deoarece poate fi destul de greu să
html_errors false citiți mesajele de eroare în mediul shell atunci când sunt
aglomerate cu etichete neinterpretate.
Într-un mediu shell, este de obicei de dorit ca rezultatul, cum ar
fi de tipărire, ecou și prieteni, să fie afișat imediat și să nu fie
implicit_flush true păstrat într-un buffer. Cu toate acestea, este încă posibil să
utilizați tamponarea de ieșire pentru a amâna sau manipula
ieșirea standard.
PHP într-un mediu shell tinde să fie folosit pentru o gamă mult
0 mai diversificată de scopuri decât scripturile tipice bazate pe
max_execution_time
(unlimited) Web și, deoarece acestea pot fi de lungă durată, timpul maxim
de execuție este setat la nelimitat.
register_argc_argv true Setarea la true înseamnă că scripturile executate prin intermediul
au întotdeauna acces la argc (numărul de argumente transmise
aplicației) și argv (matricea argumentelor reale).
Warning
default
Directive Comment
value
Prezența $argv sau $_SERVER['argv'] nu este o indicație de
încredere că un script este rulat din linia de comandă, deoarece
acestea pot fi setate în alte contexte când register_argc_argv este
activat. Valoarea returnată de php_sapi_name() ar trebui
verificată în schimb.
<?php
<?php
// Our simple test application named [Link]
echo getcwd(), "\n";
?>
$ php -q another_directory/[Link]
/tmp/another_directory
$ php -f another_directory/[Link]
/tmp
Important Există trei moduri diferite de a furniza CLI SAPI cu cod PHP pentru a fi executat:
1. Spuneți PHP să execute un anumit fișier.
$ php my_script.php
$ php -f my_script.php
<?php
$stdin = fopen('php://stdin', 'r');
?>
STDIN
If you want to read single line from stdin, you can use
<?php
$line = trim(fgets(STDIN)); // reads one line from STDIN
fscanf(STDIN, "%d\n", $number); // reads number from STDIN
?>
An already opened stream to stdout. This saves opening it with
STDOUT <?php
$stdout = fopen('php://stdout', 'w');
?>
An already opened stream to stderr. This saves opening it with
STDERR <?php
$stderr = fopen('php://stderr', 'w');
?>
Important CLI SAPI oferă un shell interactiv folosind opțiunea -a dacă PHP este compilat cu
opțiunea --with-readline. Începând cu PHP 7.1.0, shell-ul interactiv este disponibil și pe Windows,
dacă extensia readline este activată. Folosind shell-ul interactiv, puteți să tastați cod PHP și să îl
executați direct.
$ php -a
Interactive shell
Important Shell-ul interactiv oferă, de asemenea, completarea filelor pentru funcții, constante, nume
de clase, variabile, apeluri de metode statice și constante de clasă.
Important Când există o singură finalizare posibilă, apăsând Tab o dată va finaliza restul pe aceeași
linie:
php > strpt[TAB]ime(
Important Completarea va funcționa și pentru numele care au fost definite în timpul sesiunii
interactive shell curente:
Important Shell-ul interactiv stochează istoricul dvs., care poate fi accesat folosind tastele sus și jos.
Istoricul este salvat în fișierul ~/.php_history. Începând cu PHP 8.4.0, calea către fișierul istoric
poate fi setată folosind variabila de mediu PHP_HISTFILE.
Important CLI SAPI oferă setările [Link] [Link] și [Link]. Setarea [Link] permite unui
program extern (cum ar fi less) să acționeze ca un pager pentru ieșire în loc să fie afișat direct pe
ecran. Setarea [Link] face posibilă schimbarea promptului php >.
Sequence Description
\e Folosit pentru adăugarea de culori la prompt. Un exemplu ar putea fi \e[032m\v \
e[031m\b \e[34m\> \e[0m
\v Versiunea PHP.
\b Indică în ce bloc se află PHP. De exemplu /* pentru a indica faptul că se află într-un
comentariu cu mai multe rânduri. Domeniul exterior este notat cu php.
Indică caracterul prompt. În mod implicit, acesta este >, dar se schimbă atunci când
\> shell-ul se află în interiorul unui bloc sau șir neterminat. Caracterele posibile sunt: ' " { (
>
Important Dacă extensia readline nu este disponibilă, înainte de PHP 8.1.0, invocarea CLI SAPI cu
opțiunea -a a furnizat modul interactiv. În acest mod, se presupune că va fi dat un script PHP
complet prin STDIN, iar după terminarea cu CTRL +D (POSIX) sau CTRL +Z urmat de +ENTER
(Windows), acest script este evaluat. Acest lucru este practic același cu invocarea CLI SAPI fără
opțiunea -a.
Important Serverul web integrat în CLI SAPI este conceput pentru dezvoltare, testare și
demonstrații în medii controlate, dar nu este potrivit pentru utilizare în rețele publice.
Caracteristici principale:
• Rulează un singur proces și un singur thread (blocarea unei solicitări blochează întregul
server).
• Servirea fișierelor:
• Utilizează directorul de lucru curent sau poate fi configurat cu -t pentru o rădăcină
specifică a documentelor.
• Caută și returnează fișierele [Link] sau [Link]. Dacă nu sunt găsite,
returnează codul 404.
• Suport pentru scripturi router:
• Un fișier PHP specificat la pornire este executat pentru fiecare solicitare. Dacă
scriptul returnează false, serverul servește resursa solicitată; altfel, răspunsul
scriptului este trimis în browser.
• Include suport pentru tipuri MIME standard (ex. .html, .css, .png, .mp4).
Funcționalități suplimentare:
• Din PHP 7.4.0, serverul poate forka mai mulți lucrători pentru testarea solicitărilor
simultane. Configurați variabila de mediu PHP_CLI_SERVER_WORKERS înainte de
pornire.
$ cd ~/public_html
$ php -S localhost:8000
Output:
PHP 5.4.0 Development Server started at Thu Jul 21 10:43:28 2011
Listening on localhost:8000
Document root is /home/me/public_html
Press Ctrl-C to quit
$ cd ~/public_html
$ php -S localhost:8000 -t foo/
Output:
PHP 5.4.0 Development Server started at Thu Jul 21 10:50:26 2011
Listening on localhost:8000
Document root is /home/me/public_html/foo
Press Ctrl-C to quit
Important O variabilă PHP este stocată într-un container numit „zval”. Un container zval conține, pe
lângă tipul și valoarea variabilei, doi biți suplimentari de informații. Prima se numește „is_ref” și
este o valoare booleană care indică dacă variabila face sau nu parte dintr-un „mult de referință”. Cu
acest bit, motorul PHP știe să facă diferența între variabilele normale și referințe. Deoarece PHP
permite referințe utilizator-teren, așa cum sunt create de operatorul &, un container zval are și un
mecanism intern de numărare a referințelor pentru a optimiza utilizarea memoriei. Această a doua
informație suplimentară, numită „refcount”, conține câte nume de variabile (numite și simboluri)
indică acest container zval. Toate simbolurile sunt stocate într-un tabel de simboluri, dintre care
există unul pentru fiecare domeniu. Există un domeniu de aplicare pentru scriptul principal (adică
cel solicitat prin browser), precum și unul pentru fiecare funcție sau metodă.
<?php
$a = "new string";
?>
Important În acest caz, noul nume de simbol, a, este creat în domeniul curent și este creat un nou
container de variabile cu tipul șir și valoarea șir nou. Bitul „is_ref” este setat în mod implicit la false
deoarece nu a fost creată nicio referință utilizator-teren. „Refcount” este setat la 1 deoarece există
un singur simbol care folosește acest container variabil. Rețineți că referințele (adică „is_ref” este
adevărat) cu „refcount” 1, sunt tratate ca și cum nu ar fi referințe (adică, deoarece „is_ref” a fost
fals). Dacă aveți » Xdebug instalat, puteți afișa aceste informații apelând xdebug_debug_zval().
<?php
$a = "new string";
xdebug_debug_zval('a');
?>
Output: a: (refcount=1, is_ref=0)='new string'
<?php
$a = "new string";
$b = $a;
xdebug_debug_zval( 'a' );
?>
Output: a: (refcount=2, is_ref=0)='new string'
Important Refcount este 2 aici, deoarece același container variabil este legat atât cu a cât și cu b.
PHP este suficient de inteligent pentru a nu copia containerul variabil real atunci când nu este
necesar. Containerele variabile sunt distruse atunci când „refcount” ajunge la zero. „Refcount”
scade cu unu atunci când orice simbol legat de containerul variabil părăsește domeniul de aplicare
(de exemplu, când funcția se termină) sau când un simbol este nealocat (de exemplu, prin apelarea
unset()). Următorul exemplu arată acest lucru:
<?php
$a = "new string";
$c = $b = $a;
xdebug_debug_zval( 'a' );
$b = 42;
xdebug_debug_zval( 'a' );
unset( $c );
xdebug_debug_zval( 'a' );
?>
Output:
a: (refcount=3, is_ref=0)='new string'
a: (refcount=2, is_ref=0)='new string'
a: (refcount=1, is_ref=0)='new string'
Important Conexiunile sunt stabilite prin crearea de instanțe ale clasei de bază PDO. Nu contează ce
driver vrei să folosești; folosești întotdeauna numele clasei PDO. Constructorul acceptă parametri
pentru specificarea sursei bazei de date (cunoscută ca DSN) și opțional pentru numele de utilizator
și parola (dacă există).
<?php
$dbh = new PDO('mysql:host=localhost;dbname=test', $user, $pass);
?>
Important Dacă există erori de conexiune, va fi aruncat un obiect PDOException. Puteți prinde
excepția dacă doriți să gestionați condiția de eroare sau puteți opta să o lăsați pentru un handler
global de excepție al aplicației pe care l-ați configurat prin set_exception_handler().
<?php
try {
$dbh = new PDO('mysql:host=localhost;dbname=test', $user, $pass);
} catch (PDOException $e) {
// attempt to retry the connection after some timeout for example
}
Important După conectarea cu succes la baza de date, o instanță a clasei PDO este returnată la
scriptul dumneavoastră. Conexiunea rămâne activă pe toată durata de viață a acelui obiect PDO.
Pentru a închide conexiunea, trebuie să distrugeți obiectul, asigurându-vă că toate referințele rămase
la acesta sunt șterse - faceți acest lucru atribuind null variabilei care deține obiectul. Dacă nu faceți
acest lucru în mod explicit, PHP va închide automat conexiunea când scriptul dvs. se termină.
<?php
$dbh = new PDO('mysql:host=localhost;dbname=test', $user, $pass);
// use the connection here
$sth = $dbh->query('SELECT * FROM foo');
<?php
try {
$dbh = new PDO('odbc:SAMPLE', 'db2inst1', 'ibmdb2',
array(PDO::ATTR_PERSISTENT => true));
echo "Connected\n";
} catch (Exception $e) {
die("Unable to connect: " . $e->getMessage());
}
try {
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$dbh->beginTransaction();
$dbh->exec("insert into staff (id, first, last) values (23, 'Joe', 'Bloggs')");
$dbh->exec("insert into salarychange (id, amount, changedate)
values (23, 50000, NOW())");
$dbh->commit();
} catch (Exception $e) {
$dbh->rollBack();
echo "Failed: " . $e->getMessage();}
?>
Important Declarațiile pregătite sunt șabloane SQL compilate care pot fi reutilizate cu parametri
diferiți, oferind două avantaje principale:
1. Analiza, compilarea și optimizarea interogării se face o singură dată, economisind resurse și
accelerând execuția, mai ales pentru interogări complexe repetate.
2. Parametrii sunt automat securizați împotriva injecției SQL, deoarece șoferul bazei de date
gestionează citarea acestora.
PDO emulează declarațiile pregătite pentru driverele care nu le suportă, permițând o paradigmă
unificată de acces la date indiferent de baza de date utilizată.
<?php
$stmt = $dbh->prepare("INSERT INTO REGISTRY (name, value) VALUES (:name, :value)");
$stmt->bindParam(':name', $name);
$stmt->bindParam(':value', $value);
Important Acest exemplu preia date pe baza unei valori cheie furnizate de un formular. Intrarea
utilizatorului este cotată automat, deci nu există riscul unui atac de injecție SQL.
<?php
$stmt = $dbh->prepare("SELECT * FROM REGISTRY where name = ?");
$stmt->execute([$_GET['name']]);
foreach ($stmt as $row) {
print_r($row);
}
?>
Important Dacă driverul bazei de date îl acceptă, o aplicație poate lega și parametrii pentru ieșire,
precum și pentru intrare. Parametrii de ieșire sunt utilizați de obicei pentru a prelua valori din
procedurile stocate. Parametrii de ieșire sunt puțin mai complex de utilizat decât parametrii de
intrare, deoarece un dezvoltator trebuie să știe cât de mare ar putea fi un anumit parametru atunci
când îl leagă. Dacă valoarea se dovedește a fi mai mare decât dimensiunea sugerată de ei, apare o
eroare.
<?php
$stmt = $dbh->prepare("CALL sp_returns_string(?)");
$stmt->bindParam(1, $return_value, PDO::PARAM_STR, 4000);
// call the stored procedure
$stmt->execute();
<?php
$dsn = 'mysql:dbname=testdb;host=[Link]';
$user = 'dbuser';
$password = 'dbpass';
// This will cause PDO to throw a PDOException (when the table doesn't exist)
$dbh->query("SELECT wrongcolumn FROM wrongtable");
Output: Fatal error: Uncaught PDOException: SQLSTATE[42S02]: Base table or view not found:
1146
<?php
$dsn = 'mysql:dbname=test;host=[Link]';
$user = 'googleguy';
$password = 'googleguy';
// This will cause PDO to throw an error of level E_WARNING instead of an exception (when the
table doesn't exist)
$dbh->query("SELECT wrongcolumn FROM wrongtable");
Important La un moment dat în aplicație, s-ar putea să descoperiți că trebuie să stocați date „mari”
în baza de date. Mare înseamnă de obicei „aproximativ 4 kb sau mai mult”, deși unele baze de date
pot gestiona cu plăcere până la 32 kb înainte ca datele să devină „mari”. Obiectele mari pot fi de
natură textuală sau binară. PDO vă permite să lucrați cu acest tip mare de date utilizând codul de tip
PDO::PARAM_LOB în apelurile dvs. PDOStatement::bindParam() sau
PDOStatement::bindColumn(). PDO::PARAM_LOB îi spune lui PDO să mapeze datele ca flux,
astfel încât să le puteți manipula folosind API-ul PHP Streams.
Important Acest exemplu leagă LOB-ul în variabila numită $lob și apoi îl trimite la browser
folosind fpassthru(). Deoarece LOB este reprezentat ca un flux, funcții precum fgets(), fread() și
stream_get_contents() pot fi utilizate pe acesta.
<?php
$db = new PDO('odbc:SAMPLE', 'db2inst1', 'ibmdb2');
$stmt = $db->prepare("select contenttype, imagedata from images where id=?");
$stmt->execute(array($_GET['id']));
$stmt->bindColumn(1, $type, PDO::PARAM_STR, 256);
$stmt->bindColumn(2, $lob, PDO::PARAM_LOB);
$stmt->fetch(PDO::FETCH_BOUND);
header("Content-Type: $type");
fpassthru($lob);
?>
Important Acest exemplu deschide un fișier și transmite mânerul fișierului către PDO pentru a-l
insera ca LOB. PDO va face tot posibilul pentru a aduce conținutul fișierului în baza de date în cel
mai eficient mod posibil.
<?php
$db = new PDO('odbc:SAMPLE', 'db2inst1', 'ibmdb2');
$stmt = $db->prepare("insert into images (id, contenttype, imagedata) values (?, ?, ?)");
$id = get_new_id(); // some function to allocate a new ID
$stmt->bindParam(1, $id);
$stmt->bindParam(2, $_FILES['file']['type']);
$stmt->bindParam(3, $fp, PDO::PARAM_LOB);
$db->beginTransaction();
$stmt->execute();
$db->commit();
?>
class PDO {
/* Constants */
public const int PARAM_NULL;
public const int PARAM_BOOL = 5;
public const int PARAM_INT = 1;
public const int PARAM_STR = 2;
public const int PARAM_LOB = 3;
public const int PARAM_STMT = 4;
public const int PARAM_INPUT_OUTPUT;
public const int PARAM_STR_NATL;
public const int PARAM_STR_CHAR;
public const int PARAM_EVT_ALLOC;
public const int PARAM_EVT_FREE;
public const int PARAM_EVT_EXEC_PRE;
public const int PARAM_EVT_EXEC_POST;
public const int PARAM_EVT_FETCH_PRE;
public const int PARAM_EVT_FETCH_POST;
public const int PARAM_EVT_NORMALIZE;
public const int FETCH_DEFAULT;
public const int FETCH_LAZY;
public const int FETCH_ASSOC;
public const int FETCH_NUM;
public const int FETCH_BOTH;
public const int FETCH_OBJ;
public const int FETCH_BOUND;
public const int FETCH_COLUMN;
public const int FETCH_CLASS;
public const int FETCH_INTO;
public const int FETCH_FUNC;
public const int FETCH_GROUP;
public const int FETCH_UNIQUE;
public const int FETCH_KEY_PAIR;
public const int FETCH_CLASSTYPE;
public const int FETCH_SERIALIZE;
public const int FETCH_PROPS_LATE;
public const int FETCH_NAMED;
public const int ATTR_AUTOCOMMIT;
public const int ATTR_PREFETCH;
public const int ATTR_TIMEOUT;
public const int ATTR_ERRMODE;
public const int ATTR_SERVER_VERSION;
public const int ATTR_CLIENT_VERSION;
public const int ATTR_SERVER_INFO;
public const int ATTR_CONNECTION_STATUS;
public const int ATTR_CASE;
public const int ATTR_CURSOR_NAME;
public const int ATTR_CURSOR;
public const int ATTR_ORACLE_NULLS;
public const int ATTR_PERSISTENT;
public const int ATTR_STATEMENT_CLASS;
public const int ATTR_FETCH_TABLE_NAMES;
public const int ATTR_FETCH_CATALOG_NAMES;
public const int ATTR_DRIVER_NAME;
public const int ATTR_STRINGIFY_FETCHES;
public const int ATTR_MAX_COLUMN_LEN;
public const int ATTR_EMULATE_PREPARES;
public const int ATTR_DEFAULT_FETCH_MODE;
public const int ATTR_DEFAULT_STR_PARAM;
public const int ERRMODE_SILENT;
public const int ERRMODE_WARNING;
public const int ERRMODE_EXCEPTION;
public const int CASE_NATURAL;
public const int CASE_LOWER;
public const int CASE_UPPER;
public const int NULL_NATURAL;
public const int NULL_EMPTY_STRING;
public const int NULL_TO_STRING;
public const string ERR_NONE;
public const int FETCH_ORI_NEXT;
public const int FETCH_ORI_PRIOR;
public const int FETCH_ORI_FIRST;
public const int FETCH_ORI_LAST;
public const int FETCH_ORI_ABS;
public const int FETCH_ORI_REL;
public const int CURSOR_FWDONLY;
public const int CURSOR_SCROLL;
/* Methods */
public __construct(
string $dsn,
?string $username = null,
#[\SensitiveParameter] ?string $password = null,
?array $options = null
)
public beginTransaction(): bool
public commit(): bool
public static connect(
string $dsn,
?string $username = null,
#[\SensitiveParameter] ?string $password = null,
?array $options = null
): static
public errorCode(): ?string
public errorInfo(): array
public exec(string $statement): int|false
public getAttribute(int $attribute): mixed
public static getAvailableDrivers(): array
public inTransaction(): bool
public lastInsertId(?string $name = null): string|false
public prepare(string $query, array $options = []): PDOStatement|false
public query(string $query, ?int $fetchMode = null): PDOStatement|false
public query(string $query, ?int $fetchMode = PDO::FETCH_COLUMN, int
$colno): PDOStatement|false
public query(
string $query,
?int $fetchMode = PDO::FETCH_CLASS,
string $classname,
array $constructorArgs
): PDOStatement|false
public query(string $query, ?int $fetchMode = PDO::FETCH_INTO, object
$object): PDOStatement|false
public quote(string $string, int $type = PDO::PARAM_STR): string|false
public rollBack(): bool
public setAttribute(int $attribute, mixed $value): bool
}
PDO::beginTransaction — Inițiază o tranzacție
PDO::commit — Commite o tranzacție
PDO::connect — Conectați-vă la o bază de date și returnați o subclasă PDO pentru driverele care o
acceptă
PDO::__construct — Creează o instanță PDO reprezentând o conexiune la o bază de date
PDO::errorCode — Preluați SQLSTATE asociat cu ultima operațiune pe handle-ul bazei de date
PDO::errorInfo — Preluați informații de eroare extinse asociate cu ultima operațiune pe handle-ul
bazei de date
PDO::exec — Execută o instrucțiune SQL și returnează numărul de rânduri afectate
PDO::getAttribute — Preluați un atribut de conexiune la baza de date
PDO::getAvailableDrivers — Returnează o serie de drivere PDO disponibile
PDO::inTransaction — Verifică dacă este în interiorul unei tranzacții
PDO::lastInsertId — Returnează ID-ul ultimei valori de rând sau secvență inserată
PDO::prepare — Pregătește o instrucțiune pentru execuție și returnează un obiect instrucțiune
PDO::query — Pregătește și execută o instrucțiune SQL fără substituenți
PDO::quote — Indică un șir de caractere pentru a fi utilizat într-o interogare
PDO::rollBack — Derulează înapoi o tranzacție
PDO::setAttribute — Setați un atribut
/* Methods */
public bindColumn(
string|int $column,
mixed &$var,
int $type = PDO::PARAM_STR,
int $maxLength = 0,
mixed $driverOptions = null
): bool
public bindParam(
string|int $param,
mixed &$var,
int $type = PDO::PARAM_STR,
int $maxLength = 0,
mixed $driverOptions = null
): bool
public bindValue(string|int $param, mixed $value, int $type = PDO::PARAM_STR):
bool
public closeCursor(): bool
public columnCount(): int
public debugDumpParams(): ?bool
public errorCode(): ?string
public errorInfo(): array
public execute(?array $params = null): bool
public fetch(int $mode = PDO::FETCH_DEFAULT, int $cursorOrientation =
PDO::FETCH_ORI_NEXT, int $cursorOffset = 0): mixed
public fetchAll(int $mode = PDO::FETCH_DEFAULT): array
public fetchAll(int $mode = PDO::FETCH_COLUMN, int $column): array
public fetchAll(int $mode = PDO::FETCH_CLASS, string $class, ?array
$constructorArgs): array
public fetchAll(int $mode = PDO::FETCH_FUNC, callable $callback): array
public fetchColumn(int $column = 0): mixed
public fetchObject(?string $class = "stdClass", array $constructorArgs = []): object|
false
public getAttribute(int $name): mixed
public getColumnMeta(int $column): array|false
public getIterator(): Iterator
public nextRowset(): bool
public rowCount(): int
public setAttribute(int $attribute, mixed $value): bool
public setFetchMode(int $mode): bool
public setFetchMode(int $mode = PDO::FETCH_COLUMN, int $colno): bool
public setFetchMode(int $mode = PDO::FETCH_CLASS, string $class, ?array
$constructorArgs = null): bool
public setFetchMode(int $mode = PDO::FETCH_INTO, object $object): bool
}
36. MYSQL
Important Există mai multe API-uri PHP pentru accesarea bazei de date MySQL. Utilizatorii pot
alege între extensiile mysqli sau PDO_MySQL.
Important Această secțiune explică opțiunile pentru conectarea aplicațiilor PHP la MySQL și
clarifică termeni esențiali:
1. API (Interfață de Programare a Aplicației): Definește clasele, funcțiile și metodele pentru
comunicarea cu baza de date. API-urile pot fi procedurale (apelare funcții) sau orientate pe
obiecte (instanțiere clase și apelare metode), preferându-se abordarea orientată pe obiecte
pentru organizare mai bună.
2. Conector: Software care permite aplicației PHP să comunice cu serverul MySQL, asigurând
conexiunea și gestionarea comunicării, inclusiv cu alte biblioteci intermediare.
3. Driver: Software specific pentru comunicarea cu un anumit tip de bază de date. De
exemplu, driverul PDO MySQL facilitează interacțiunea între stratul PDO și serverul
MySQL. Termenii „conector” și „driver” sunt uneori folosiți interschimbabil, dar un driver
reprezintă partea specifică bazei de date a unui conector.
4. Extensie: În PHP, extensiile sunt componente care extind funcționalitatea de bază a
limbajului. De exemplu, extensia mysqli expune un API pentru MySQL, iar extensia PDO
MySQL furnizează o interfață către stratul PDO, fără a expune direct un API
programatorului.
Termenii API, conector, driver și extensie au roluri distincte, fiind esențiali pentru dezvoltarea
aplicațiilor conectate la baze de date MySQL.
Important PHP oferă diferite API-uri pentru conectarea la MySQL. Mai jos arătăm API-urile
furnizate de extensiile mysqli și PDO. Fiecare fragment de cod creează o conexiune la un server
MySQL care rulează pe „[Link]” folosind numele de utilizator „utilizator” și parola „parolă”.
Și se execută o interogare pentru a saluta utilizatorul.
// PDO
$pdo = new PDO('mysql:host=[Link];dbname=database', 'user', 'password');
$statement = $pdo->query("SELECT 'Hello, dear MySQL user!' AS _message FROM DUAL");
$row = $statement->fetch(PDO::FETCH_ASSOC);
echo htmlentities($row['_message']);
// PDO
$pdo = new PDO('mysql:host=[Link];dbname=database', 'user', 'password');
$statement = $pdo->prepare("SELECT District FROM City WHERE Name=?");
$statement->execute(["Amersfoort"]);
$row = $statement->fetch(PDO::FETCH_ASSOC);
echo htmlentities($row['District']);
Important Extensiile PHP mysqli și PDO_MySQL sunt pachete ușoare deasupra unei biblioteci
client C. Extensiile pot folosi fie biblioteca mysqlnd, fie biblioteca libmysqlclient. Alegerea unei
biblioteci este o decizie de compilare.
Important Biblioteca mysqlnd face parte din distribuția PHP. Oferă funcții precum conexiuni leneșe
și stocarea în cache a interogărilor, caracteristici care nu sunt disponibile cu libmysqlclient, așa că
este foarte recomandată utilizarea bibliotecii încorporate mysqlnd. Consultați documentația
mysqlnd pentru detalii suplimentare și o listă de caracteristici și funcționalități pe care le oferă.
Important Setul de caractere trebuie înțeles și definit, deoarece are un efect asupra fiecărei acțiuni și
include implicații de securitate. De exemplu, mecanismul de evadare (de exemplu,
mysqli_real_escape_string() pentru mysqli și PDO::quote() pentru PDO_MySQL) va adera la
această setare. Este important să realizați că aceste funcții nu vor folosi setul de caractere care este
definit cu o interogare, deci, de exemplu, următoarele nu vor avea efect asupra lor:
if (!$mysqli->set_charset('utf8mb4')) {
printf("Error loading character set utf8mb4: %s\n", $mysqli->error);
exit;
}
Acest text oferă o introducere în opțiunile de conectare a aplicațiilor PHP la o bază de date MySQL,
discutând concepte precum API-uri, conectori, drivere și extensii:
1. API-uri: Definează funcții, clase și metode necesare pentru comunicarea aplicației PHP cu
bazele de date. Pot fi procedurale (funcții apelate direct) sau orientate pe obiecte (clase și
metode). API-urile orientate pe obiecte sunt preferate pentru cod mai organizat.
2. Conectori: Software care permite aplicației să se conecteze la MySQL, gestionând
comunicarea între PHP și serverul bazei de date.
3. Drivere: Module software specializate pentru interacțiunea cu un tip specific de server de
baze de date. De exemplu, driverul PDO MySQL permite stratului PDO să comunice cu
MySQL.
4. Extensii: Module PHP care extind funcționalitatea de bază, expunând API-uri sau funcții
specifice pentru MySQL, precum mysqli sau PDO MySQL.
5. API-uri MySQL principale în PHP:
• Extensia mysqli: Include interfață orientată pe obiecte și procedurală, suport pentru
declarații pregătite, tranzacții, declarații multiple și depanare.
• PDO (PHP Data Objects): Strat de abstractizare pentru baze de date care suportă
mai multe tipuri de drivere.
Extensia mysqli este recomandată pentru utilizarea funcțiilor avansate disponibile în MySQL 4.1.3
și versiunile ulterioare.
Important Extensia mysqli are o interfață duală. Suportă paradigma de programare procedurală și
orientată pe obiecte.
Important Utilizatorii care migrează de la vechea extensie mysql pot prefera interfața procedurală.
Interfața procedurală este similară cu cea a vechii extensii mysql. În multe cazuri, numele funcțiilor
diferă doar prin prefix. Unele funcții mysqli iau un mâner de conexiune ca prim argument, în timp
ce funcțiile de potrivire din vechea interfață mysql îl iau ca un ultim argument opțional.
$result = mysqli_query($mysqli, "SELECT 'A world full of ' AS _msg FROM DUAL");
$row = mysqli_fetch_assoc($result);
echo $row['_msg'];
Important Serverul MySQL acceptă utilizarea diferitelor straturi de transport pentru conexiuni.
Conexiunile folosesc TCP/IP, socketuri de domeniu Unix sau conducte numite Windows.
Important Numele de gazdă localhost are o semnificație specială. Este legat de utilizarea socket-
urilor de domeniu Unix. Pentru a deschide o conexiune TCP/IP la localhost, trebuie folosit
[Link] în locul numelui de gazdă localhost.
<?php
$mysqli = new mysqli("localhost", "user", "password", "database");
echo $mysqli->host_info . "\n";
$mysqli = new mysqli("[Link]", "user", "password", "database", 3306);
echo $mysqli->host_info . "\n";
<?php
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new mysqli("[Link]", "user", "password", "database");
<?php
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new mysqli("[Link]", "user", "password", "database");
Output:
Reverse order...
id = 3
id = 2
id = 1
Result set order...
id = 1
id = 2
id = 3
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new mysqli("[Link]", "user", "password", "database");
Output:
id = 1 (string)
label = a (string)
Important Execuția instrucțiunii pregătite constă din două etape: pregătire și execuție. În etapa de
pregătire, un șablon de declarație este trimis la serverul bazei de date. Serverul efectuează o
verificare de sintaxă și inițializează resursele interne ale serverului pentru utilizare ulterioară.
<?php
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new mysqli("[Link]", "user", "password", "database");
/* Non-prepared statement */
$mysqli->query("DROP TABLE IF EXISTS test");
$mysqli->query("CREATE TABLE test(id INT, label TEXT)");
$stmt->execute();
Important O instrucțiune pregătită poate fi executată în mod repetat. La fiecare execuție, valoarea
curentă a variabilei legate este evaluată și trimisă la server. Declarația nu este analizată din nou.
Șablonul de declarație nu este transferat din nou pe server.
<?php
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new mysqli("[Link]", "user", "password", "database");
/* Non-prepared statement */
$mysqli->query("DROP TABLE IF EXISTS test");
$mysqli->query("CREATE TABLE test(id INT, label TEXT)");
$data = [
1 => 'PHP',
2 => 'Java',
3 => 'C++'
];
foreach ($data as $id => $label) {
$stmt->execute();
}
Important Declarațiile pregătite consumă resurse serverului și trebuie închise explicit după
utilizare. Dacă nu sunt închise, ele se închid automat când handle-ul este eliberat. În unele cazuri,
utilizarea instrucțiunilor pregătite poate fi mai puțin eficientă, deoarece execuția lor o singură dată
presupune mai multe interacțiuni client-server decât o instrucțiune nepregătită. De asemenea, pentru
operațiuni de tip INSERT, se recomandă utilizarea sintaxei MySQL multi-INSERT, care necesită
mai puține călătorii client-server.
<?php
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new mysqli("[Link]", "user", "password", "database");
<?php
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new mysqli("[Link]", "user", "password", "database");
/* Non-prepared statement */
$mysqli->query("DROP TABLE IF EXISTS test");
$mysqli->query("CREATE TABLE test(id INT, label TEXT)");
$mysqli->query("INSERT INTO test(id, label) VALUES (1, 'PHP')");
Important Rezultatele din instrucțiunile pregătite pot fi fie preluate prin legarea variabilelor de
ieșire, fie prin solicitarea unui obiect mysqli_result. Variabilele de ieșire trebuie să fie legate după
executarea instrucțiunii. O variabilă trebuie să fie legată pentru fiecare coloană a setului de rezultate
de instrucțiuni.
<?php
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new mysqli("[Link]", "user", "password", "database");
/* Non-prepared statement */
$mysqli->query("DROP TABLE IF EXISTS test");
$mysqli->query("CREATE TABLE test(id INT, label TEXT)");
$mysqli->query("INSERT INTO test(id, label) VALUES (1, 'PHP')");
$stmt->bind_result($out_id, $out_label);
while ($stmt->fetch()) {
printf("id = %s (%s), label = %s (%s)\n", $out_id, gettype($out_id), $out_label,
gettype($out_label));
}
Important Procedurile stocate pot avea parametri IN, INOUT și OUT, în funcție de versiunea
MySQL. Interfața mysqli nu are o noțiune specială pentru diferitele tipuri de parametri.
<?php
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new mysqli("[Link]", "user", "password", "database");
$mysqli->query("CALL p(1)");
var_dump($result->fetch_assoc());
Important Procedurile stocate pot returna seturi de rezultate. Seturile de rezultate returnate dintr-o
procedură stocată nu pot fi preluate corect folosind mysqli::query(). Funcția mysqli::query()
combină execuția instrucțiunilor și preluarea primului set de rezultate într-un set de rezultate
tamponat, dacă există. Cu toate acestea, există seturi suplimentare de rezultate de procedură stocată
ascunse utilizatorului, care fac ca mysqli::query() să nu returneze seturile de rezultate așteptate de
utilizator.
Important Seturile de rezultate returnate dintr-o procedură stocată sunt preluate folosind
mysqli::real_query() sau mysqli::multi_query(). Ambele funcții permit preluarea oricărui număr de
seturi de rezultate returnate de o instrucțiune, cum ar fi CALL. Eșecul de a prelua toate seturile de
rezultate returnate de o procedură stocată provoacă o eroare.
<?php
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new mysqli("[Link]", "user", "password", "database");
$mysqli->query("DROP TABLE IF EXISTS test");
$mysqli->query("CREATE TABLE test(id INT)");
$mysqli->query("INSERT INTO test(id) VALUES (1), (2), (3)");
do {
if ($result = $mysqli->store_result()) {
printf("---\n");
var_dump($result->fetch_all());
$result->free();
}
} while ($mysqli->next_result());
Important MySQL permite executarea mai multor instrucțiuni într-un singur șir, folosind
mysqli::multi_query(). Instrucțiunile sunt separate prin punct și virgulă, iar toate seturile de
rezultate trebuie preluate. Se pot combina instrucțiuni care returnează seturi de rezultate cu cele care
nu, într-o singură instrucțiune multiplă.
<?php
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new mysqli("[Link]", "user", "password", "database");
$mysqli->multi_query($sql);
do {
if ($result = $mysqli->store_result()) {
var_dump($result->fetch_all(MYSQLI_ASSOC));
$result->free();
}
} while ($mysqli->next_result());
Output:
array(1) {
[0]=>
array(1) {
["_num"]=>
string(1) "0"
}
}
array(1) {
[0]=>
array(1) {
["_num"]=>
string(1) "1"
}
}
PHP Fatal error: Uncaught mysqli_sql_exception: You have an error in your SQL syntax;
check the manual that corresponds to your MySQL server version for the right syntax to
use near 'DROP TABLE [Link]' at line 1
Important Serverul MySQL acceptă tranzacții în funcție de motorul de stocare utilizat. Începând cu
MySQL 5.5, motorul de stocare implicit este InnoDB. InnoDB are suport complet pentru tranzacții
ACID. Tranzacțiile pot fi controlate folosind apeluri SQL sau API. Este recomandat să utilizați
apeluri API pentru activarea și dezactivarea modului de autocommit și pentru comiterea și anularea
tranzacțiilor.
<?php
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new mysqli("[Link]", "user", "password", "database");
/* Won't be monitored and recognized by the replication and the load balancing plugin */
$mysqli->query('SET AUTOCOMMIT = 0');
<?php
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new mysqli("[Link]", "user", "password", "database");
$mysqli->autocommit(false);
Important Un set de rezultate MySQL conține metadate. Metadatele descriu coloanele găsite în
setul de rezultate. Toate metadatele trimise de MySQL sunt accesibile prin interfața mysqli.
Extensia nu efectuează modificări sau modificări neglijabile ale informațiilor pe care le primește.
Diferențele dintre versiunile de server MySQL nu sunt aliniate. Metadatele este accesul prin
interfața mysqli_result.
<?php
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new mysqli("[Link]", "user", "password", "database");
Important Metadatele seturilor de rezultate create folosind instrucțiuni pregătite sunt accesate în
același mod. Un handle adecvat pentru mysqli_result este returnat de
mysqli_stmt::result_metadata().
<?php
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new mysqli("[Link]", "user", "password", "database");
Important Conexiunile persistente permit reutilizarea unei conexiuni între client și bază de date,
reducând costurile de creare a unor noi conexiuni. În mysqli, conexiunile persistente sunt deschise
prin adăugarea unui "p:" la numele gazdei. Totuși, aceste conexiuni pot lăsa stări imprevizibile dacă
un client nu le închide corespunzător. Mysqli gestionează curățarea automată a conexiunilor
persistente, incluzând rollback, închiderea tabelelor temporare, deblocarea meselor și resetarea
variabilelor de sesiune. Aceasta asigură că conexiunile sunt într-o stare curată la reutilizare. Totuși,
curățarea automată poate afecta performanța, iar aceasta poate fi dezactivată printr-o opțiune de
compilare a PHP.
class mysqli {
/* Properties */
public readonly int|string $affected_rows;
public readonly string $client_info;
public readonly int $client_version;
public readonly int $connect_errno;
public readonly ?string $connect_error;
public readonly int $errno;
public readonly string $error;
public readonly array $error_list;
public readonly int $field_count;
public readonly string $host_info;
public readonly ?string $info;
public readonly int|string $insert_id;
public readonly string $server_info;
public readonly int $server_version;
public readonly string $sqlstate;
public readonly int $protocol_version;
public readonly int $thread_id;
public readonly int $warning_count;
/* Methods */
public __construct(
?string $hostname = null,
?string $username = null,
#[\SensitiveParameter] ?string $password = null,
?string $database = null,
?int $port = null,
?string $socket = null
)
public autocommit(bool $enable): bool
public begin_transaction(int $flags = 0, ?string $name = null): bool
public change_user(string $username, #[\SensitiveParameter] string $password, ?string
$database): bool
public character_set_name(): string
public close(): true
public commit(int $flags = 0, ?string $name = null): bool
public connect(
?string $hostname = null,
?string $username = null,
#[\SensitiveParameter] ?string $password = null,
?string $database = null,
?int $port = null,
?string $socket = null
): bool
public debug(string $options): true
public dump_debug_info(): bool
public execute_query(string $query, ?array $params = null): mysqli_result|bool
public get_charset(): ?object
#[\Deprecated]
public get_client_info(): string
public get_connection_stats(): array
public get_server_info(): string
public get_warnings(): mysqli_warning|false
#[\Deprecated]
public init(): ?bool
#[\Deprecated]
public kill(int $process_id): bool
public more_results(): bool
public multi_query(string $query): bool
public next_result(): bool
public options(int $option, string|int $value): bool
#[\Deprecated]
public ping(): bool
public static poll(
?array &$read,
?array &$error,
array &$reject,
int $seconds,
int $microseconds = 0
): int|false
public prepare(string $query): mysqli_stmt|false
public query(string $query, int $result_mode = MYSQLI_STORE_RESULT):
mysqli_result|bool
public real_connect(
?string $hostname = null,
?string $username = null,
#[\SensitiveParameter] ?string $password = null,
?string $database = null,
?int $port = null,
?string $socket = null,
int $flags = 0
): bool
public real_escape_string(string $string): string
public real_query(string $query): bool
public reap_async_query(): mysqli_result|bool
#[\Deprecated]
public refresh(int $flags): bool
public release_savepoint(string $name): bool
public rollback(int $flags = 0, ?string $name = null): bool
public savepoint(string $name): bool
public select_db(string $database): bool
public set_charset(string $charset): bool
public ssl_set(
?string $key,
?string $certificate,
?string $ca_certificate,
?string $ca_path,
?string $cipher_algos
): true
public stat(): string|false
public stmt_init(): mysqli_stmt|false
public store_result(int $mode = 0): mysqli_result|false
public thread_safe(): bool
public use_result(): mysqli_result|false
}
/* Methods */
public __construct(mysqli $mysql, ?string $query = null)
public attr_get(int $attribute): int
public attr_set(int $attribute, int $value): bool
public bind_param(string $types, mixed &$var, mixed &...$vars): bool
public bind_result(mixed &$var, mixed &...$vars): bool
public close(): true
public data_seek(int $offset): void
public execute(?array $params = null): bool
public fetch(): ?bool
public free_result(): void
public get_result(): mysqli_result|false
public get_warnings(): mysqli_warning|false
public more_results(): bool
public next_result(): bool
public num_rows(): int|string
public prepare(string $query): bool
public reset(): bool
public result_metadata(): mysqli_result|false
public send_long_data(int $param_num, string $data): bool
public store_result(): bool
}
/* Methods */
public __construct(mysqli $mysql, int $result_mode = MYSQLI_STORE_RESULT)
public data_seek(int $offset): bool
public fetch_all(int $mode = MYSQLI_NUM): array
public fetch_array(int $mode = MYSQLI_BOTH): array|null|false
public fetch_assoc(): array|null|false
public fetch_column(int $column = 0): null|int|float|string|false
public fetch_field(): object|false
public fetch_field_direct(int $index): object|false
public fetch_fields(): array
public fetch_object(string $class = "stdClass", array $constructor_args = []):
object|null|false
public fetch_row(): array|null|false
public field_seek(int $index): true
public free(): void
public close(): void
public free_result(): void
public getIterator(): Iterator
}
/* Methods */
private __construct()
public next(): bool
}
/* Methods */
public getSqlState(): string
/* Inherited methods */
public Exception::__construct(string $message = "", int $code = 0, ?Throwable
$previous = null)
final public Exception::getMessage(): string
final public Exception::getPrevious(): ?Throwable
final public Exception::getCode(): int
final public Exception::getFile(): string
final public Exception::getLine(): int
final public Exception::getTrace(): array
final public Exception::getTraceAsString(): string
public Exception::__toString(): string
private Exception::__clone(): void
}