vineri, 8 aprilie 2011

PHP OOP - Utilizare clase si obiecte (1) (Part31)

O abordare importanta a activitatii de programare, care a devenit populara dupa 1990, este orientarea spre obiecte, OOP (Object Oriented Programming).
Orientarea spre obiecte a fost creata ca o modalitate de organizare mai eficienta a unor programe de simulare complexe, metoda care s-a dovedit utila in scrierea si utilizarea programelor interactive.
Principiul de baza al programarii orientate spre obiecte îl reprezinta incapsularea datelor, gruparea lor in module.
Un program care nu este orientat spre obiecte este organizat ca un set de functii si un set de variabile globale utilizate de acele functii. Orice functie poate opera folosind orice variabila globala.
Un program orientat spre obiecte combina una sau mai multe functii create de programator într-o unitate, cunoscuta sub numele de "clasa".
Programele orientate spre obiecte pot fi mai usor de înteles si modificat, deoarece interactiunile între clasele unui program orientat spre obiecte sunt relativ reduse ca numar. Astfel, un programator poate studia si întelege un program orientat spre obiecte abordând fiecare clasa în parte, nu toate clasele deodata.
Pe langa modatitatea de programare liniara (procedurala), invatata pana acum, PHP va permite sa creati si sa folositi clase si obiecte, respectiv proprietatile si metodele asociate acestora.
Aceasta lectie prezinta conceptele de baza ale orientarii spre obiecte in PHP, într-un mod general.

1. Clasele

O clasa este de fapt o structura care contine variabile (membrii) si functii (metode), Metodele sunt operatiile pe care membrii clasei le pot efectua.
Membrii si metodele declarate intr-o clasa apartin clasei respective si se acceseaza specificand numele clasei.
O clasa poate include o metoda speciala, numita "metoda constructor" sau "constructor". Aceasta este o functiei din clasa care are acelasi nume cu denumirea clasei.

Diferenta între clasa si obiect este importanta. Daca o clasa poate fi asimilata unui tip de date, un obiect poate fi echivalat cu o variabila sau cu o valoare avand un anumit tip de date. Practic, o clasa este o "fabrica" de obiecte, care produce obiecte cu aceeasi structura, avand proprietati si metode identice.



- Pe langa incapsularea datelor, o alta caracteristica importanta al POD este mostenirea
Mostenirea consta in aceea ca putem declara anumite clase ca fiind derivate din alte clase de baza. In cele mai multe situatii clasa derivata (numita si clasa copil) extinde, primeste functionalitatile clasei de baza (numita si clasa parinte). In acest fel se reduce foarte mult cantitatea de cod necesara.

2. Alcatuirea si instantierea unei clase

Definirea unei clase incepe cu un cuvantul cheie "class". Variabilele sau membrii clasei se specifica folosind cuvantul "var". Functiile sau metodele unei clase se declara specificand cuvantul "function" . Structura general de alcatuire a unei clase este urmatoarea:

class nume_claca {
    var membru1;
    var membru2;
    .................
    function nume_functie(); {
        function metoda1();
        function metoda2();
        .................
    }
}

Pentru a intelege mai bine modalitatea de definire a unei clase în PHP, consideram urmatorul exemplu in care alcatuim o clasa simpla denumita "ContBanca":

<?php

// Definirea clasei

class ContBanca {
    var $sold = 0;             // Membru clasei
    // Definirea primei metode a clasei
    function c_depozit($suma) {
        $this->sold = $this->sold + $suma;
    }
    // Definirea celei dea doua metode a clasei
    function obtine_sold() {
        return $this->sold;
    }
}
?>

- Clasa "ContBanca" are un singr membru, "$sold" si doua metode: "c_depozit()" si "obtine_sold()".
- Membru (variabila) "$sold" este definita de o instructiune "var". Clasa "ContBanca" atribuie variabilei "$sold" valoarea initiala zero ( Nu este necesara atribuirea unei valori initiale unei proprietati, dar astfel programele devin mai simple si mai usor de citit).
- Cele doua metodele (functii) sunt definite folosind cuvântul cheie "function". (Diferenta dintre metode si functii este legata de amplasarea acestora, pentru a se face deosebirea; metodele sunt definite în interiorul claselor, în timp ce functiile sunt definite în exteriorul acestora).
Un aspect interesant al metodelor consta în modalitatea în care acestea obtin accesul la variabila, folosend sintaxa "$this->" (aceasta are o semnificatie similara cu a pronumelui posesiv din limba româna (al meu)). Când o metoda face o referire de forma "$this->sold", se considera ca face trimitere la membru "$sold" a obiectului curent, aici efectul este similar cu acela al expresiei "sold-ul mea".

Instantierea unei clase se face prin operatorul "new", avand urmatoarea forma generala:

$nume_variabila = new nume_clasa();

Variabila "$nume_variabila" contine o referinta la clasa "nume_clasa". In continuare se apeleaza metodele clasei respective, asta se face prin operatorul de referinta "->" ca mai jos:

$nume_variabila->Metoda1();

Variabila apeleaza metoda cu numele "Medoda1()", care apartine clasei "nume_clasa".
Stergerea instantelor unei clase se face simplu prin apelarea functiei:

unset($nume_variabila)

Dupa aceasta stergere, orice apel de genul "$nume_variabila->Metoda1();" va fi semnalat ca eroare.
Iata un exemplu concret de Instantiere in care folosim clasa "ContBanca", definita mai sus.

<?php
// Definirea clasei

class ContBanca {
    var $sold = 0;             // Membru clasei

    // Definirea primei metode a clasei
    function c_depozit($suma) {
        $this->sold = $this->sold + $suma;
    }
    // Definirea celei dea doua metode a clasei
    function obtine_sold() {
        return $this->sold;
    }
}
// Instantierea clasei (setarea obiectului)
$cont = new ContBanca();
// Apelarea metodelor din obiectul setat
$cont->c_depozit(90);
echo "<br /> Soldul este : ". $cont->obtine_sold();
?>

