|
Asteptand sa expiri
Poate ai auzit de termenul GIGO inainte. Daca nu, afla ca vine de la Garbage In, Garbage Out si reprezinta un fapt elementar ce tine de programare: daca iti „hranesti” programul cu ceva rau, mai mult ca sigur vei primi un rezultat la fel de rau. Indiferent de cum privesti situatia, un rezultat prost nu e un lucru bun pentru un programator care vrea sa se faca remarcat.
Daca ai impresia ca exagerez, lasa-ma sa iti dau un exemplu simplu. Gandeste-te la un calculator de imprumuturi online care permite user-ului sa introduca suma de imprumutat dorita, termenul de finantare si rata dobanzii. Sa presupunem ca aplicatia nu include si o optiune care sa verifice erorile si ca user-ul decide sa introduca magica cifra 0 in campul Termen.
Iti poti inchipui rezultatul. Dupa cateva calcule interne aplicatia va incerca sa imparta intreaga suma platita cu zero. Nu are rost sa discutam multitudinea de mesaje de eroare care vor urma, dar trebuie sa mentionez ca ele ar fi putut fi evitate daca developer-ul s-ar fi gandit sa verifice datele de intrare inainte de efectua calculele.
Care este morala acestei povesti? Daca vrei cu adevarat sa folosesti PHP pentru web development, unul din lucrurile cele mai importate pe care trebuie sa le inveti este cum sa validezi informatiile introduse de utilizator si cum sa manevrezi posibilele date eronate. O astfel de verificare a input-ului reprezinta unul din cele mai importante sisteme de protectie pe care un developer le poate instala intr-o aplicatie, iar un esec in aceasta privinta poate genera probleme serioase sau poate chiar sa cauzeze intreruperea aplicatiei in momentul in care gaseste date nule sau corupte.
In urmatoarele paragrafe iti voi arata cateva trucuri simple pentru a valida datele utilizator, pentru a „prinde” informatiile „rele” inainte sa iti corupa calculele si bazele de date si pentru a oferi notificari utilizatorilor intr-o maniera simpla si inteligibila.
Un vas gol
Acest tutorial presupune faptul ca datele ce trebuiesc validate sunt transmise prin intermediul unui formular. Aceasta nu este singura cale prin care un script PHP poate primi date de la utilizator, dar este cea mai comuna metoda.
O practica comuna este folosirea limbajelor scripting client cum ar fi JavaScript sau VBScript pentru validarea formularelor. Totusi, acest tip de validare nu prezinta siguranta maxima pentru ca nu ai control asupra clientului (browserul), iar daca un user inchide JavaScript-ul din browser-ul sau, toate eforturile tale de a te asigua ca el nu introduce informatii invalide devin inutile. De aceea, majoritatea developerilor experimentati folosesc atat validari client-side cat si server-side. Validarile server-side implica verificarea valorilor transmise serverului printr-un script PHP, precum si luarea de masuri corespunzatoare cand input-ul este incorect.
Sa incepem cu cea mai des intalnita eroare de input: un camp obligatoriu caruia ii lipseste valoarea. Arunca o privire la urmatorul exemplu:
<html>
<head></head>
<body>
<?php
if (!isset($_POST['submit'])) {
?>
<form action = '<?php $_SERVER['PHP_SELF'] ?>' method = 'post'>
Ce tip de umplutura de sandwich ai dori ?
<br />
<input type = 'text' name = 'filling'>
<br />
<input type = 'submit' name = 'submit' value = 'Salveaza'>
</form>
<?php
}
else {
$host = 'localhost';
$user = 'user';
$pass = 'secret';
$db = 'sandwiches';
$filling = mysql_escape_string($_POST['filling']);
$connection = mysql_connect($host, $user, $pass) or die('Nu ma pot conecta la MySQL!');
mysql_select_db($db) or die('Nu pot selecta baza de date!');
$query = 'INSERT INTO orders (filling) VALUES ("$filling")';
$result = mysql_query($query) or die("Eroare in query: $query. ".mysql_error());
mysql_close($connection);
echo "Sandvisul tau cu {$_POST['filling']} este pregatit!";
}
?>
</body>
</html>
Din exemplul de mai sus se poate observa ca transmiterea acestuia fara a introduce nici o informatie va rezulta intr-un inregistrarea goala ce va fi adaugata in baza de date (presupunand ca nu avem constrangeri NOT NULL pentru tabelul orders). Pentru a evita acest lucru, e important sa verifici ca formularul contine date valide si abia apoi poti executa instructiunea INSERT:
<html>
<head></head>
<body>
<?php
if (!isset($_POST['submit'])) {
?>
<form action = '<?php $_SERVER['PHP_SELF'] ?>' method = 'post'>
Ce tip de umplutura de sandwich ai dori ?
<br />
<input type = 'text' name = 'filling'>
<br />
<input type = 'submit' name = 'submit' value = 'Salveaza'>
</form>
<?php
}
else {
if (!isset($_POST['filling']) || trim($_POST['filling']) == '') {
die("EROARE: Nu poti avea un sandwich fara umplutura!");
}
else {
$filling = mysql_escape_string(trim($_POST['filling']));
}
$host = 'localhost';
$user = 'user';
$pass = 'secret';
$db = 'sandwiches';
$connection = mysql_connect($host, $user, $pass) or die('Nu ma pot conecta la MySQL!');
mysql_select_db($db) or die('Nu pot selecta baza de date!');
$query = 'INSERT INTO orders (filling) VALUES ("$filling")';
$result = mysql_query($query) or die("Error in query: $query. ".mysql_error());
mysql_close($connection);
echo " Sandvisul tau cu {$_POST['filling']} este pregatit!";
}
?>
</body>
</html>
Verificarea erorii in acest caz e simpla si logica: functia trim() e folosita pentru a sterge spatiile de la inceputul si sfarsitul datelor introduse, valoare returnata fiind apoi comparata cu un sir gol. Daca avem egalitate, atunci campul a fost introdus gol, iar script-ul afiseaza un mesaj de eroare inainte ca MySQL sa apara in peisaj.
O greseala comuna, mai ales printre incepatori, este inlocuirea combinatiei isset() si trim() cu functia PHP empty() ce iti spune daca o variabila e goala. Aceasta nu e o idee buna de obicei, pentru ca empty() are un defect : va returna true chiar daca o variabila contine cifra 0. Urmatorul exemplu ilustreaza acest lucru:
<?php
$data = '';
echo empty($data) ? "$data e gol" : "$data nu e gol";
echo "<br />\n";
$data = '1';
echo empty($data) ? "$data e gol" : "$data nu e gol";
echo "<br />\n";
$data = '0';
echo empty($data) ? "$data e gol" : "$data nu e gol";
?>
Asadar, daca formular tau nu trebuie sa contina un camp cu date non-goale si non-zero, empty() reprezinta o varianta buna pentru a-l valida. Dar daca sirul de valori valide pentru campul tau include cifra 0, ramai la combinatia isset() si trim().
Nu e genul meu
Acum stii cum sa „prinzi” cea mai simpla dintre erori – datele care lipsesc – si cum sa opresti procesarea script-ului inainte sa se produca vreo paguba. Ce faci insa daca datele sunt prezente, dar tipul lor si marimea e gresita? Testul care verifica valorile lipsa nu se va declansa, dar calculele si baza de date tot pot fi afectate. In mod evident, trebuie sa adaugi verificari suplimentare care sa verifice tipul informatiei introduse de utilizator. Iata un exemplu care ilustreaza acest lucru:
<html>
<head></head>
<body>
<?php
if (!isset($_POST['submit'])) {
?>
<form action = '<?php $_SERVER['PHP_SELF']?>' method = 'post'>
Cate sandwich-uri doresti ? (min 1, max 9)
<br />
<input type = 'text' name = 'quantity'>
<br />
<input type = 'submit' name = 'submit' value = 'Salveaza'>
</form>
<?php
}
else {
if (!isset($_POST['quantity']) || trim($_POST['quantity']) == '') {
die ("EROARE : Nu le putem face daca nu spui cate vrei!");
}
if (!is_numeric($_POST['quantity'])) {
die ("EROARE: Ce ai spus nu este un numar!");
}
if (intval($_POST['quantity']) != $_POST['quantity']) {
die ("EROARE: Nu pot face jumatati, sferturi sau treimi... mi-as pierde slujba!");
}
if (($_POST['quantity'] < 1) || ($_POST['quantity'] > 9)) {
die ("EROARE: Nu pot sa fac decat intre 1 si 9 sandwich-uri pe comanda!");
}
echo "Iti pregatesc {$_POST['quantity']} sandwich-uri. Sper ca le poti manca pe toate!";
}
?>
</body>
</html>
Observa ca din momentul in care am stabilit ca input-ul contine cateva informatii, am adaugat o serie de teste pentru a ma asigura ca tipul acestuia este corect si ca indeplineste constrangerile. In primul rand, am verificat daca valoarea e numerica cu ajutorul functiei is_numeric() ce testeaza un sir de caractere pentru a vedea daca reprezinta un numar.
Presupunand ca e vorba de un numar, trebuie sa te asiguri ca este un intreg intre 1-9. Pentru a afla daca e un numar intreg am folosit functia intval() pentru a extrage partea intreaga din valoare si am testat-o pentru a vedea daca este egala cu numarul propriu-zis. Valorile float ( cum ar fi 2.5) vor pica acest test; valorile intregi il vor trece. Testul final inainte de a avea unda verde este sa vezi daca se incadreaza undeva intre 1 si 9. Acest lucru se poate realiza usor cu cateva teste de inegalitate.
|