- Prima instructiune, dupa crearea clasei, seteaza (instantiaza) un obiect "ContBanca" folosind operatorul "new" si stocheaza referinta la acest obiect în variabila "$cont", care va fi utilizata ulterior pentru a obtine acces la metodele obiectului.
- A doua instructiune foloseste variabila "$cont", (care face referire la obiectul "ContBanca" creat de prima instructiune). Operatorul "->" arata ca PHP trebuie sa apeleze metoda "c_depozit()" asupra obiectului desemnat de variabila "$cont".
Astfel, prin a doua instructiune se va executa metoda "c_depozit()", careia ii este transmis argumentul 90. Dupa cum este definita, metoda "c_depozit", aceasta incrementeaza valoarea membrului "$sold" cu valoarea argumentului din paranteze, "$suma" (adica aici 90).
- Cea de-a treia instructiune invoca metoda "obtine_sold()", care returneaza valoarea membrului "$sold". Instructiunea afiseaza valoarea returnata prin intermediul unei instructiuni "echo", afisand "Soldul este : 90".

3. Definirea unei metode constructor

Metoda constructor este o functie din interiorul clasei care are aceeasi denumire cu numele clasei.
Pentru ca o clasa sa fie eficienta, ar trebui sa aibe mai multi membri.
De exemplu, clasa "ContBanca", pe langa membrul "$sold", ar necesita membrii care sa defineasca numele si id-ul posesorului.
Iata o noua versiune a clasei, care include trei membri si o metoda constructor:

<?php
// Definirea clasei

class ContBanca {
    // Membri clasei
    var $cont_id;
    var $nume_posesor;
    var $sold = 0;

    // Definirea metodei constructor
    function ContBanca($id, $nume, $suma) {
        $this->cont_id = $id;
        $this->nume_posesor = $nume;
        $this->sold = $suma;
    }

    // Definirea celei dea doua metode a clasei
    function c_depozit($suma) {
        $this->sold = $this->sold + $suma;
        return $this->sold;
    }
}
?>

- Constructorul este "function ContBanca()", asa cum se observa, are acelasi nume ca al clasei. Deosebirea fata de ceilalti membri este ca la invocarea operatorului "new", pentru setarea obiectului, PHP va apela automat si aceasta functie din clasa.
Argumentele constructorului sunt folosite pentru a stabili valorile initiale ale membrilor noului obiect, "$id", "$nume" si "$suma".
Iata cum s-ar putea folosi noua clasa, adaugam codul de mai jos dupa datele de definire a clasei, pe care nu le mai repetam:

<?php
// Aici sunt adaugate datele pentru definirea clasei

// Setarea (instantierea) obiectului "ContBanca"
$cont = new ContBanca(8, "Plo Mar", 100);
echo "<br /> Contul $cont->cont_id apartine lui $cont->nume_posesor";
// Apelarea celei dea doua metode
$cont->c_depozit(90);
echo "<br /> Soldul este $cont->sold";
?>

- Instructiunea "$cont = new ContBanca(8, "Plo Mar", 100);" obtine accesul la membrii obiectului în mod direct, prin "constructorul" care are acelasi nume cu al clasei, transferandu-le valorile "8", "Plo Mar" si "100"
- Datele de iesire ale acestui exemplu sunt urmatoarele:


Contul 8 apartine lui Plo Mar
Soldul este 190

4. Utilizarea mostenirii

Asa cum s-a explicat la inceput, un avantaj al programarii orientate spre obiecte este facilitatea cunoscuta sub numele de mostenire.
Pentru a intelege cum functioneaza, iata un exemplu care prezinta modul de derivare a unei clase "ContCurent" din clasa de baza "ContBancar", definita anterior si pe care o salvam intr-un fisier extern "contbanca.php":

<?php
include("contbanca.php");             // Include clasa parinte (sau poate fi scrisa aici)

// Definirea clasei copil
class ContCurent extends ContBanca {
    var $cec_nr;             // Membru clasei copil

    // Metoda constructor a clasei copil
    function ContCurent($id, $nume, $suma, $cecnr) {
        $this->cont_id = $id;
        $this->nume_posesor = $nume;
        $this->sold = $suma;
        $this->cec_nr = $cecnr;
    }

    // A doua metoda a clasei copil
    function primire_cec($cecnr, $suma) {
        $this->sold = $this->sold - $suma;
    }

    // A treia metoda a clasei copil
    function obtine_sold() {
        return $this->sold;
    }
}
?>

- Exemplul foloseste o instructiune "include" pentru a obtine accesul la definitia clasei "ContBanca". (sau puteti scrie direct aceasta clasa in locul "include").
- Cuvântul cheie "extends" stabileste identitatea clasei "ContCurent" ca fiind derivata (copil) a clasei "ContBanca".
- Clasa derivata defineste un membru, "$cec_nr", de asemenea, defineste un constructor si alte doua metode, "primire_cec()" si "obtine_sold()".
Important este faptul ca aceasta clasa mai include si membrii definiti în clasa de baza (parinte): "$cont_id", "$nume_posesor" si "$sold", in plus va mosteni si metoda "c_depozit()". Constructorul clasei copil atribuie valori membrilor mosteniti, dar si membrilor noi definiti în clasa copil.
Clasa derivata (copil) se foloseste ca orice clasa.
Dupa ce adaugam datele de definire a claselor parinte si copil prezentate mai sus, creem un obiect "ContCurent" care face referire la aceasta clasa copil, ca in exempll urmator.

<?php
// Aici sunt adaugate datele pentru clasa parinte si clasa derivata (copil)
// Setarea (instantierea) obiectului "ContCurent"
$cont = new ContCurent(8, "Plo Mar", 100, 11);
$cont->primire_cec(11, 150);             // Apeleaza metoda creata in clasa copil
$cont->c_depozit(250);             // Apeleaza metoda mostenita
echo "<br /> Soldul este". $cont->obtine_sold();
?>
- Observati ca metoda "c_depozit()", care este definita în clasa de baza, este invocata ca si cum ar fi fost definita în clasa derivata; metodele mostenite se apeleaza la fel ca cele create in clasa copil.
- Dupa ce veti include in acelasi fisier php clasa parinte, clasa copil si instantierea de mai sus, rezultatul afisat dupa executia acestui fisier va fi: Soldul este 200".

PHP Optiuni pentru utilizarea caracterelor speciale (Part30)

1. Ghilimelele magice
Apar situatii cand dorim sa introducem ghilimele in interiorul unui textintr-o baza de date, dar SQL nu permite înglobarea unor ghilimele simple în interiorul valorii unui sir. Probleme similare pot aparea la introducerea unui text ce contine caractere speciale precum: \ + * ? ^ ( $ ), si care sunt trimise la un script PHP.
PHP include functii si facilitati pentru rezolvarea acestor situatii.
Fisierul de initializare PHP ("php.ini") contine optiuni de configurare care determina modul în care PHP controleaza datele provenite de la o sursa externa, cum sunt un formular HTML, un fisier text sau o baza de date.
Optiunea magic_quotes_gpc specifica modul în care PHP manipuleaza operatiile HTTP: GET si POST, precum si operatiile dintre PHP si MySQL sau cele cu variabile cookie. Daca optiunea este activata (ON), PHP prefixeaza automat ghilimelele simple, ghilimelele duble, caracterele backslash si caracterele nule (caracterele a caror valoare ASCII este 0) care apar într-o variabila HTTP, cu un caracter backslash (\).
Optiunea magic_quotes_runtime specifica modul în care PHP manipuleaza datele de origine externa. Daca aceasta optiune este activata, PHP ignora automat ghilimelele simple si duble care apar în datele externe, inclusiv datele din formularele HTML, din fisiere si baze de date.
Daca este activata optiunea magic_quotes_sybase, aceasta modifica efectul optiunilor magic_quotes_gpc si magic_quotes_runtime, astfel încât un caracter de tip ghilimele simple sa fie prefixat cu un alt caracter de tip ghilimele simple, nu cu un backslas.
Dar, în general, accesul la aceste comenzi din fisierul "php.ini" il are administratorul de sistem iar utilizatorii obisnuiti nu trebuie sa aiba posibilitatea de a aduce modificari în fisier. Astfel, pot fi folosite functii PHP care sa seteze aceste optiuni pe durata scriptului respectiv.
Functiile get_magic_quotes_gpc() si get_magic_quotes_runtime() returneaza fiecare valoarea optiunii PHP corespunzatoare setate in fisierul "php.ini". Mai mult, puteti folosi functia set_magic_quotes_runtime() pentru a specifica valoarea optiunii magic_quotes_runtime pentru restul duratei scriptului PHP curent.
De exemplu, pentru a dezactiva optiunea magic_quotes_runtime, invocati functia

set_magic_quotes_runtime(0);

Alternativ, pentru a activa aceasta optiune intr-un script, folositi functia

set_magic_quotes_runtime(1);

2. Conversia caracterelor speciale si anularea acesteia

PHP poate converti ghilimelele simple si duble dintr-un sir, folosind functia addslashes().
Daca PHP nu este configurat astfel încât sa converteasca aceste caractere din sir în mod automat, atunci trebuie sa executati manual aceasta modificare. Pur si simplu utilizati functia addslashes(), transferându-i ca argument sirul text. Aceasta adauga caracterul backslash "\" pentru conversia caracterelor de tip ghilimele simple, ghilimele duble, backslash si caractere nule

Aceasta conversie nu trebuie confundata cu o alta, si anume conversia de tip, care foloseste caracterul backslash (\).
Conversia mentionata în acest capitol consta din modificarea semnificatiei anumitor caractere, pentru a preveni o interpretare eronata a acestora de catre programele specializate, precum MySQL. Din acest motiv, toate conversiile mentionate în acest capitol fac referire la modificarea semnificatiei unor caractere, nu la conversiile de tip.

De exemplu, pentru a converti continutul sirului "$text" si a plasa rezultatul în variabila "$modificat", invocati functia dupa cum urmeaza:

$modificat = addslashes($text);
Functia stripslashes() executa operatia complementara de anulare a conversiei, elimina caracterele backslash inserate.
Pentru a anula conversia sirului "$modificat" si a plasa rezultatul în variabila "$nemodificat", utilizati functia dupa cum urmeaza:

$nemodificat = stripslashes($modificat)

O alta functi utila pentru conversia caracterelor speciale este quotemeta(), aceasta va insera un backslash înainte de fiecare aparitie a urmatoarelor caractere: . \ + * ? [ ^ ] ( $ ). Ca si addslashes(), functia quotemeta() se foloseste in mod similar, prelund ca argument sirul text.

3. Conversia textelor HTML

Când lucrati cu texte HTML, conversia executata de functia addslashes() nu este suficienta, deoarece HTML este sensibil si la alte caractere speciale decât cele convertite de functia addslashes().
In schimb puteti folosi functia htmlspecialchars().
Aceasta converteste caracterele la care HTML este sensibil. Functie este utila cand se doreste ca un anumit sir sa nu contina marcaje HTML, ceea ce poate fi important in modul de operare a unei aplicatii, cum ar fi un tabel HTML.
Functia are urmatoarea forma:

htmlspecialchars("text" [,stil_ghilimele])

Unde "text" specifica sirul care contine textul ce urmeaza a fi convertit, iar argumentul optional "stil_ghilimele" specifica modul de conversie a ghilimelelor simple, respectiv duble. Valorile permise ale optiunii "stil_ghilimele" sunt:

ENT_COMPAT - precizeaza ca trebuie convertite numai ghilimelele duble

ENT_QUOTES - precizeaza ca trebuie convertite ambele tipuri de ghilimele

ENT_NOQUOTES - precizeaza ca nu trebuie convertit nici un tip de ghilimele

De exemplu, pentru a converti toate caracterele HTML speciale, inclusiv ambele tipuri de ghilimele, din sirul "$texthtml", utilizati functia dupa cum urmeaza:

$conversie = htmlspecialchars($texthtml);

Functia htmlspecialchars() executa urmatoarele conversii:

Caracter
Rezultatul conversiei
  & (ampersand)
  &amp;
  "(ghilimele duble)
  &quot; (numait când este specificată opţiunea ENT_COMPAT sau ENT_QUOTES)
  '(ghilimele simple)
  &#39; (numai când este specificată opţiunea ENT_QUOTES)
  < (mai mic decât)
  &lt;
  > (mai mare decât)
  &gt;

O functie PHP conexa, htmlentities(), converteste toate caracterele cu echivalente în entitati HTML. Este acceptat setul de caractere ISO-8859-1
Si o alta functie utila pentru conversia textelor HTML este functia n12br(). Aceasta insereaza tag-ul <br /> anterior fiecarui caracter de tip linie noua care se gaseste in argumentul sau.

4. Conversia pentru adresele URL

Când doriti sa codificati in PHP date ca parte a unei adrese URL, puteti folosi functia urlencode().
Aceasta functie înlocuieste fiecare caracter non-alfanumeric (cu exceptia spatiilor) cu un simbol al procentului (%), urmat de doua cifre hexazecimale care contin valoarea ASCII a caracterului. Spatiile sunt codificate sub forma de simboluri ale adunarii (+).
O functie conexa, în speta rawurlencode(), executa o conversie similara; cu deosebirea ca înlocuieste spatiile cu %20, conform RFC 1738, standardul Internet pentru codificarea adreselor URL.
Functiile urldecode() si rawurldecode() executa operatii complementare. Aceste functii sunt utile la crearea adreselor URL care includ perechi 'nume-valoare'.
De exemplu, sa presupunem ca avem un script PHP care trebuie sa creeze o pagina HTML ce contine o hiperlegatura spre adresa URL a unui motor de cautare. Termenul de cautare trebuie transmis în forma codificata URL, pentru ca serverul Web si browserul sa nu se "impiedice" de caracterele speciale. Pentru a codifica datele pentru o adresa URL, puteti folosi o metoda ca in exemplul urmator:

echo ’<a href="www.sitecautare.com?cuvantcheie='. urlencode($text). '">’;

Ca sa intelegeti mai bine aceste moduri de conversie, puteti studia amanuntit exemplul urmator:

<?php

// Variabila $a contine textul ca va fi convertit
$a = "abc 123 ' <br /> / < & > ( % ) * , $ . # ^ ! [ \ ] { @ } : ; = ?";
$b = addslashes($a);
$c = stripslashes($b);
$d = quotemeta($a);
$e = htmlentities($a);
$f = urlencode($a);
echo '<br /> Conversie addslashes() = '. $b;
echo '<br /> Anulare conversie addslashes() = '. $c;
echo '<br /> Conversie quotemeta($a) = '. $d;
echo '<br /> Conversie caractere HTML = '. $e;
echo '<br /> Conversie pt. adrese URL = '. $f;
?>

Datele de iesire ale exemplului sunt urmatoarele:

Conversie addslashes() = abc 123 \' / < & > ( % ) * , $ . # ^ ! [ \\ ] { @ } : ; = ?
Anulare conversie addslashes() = abc 123 ' / < & > ( % ) * , $ . # ^ ! [ \ ] { @ } : ; = ?
Conversie quotemeta($a) = abc 123 ' / < & > \( % \) \* , \$ \. # \^ ! \[ \\ \] { @ } : ; = \?
Conversie caractere HTML = abc 123 ' <br /> / < & > ( % ) * , $ . # ^ ! [ \ ] { @ } : ; = ?
Conversie pt. adrese URL = abc+123+%27+%3Cbr+%2F%3E+%2F+%3C+%26+%3E+%28+%25+%29+
%2A+%2C+%24+.+%23+%5E+%21+%5B+%5C+%5D+%7B+%40+%7D+%3A+%3B+%3D+%3F

PHP Lucrul cu baze de date MySQL, seturi de rezultate (Part 29)

Biblioteca de functii MySQL a limbajului PHP include functii care va permit sa obtineti informatii despre un set de rezultate, inclusiv:
Numarul coloanelor din setul de rezultate
Numele fiecarei coloane
Lungimea fiecarei coloane
Indicatorii MySQL asociati coloanei
Tipul MySQL al fiecarei coloane
Numele tabelului MySQL care contine coloana
1. Obtinerea numarului coloanelor dintr-un tabel MySQL
Pentru a obtine numarul coloanelor dintr-un set de rezultate, utilizati functia
mysql_num_fields()
Aceasta foloseste ca argument valoarea returnata de functia mysql_query().
Iata un exemplu in care functia mysql_num_fields() determina numarul coloanelor dintr-o interogare care selecteaza toate coloanele folosind specificatorul SQL pentru toate câmpurile "*", astfel puteti afla numarul de coloane dintr-un tabel:

<?php
$sql = "SELECT * FROM `nume_tabel`";
$rezultat = mysql_query($sql);
if (mysql_errno()) {
    echo "<br />". mysql_errno(). " : ". mysql_error(). "<br />";
}
$nr_campuri = mysql_num_fields($rezultat);
echo "<br /> Numar campuri: $nr_campuri";
mysql_close();
?>
2. Obtinerea numelui unei coloane

Pentru a obtine numele unei coloane dintr-un tabel MySQL, folositi functia

mysql_field_name()

Aceasta returneaza numele coloanei din setul de rezultate. Functia preia doua argumente: valoarea returnata de functia mysql_query() si indexul coloanei care va fi descrisa. Indexul asociat cu prima coloana este 0, indexul asociat celei de-a doua coloane este l etc.
Iata un exemplu care determina numele primei coloane dintr-un tabel MySQL:

<?php
$sql = "SELECT * FROM `nume_tabel`";
$rezultat = mysql_query($sql);
if (mysql_errno()) {
    echo "<br />". mysql_errno(). " : ". mysql_error(). "<br />";
}
$nume = mysql_field_name($rezultat, 0);
echo "<br /> Coloana 1 : $nume";
mysql_close();
?>

3. Obtinerea lungimii unei coloane
Pentru a obtine lungimea unei coloane dintr-un tabel MySQL, folositi functia
mysql_field_len()
Aceasta returneaza lungimea maxima a coloanei din setul de rezultate. Functia preia doua argumente: valoarea returnata de functia mysql_query() si indexul coloanei care va fi descrisa. Indexul asociat cu prima coloana este 0, indexul asociat celei de-a doua coloane este l etc.
Iata un exemplu care determina lungimea maxima a coloanei doi dintr-un tabel MySQL:

<?php
$sql = "SELECT * FROM `nume_tabel`";
$rezultat = mysql_query($sql);
if (mysql_errno()) {
    echo "<br />". mysql_errno(). " : ". mysql_error(). "<br />";
}
$lungime = mysql_field_len($rezultat, 1);
echo "<br /> Lungime Coloana 2 - $lungime";
mysql_close();
?>

4. Obtinerea indicatorilor MySQL asociati unei coloane

Pentru a obtine indicatorii SQL asociati unei coloane dintr-un tabel MySQL, folositi functia

mysql_field_flags()

Aceasta preia doua argumente: valoarea returnata de functia mysql_query() si indexul coloanei care va fi descrisa. Indexul asociat cu prima coloana este 0, indexul asociat celei de-a doua coloane este l etc.
Functia mysql_field_flags() raporteaza urmatorii indicatori:

AUTO_INCREMENT

BINARY
BLOB

ENUM

MULTIPLE_KEY

NOT_NULL

PRIMARY_KEY

TIMESTAMP

UNIQUE_KEY
UNSIGNED
ZEROFILL

- Daca la o coloana sunt asociati mai multi indicatori, fiecare indicator este separat de vecinii sai prin intermediul unui singur spatiu.
Iata un exemplu care determina indicatorii asociati primei coloane dintr-un tabel MySQL:
<?php
$sql = "SELECT * FROM `nume_tabel`";
$rezultat = mysql_query($sql);
if (mysql_errno()) {
    echo "<br />". mysql_errno(). " : ". mysql_error(). "<br />";
}
$indicatori = mysql_field_flags($rezultat, 0);
echo "<br /> Indicatorii Coloanei 1 : $indicatori";
mysql_close();
?>

5. Obtinerea tipului MySQL al unei coloane

Pentru a obtine tipul MySQL al unei coloane dintr-un tabel MySQL, folositi functia

mysql_field_type()

Aceasta preia doua argumente: valoarea returnata de functia mysql_query() si indexul coloanei care va fi descrisa. Indexul asociat cu prima coloana este 0, indexul asociat celei de-a doua coloane este l etc.
Principalele tipuri MySQL returnate de functia mysql_field_type() sunt prezentate in
Lectia 22 , in tabelul "Principalele tipuri de date din MySQL".
Iata un exemplu care determina tipul primei coloane dintr-un tabel MySQL:

<?php
$sql = "SELECT * FROM `nume_tabel`";
$rezultat = mysql_query($sql);
if (mysql_errno()) {
    echo "<br />". mysql_errno(). " : ". mysql_error(). "<br />";
}
$tip = mysql_field_type($rezultat, 0);
echo "<br /> Tip Coloana 1 : $tip";
mysql_close();
?>

6. Determinarea tabelului MySQL asociat unei coloane

Pentru a determina tabelul MySQL (daca exista) asociat unei anumite coloane, folositi functia

mysql_field_table()

Aceasta preia doua argumente: valoarea returnata de functia mysql_query() si indexul coloanei care va fi descrisa. Indexul asociat cu prima coloana este 0, indexul asociat celei de-a doua coloane este l etc.
În cazul în care coloana contine o valoare calculata sau daca respectiva coloana nu este asociata în alt mod cu un tabel MySQL, functia returneaza un sir vid.
Iata un exemplu care determina tabelul asociat primei coloane din setul de rezutate:

<?php
$sql = "SELECT * FROM `nume_tabel`";
$rezultat = mysql_query($sql);
if (mysql_errno()) {
    echo "<br />". mysql_errno(). " : ". mysql_error(). "<br />";
}
$tabel = mysql_field_table($rezultat, 0);
echo "<br /> Nume tabel : $tabel";
mysql_close();
?>

7. Obtinerea structurii complete a setului de rezultate

Daca doriti obtinerea mai multor caracteristici ale setului de rezultate, o functie utila poate fi:

mysql_fetch_field()

Aceasta functie returneaza un obiect ale carui proprietati contin o varietate de informatii cu privire la coloana unui tabel MySQL. Proprietatile sunt urmatoarele:
blob - are valoarea 1 în cazul în care coloana este de tip BLOB

max_length - lungimea maxima a coloanei;

multiple_key - are valoarea 1 în cazul în care coloana este o cheie non-unica

name - numele coloanei

not_null - are valoarea 1 în cazul în care coloana nu poate contine valoarea NULL

numeric - are valoarea 1 în cazul în care coloana este numerica
primary_key - are valoarea 1 în cazul în care coloana este o cheie primara

table - numele tabelului MySQL caruia îi apartine coloana

type - tipul MySQL al coloanei

unique_key - are valoarea 1 în cazul în care coloana este o cheie unica

unsigned - are valoarea 1 în cazul în care coloana este de tip UNSIGNED

zerofill - are valoarea 1 în cazul în care coloana este completata cu zerouri

functia mysql_fetch_field() preia doua argumente: valoarea returnata de functia mysql_query() si indexul coloanei care va fi descrisa. Indexul asociat primei coloane este 0, indexul asociat celei de-a doua coloane este l etc.
Iata un exemplu care prezinta modul de obtinere si descriere a structurii complete a setului de rezultate pentru prima coloana dintr-un tabel MySQL:

<?php
$sql = "SELECT * FROM `nume_tabel`";
$rezultat = mysql_query($sql);
if (mysql_errno()) {
    echo "<br />". mysql_errno(). " : ". mysql_error(). "<br />";
}
$info = mysql_fetch_field($rezultat, 0);
echo "<br /> Coloana 1: ";
echo "<PRE>
blob: $info->blob
max_length: $info->max_length
multiple_key: $info->multiple_key
name: $info->name
not_null: $info->not_null
numeric: $info->numeric
primary_key: $info->primary_key
table: $info->table
type: $info->type
unique_key: $info->unique_key
unsigned: $info->unsigned
zerofill: $info->zerofill
</PRE>";
mysql_close();
?>

Pentru a obtine aceste proprietati pentru toate coloanele din tabel, folositi o instructiune "for", dupa exemplul de mai jos, care parcurge fiecare coloana, folosind ca limita a numarului de coloane valoarea returnata de functia mysql_num_fields()

<?php
$sql = "SELECT * FROM `nume_tabel`";
$rezultat = mysql_query($sql);
if (mysql_errno()) {
    echo "<br />". mysql_errno(). " : ". mysql_error(). "<br />";
}
$nr_campuri = mysql_num_fields($rezultat);
for ($i=0; $i<$nr_campuri; $i++) {
    echo "<br /> Coloana $i: ";
    $info = mysql_fetch_field($rezultat);
    if ($info) {
        echo "<PRE>
        blob: $info->blob
        max_length: $info->max_length
        multiple_key: $info->multiple_key
        name: $info->name
        not_null: $info->not_null
        numeric: $info->numeric
        primary_key: $info->primary_key
        table: $info->table
        type: $info->type
        unique_key: $info->unique_key
        unsigned: $info->unsigned
        zerofill: $info->zerofill
        </PRE>";
    }
    else {
        echo "Necunoscut";
    }
}
mysql_close();
?>

8. Accesul non-secvential la coloanele unui set de rezultate

Functiile mysql_fetch_row() si mysql_fetch_array() returneaza, în general, rândurile dintr-un set de rezultate în mod secvential, incepand de la primul rand al tabelului. Totusi, functia mysql_data_seek() permite obtinerea accesului la rândurile unui set de rezultate într-o maniera non-secventiala, . Functia are forma:

mysql_data_seek(rezultat, numar_rand)

Unde "rezultat" este valoarea returnata de functia mysql_query(), iar "numar_rand" este indexul rândului la care doriti sa obtineti accesul. Primul rând al tabelului este numerotat cu 0, al doilea cu 1 etc.
Functia returneaza TRUE daca executia reuseste, respectiv FALSE în caz contrar.
Apoi, o invocare ulterioara a functiei mysql_fetch_row() sau a functiei mysql_fetch_array() va returna rândul din pozitia specificata in functia mysql_data_seek().
Studiati urmatorul exemplu, care obtine accesul la al treilea rând al setului de rezultate returnat de o interogare anterioara:

<?php
$sql = "SELECT * FROM `nume_tabel`";
$rezultat = mysql_query($sql);
if (mysql_errno()) {
    echo "<br />". mysql_errno(). " : ". mysql_error(). "<br />";
}
if (!mysql_data_seek($rezultat, 2)) {
    echo "<br />". mysql_errno(). " : ". mysql_error(). "<br />";
}
else {
    $rand = mysql_fetch_array($rezultat, MYSQL_ASSOC);
    foreach ($rand as $coloana) {
        echo "| $coloana |";
    }
}
mysql_close();
?>

- Acest exemplu afiseaza datele din randul trei pentru fiecare coloana a tabelului MySQL.

PHP Utilizarea bazelor de date folosind PHP (2) (Part 28)

1. Verificarea interogarilor care nu returneaza rânduri de tabel

Din punctul de vedere al limbajului PHP, exista doua categorii de interogari SQL, ambele fiind emise folosind functia mysql_query().

Interogarile SELECT, care returneaza rânduri ale unui tabel

Interogarile UPDATE, INSERT si DELETE, care nu returneaza rânduri ale unui tabel

Pentru a verifica daca o interogare UPDATE, INSERT sau DELETE a avut efectul dorit, puteti folosi functia mysql_affected_rows(), care returneaza numarul rândurilor afectate de interogarea cea mai recenta.
O alta functie utila este mysql_insert_id().
Cand introduceti un rand intr-un tabel a carui cheie primara este de tipul AUTO_INCREMENT, functia mysql_insert_id() determina valoarea cheii primare atribuite de MySQL. Functia returneaza valoarea zero daca interogarea precedenta nu a generat o valoare AUTO_INCREMENT. Ca atare, functia trebuie apelata la putin timp dupa interogarea care a inserat rândul in tabel, astfel încât o alta interogare ulterioara sa nu modifice rezultatul.
Iata un exemplu de utilizare a functiilor mysql_affected_rows() si mysql_insert_id() impreuna cu iterogarea INSERT (care adauga randuri in tabel). Folosim baza de date "lucrudb" si tabelul "carti", create in
Lectia 25

<?php
$conn = mysql_connect("localhost", "Marius", "mypass")
    or die("Unable to connect to MySQL");
$selectdb = mysql_select_db('lucrudb');
if (!$selectdb)
    echo "Baza de date lucrudb nu a putut fi selectata deoarece : ". mysql_errno(). " : ". mysql_error();
$sql = "INSERT INTO `carti` (nume, autor, gen, data_intrare, pret) VALUE ('Carte2', 'Autor2', 'Educativ', '2008-9-16', 11.00)";
if (mysql_query($sql))
    echo "Datele au fost adaugate in tabelul carti <br />";
else
    echo "Datele nu au fost adaugate in tabelul carti deoarece : ". mysql_errno(). " : ". mysql_error();
$nranduri = mysql_affected_rows();
$id = mysql_insert_id();
if ($nranduri == -1) {
    echo "INSERT nu a putut sa adauge datele";
}
else
    echo "Au fost adaugate $nranduri randuri, cheia primara = $id" ;
mysql_close();
?>

Dupa ce s-a facut conectarea la serverul MySQL si s-a reusit selectarea bazei de date, variabila "$sql" contine comanda SQL pentru introducerea unui nou rand in tabelul "carti", prin intermediul functiei mysql_query($sql) se introduce datele in baza de date, variabila "$nranduri" preia de la functia mysql_affected_rows() numarul de randuri afectate (aici introduse) iar variabila "$id" va avea (prin "mysql_insert_id()") valoarea cheii primare atribuite de MySQL.
Daca nu apare nici o eroare, rezultatul afisat de acest script este urmatorul:

Datele au fost adaugate in tabelul carti
Au fost adaugate 1 randuri, chea primara = 2

Functia mysql_insert_id() poate returna un rezultat incorect pentru coloanele MySQL de tipul BIGINT
[BIGINT este un tip de valoare care suporta numere cu 20 de cifre, folosit pentru campurile integer (spre deosebire de MEDIUMINT care suporta numere de la 0 la 16.777.215 (3 bytes) sau INT care suporta numerele de la 0 la 4.294.967.295 (4 bytes)].
Dupa efectuarea unei interogari INSERT, In locul functiei mysql_insert_id() se poate folosi functia LAST_INSERT_ID(), aceasta returneaza valoarea atribuita de MySQL unei coloane AUTO_INCREMENT, indiferent de tipul coloanei. Mai mult, apelurile ulterioare in script la functii MySQL nu afecteaza rezultatul returnat de LAST_INSERT_ID(), care este afectat numai de operatiile INSERT în care sunt implicate coloane AUTO_INCREMENT.
Totusi, spre deosebire de "mysql_insert_id()", LAST_INSERT_ID() necesita o interogare suplimentara la MySQL.
Iata un exemplu care prezinta modul de obtinere a valorii LAST INSERT ID():

<?php
$sql = "INSERT INTO `carti` (nume, autor, gen, data_intrare, pret) VALUE ('Carte3', 'Autor3', 'Gen3', '2008-9-16', 8.30)";
$insert = mysql_query($sql);
if (!$insert) {
    echo "<br /> Cmanda INSERT a esuat: ". mysql_errno(). " : ". mysql_error(). "<br />";
}
$interogare = "SELECT LAST_INSERT_ID() FROM `carti`";
$rezultat = mysql_query($interogare);
if (mysql_errno()) {
    echo "<br />". mysql_errno(). " : ". mysql_error(). "<br />";
}
$rand = mysql_fetch_row($rezultat);
echo "<br /> Ultimul ID repartizat: $rand[0]";
mysql_close();
?>

Dupa executarea acestui script, daca nu apare vreo eroare, rezultatul afisat va fi de genul:

Ultimul ID repartizat: 3

Functia last_insert_id() returneaza rezultatul corect numai dupa ce a fost efectuata o comanda INSERT.
Functia mysql_affected_rows() numara numai rândurile efectiv modificate de catre o interogare UPDATE. Rândurile în cazul carora vechea si noua valoare din coloana sunt identice nu se numara printre rândurile afectate.
De asemenea, o interogare DELETE care nu contine o clauza WHERE va determina functia mysql_affected_rows() sa returneze valoarea zero, indiferent de numarul rândurilor sterse din tabel.
O modalitate simpla de a determina daca stergerea tuturor rândurilor unui tabel a reusit consta în a emite o interogare care returneaza numarul rândurilor existente în tabel. De exemplu:

<?php
$sql = "SELECT COUNT(*) FROM `carti`";
$result = mysql_query($sql);
$nr = mysql_fetch_row($result);
echo $nr[0];
?>

Daca interogarea returneaza valoarea zero, demonstreaza stergerea tuturor rândurilor din tabel.

2. Prelucrarea rezultatelor interogarilor SELECT

Interogarile SELEC returneaza ca rezultate rânduri de tabel.
Rândurile unui tabel sunt incluse într-o structura de date numita "set de rezultate". Prelucrarea setului de rezultate returnat de o interogare SELECT implica parcurgerea rândurilor setului de rezultate.
O modalitate de parcurgere a rândurilor unui set de rezultate este prin utilizarea unei instructiuni "WHILE".

1. Intai se verifica daca numarul de randuri returnat este 0 folosind functia mysql_num_rows(), transferându-i ca argument valoarea returnata de functia mysql_query()

2. Daca numarul de randuri este 0 inseamna ca interogarea SELECT nu a returnat nici un rand din tabel,

3. Daca numarul de randuri este diferit de 0, se executa o instructiune WHILE impreuna cu una din functiile:

mysql_fetch_assoc() (sau mysql_fetch_array() cu parametru "MYSQL_ASSOC").
        - sunt similare, adauga datele intr-o matrice asociativa unde pentru fiecare element avem chei cu numele coloanelor iar valoarile lor sunt datele din randul respectiv.

mysql_fetch_row().
        - adauga datele intr-o matrice asociativa unde pentru fiecare element avem chei cu numere consecutive (incepand de la 0) care reprezinta ordinea coloanelor iar valoarile lor sunt datele din randul respectiv

mysql_fetch_object().
        - aduce rezultatele randului sub forma de obiect cu perechile $rand->coloana

4. Pentru a prelucra coloanele stocate în matrice, depinde de functia folosita.
      - pentru mysql_fetch_assoc() (sau mysql_fetch_array()) puteti folosi o sintaxa de genul $rand['coloana']
      - pentru mysql_fetch_row() puteti folosi o instructiune "foreach", prin care parcurgeti datele din fiecare element a matricei
      - pentru mysql_fetch_object() puteti folosi o sintaxa de genul $rand->'coloana'

- Aceste functii returneaza FALSE daca nu mai exista rânduri în setul de rezultate

Ca sa intelegeti mai bine, voi arata cate un exemplu cu fiecare in parte (voi folosi acelasi tabel, "carti"). Studiati-le cu atentie si exersati-le singuri.
Nu s-au mai introdus in aceste exemple instructiunile pentru conectarea la serverul MySQL si pentru selectarea bazei de date, le adaugati dumneavoastra.

De exemplu, daca doriti sa aflati toate datele din anumite coloane puteti folosi functia mysql_fetch_assoc() astfel:

<?php
$interogare = "SELECT `nume`, `autor` FROM `carti`";
$rezultat = mysql_query($interogare);
if (mysql_errno()) {
    echo "<br />". mysql_errno(). " : ". mysql_error(). "<br />";
}
if (mysql_num_rows($rezultat) == 0) {
    echo '0 rezultate';
}
else {
    while ($rand = mysql_fetch_assoc($rezultat)) {
        echo '<br />'. $rand['nume']. ' - '. $rand['autor'];
    }
}
?>

- Variabila "$rand" devine o matrice ale carei chei sunt numele coloanelor iar valorile lor sunt datele coloanelor respective din randul curent; instructiunea WHILE parcurge fiecare rand.

Iata acest exemplu, dar cu functia mysql_fetch_array(). In plus, in interogare SQL voi adauga numele coloanelor prin variabile, ca sa vedeti cum se lucreaza si cu variabile.

<?php
// Variabilele cu numele coloanelor
$col1 = 'nume';
$col2 = 'autor';

// Interogarea SQL folosind si variabile
$interogare = "SELECT `$col1`, `$col2` FROM `carti`";
$rezultat = mysql_query($interogare);
if (mysql_errno()) {
    echo "<br />". mysql_errno(). " : ". mysql_error(). "<br />";
}
if (mysql_num_rows($rezultat) == 0) {
    echo '0 rezultate';
}
else {
    while ($rand = mysql_fetch_array($rezultat, MYSQL_ASSOC)) {
        echo '<br />'. $rand['nume']. ' - '. $rand['autor'];
    }
}
?>

Cel de-al doilea argument al functiei mysql_fetch_array() este optional. Totusi, daca nu specificati MYSQL_ASSOC ca valoare a argumentului, PHP returneaza un tablou in care valoarea cheilor vor fi numerele si numele coloanelor.

- Comform datelor adaugate in tabelul "carti", aceste doua exemple vor afisa urmatorul rezultat

Glossa - Mihai Eminescu
Carte2 - Autor2
Carte3 - Autor3


Daca doriti sa afisati toate datele din fiecare coloana de pe fiecare rand al tabelului, puteti folosi functia mysql_fetch_row() astfel:

<?php
$interogare = "SELECT * FROM `carti`";
$rezultat = mysql_query($interogare);
if (mysql_errno()) {
    echo "<br />". mysql_errno(). " : ". mysql_error(). "<br />";
}
if (mysql_num_rows($rezultat) == 0) {
    echo '0 rezultate';
}
else {
    while ($rand = mysql_fetch_row($rezultat)) {
        foreach ($rand as $coloana) {
            echo "| $coloana |";
        }
        echo "<br />";
    }
}
?>

- Exemplul de mai sus v-a afisa urmatorul rezultat, in functie de datele din tabel:

| 1 || Glossa || Mihai Eminescu || poezie || 0000-00-00 || 8.00 |
| 2 || Carte2 || Autor2 || Educativ || 2008-09-16 || 11.00 |
| 3 || Carte3 || Autor3 || Gen3 || 2008-09-16 || 8.30 |

Daca doriti sa obtineti acces la valoarea unei anumite coloane, puteti face referire la elementul din tablou folosind o cheie a tabloului.
De exemplu, daca rezultatul functiei mysql_fetch_row() este stocat în variabila "$rand", puteti obtine acces la prima coloana folosind sintaxa "$rand[0]", la a doua coloana folosind sintaxa "$rand[1]" etc.

Iata un exemplu in care este utilizata functia mysql_fetch_object(), iar in interogarea SQL este adaugata si o conditie WHERE si o variabila "$nr".

<?php
$nr = 3;
$interogare = "SELECT `nume`, `autor` FROM `carti` WHERE `id`<'$nr'";
$rezultat = mysql_query($interogare);
if (mysql_errno()) {
    echo "<br />". mysql_errno(). " : ". mysql_error(). "<br />";
}
if (mysql_num_rows($rezultat) == 0) {
    echo '0 rezultate';
}
else {
    while ($rand = mysql_fetch_object($rezultat)) {
        echo '<br />'. $rand->nume. ' - '. $rand->autor;
    }
}
?>

- Testati singuri pentru a vedea rezultatul.

Precizare: - Comform sintaxei MySQL cu PHP, numele tabelelor si coloanelor se scriu intre caracterele ` ` (semnul din stanga tastei 1), desi functioneaza si fara, asa e corect, comform standardului, si e necesar in cazul numelor de tabele /coloane formate din mai multe cuvinte.
- Variabilele, cum e aici $nr se scriu intre ghilimele simple ' '