Sunteți pe pagina 1din 24

PHP OOP - Clase si Obiecte, Metoda constructor

OOP (Object Oriented Programming - Programare Orientata pe obiecte) este un concept (sau tehnica) de programare care
trateaza datele si functiile ca obiecte. Important la acest concept este sa fie inteleasa bine diferenta dintre Clasa (Class)
si Obiect (Object).
Inainte de a trece la lucruri practice, iata cate ceva teoretic despre OOP.
Clasa este o structura de date compacta, care contine variabile (numite proprietati) si functii (numite metode) prin care se pot
crea diferite instructiuni legate intre ele in acea structura.
Obiectele sunt elementele din script create cu o clasa, si prin care se pot folosi proprietatile si metodele din acea clasa.
- De exemplu, pentru a intelege mai bine, prin analogie, o Clasa poate fi asemanata cu planul /schita unei case, iar obiectul este
insasi casa, si contine proprietatile (culoare, ferestre, etc.) definite in schita. Precum, folosind acelasi plan se pot construi mai
multe case, asa si in OOP, folosind aceeasi clasa se pot crea unul sau mai multe obiecte prin care se aplica in script proprietatile si
functiile definite in clasa.
Practic, o clasa este o "fabrica" de obiecte, prin care se creaza obiecte cu aceeasi structura, avand proprietati si metode identice. Fiecare
astfel de obiect creat poarta denumirea de Instanta a clasei.

In OOP (Programarea Orientata pe Obiect) apar termenii: "Encapsulation" (Encapsulare), "Inheritance" (Mostenire) si
"Polymorphism" (polimorfism.).
- Encapsularea reprezinta faptul de a utiliza proprietatile si metodele clasei fara a fi necesara cunoasterea sructurii ei. Astfel,
cine foloseste o clasa intr-un script nu are nevoie sa cunoasca structura codului si instructiunilor din ea.
- Mostenirea e abilitatea unei clase de a folosi proprietati si functii definite in alta clasa din care este extinsa
(denumita parinte).
- Polimorfismul e abilitatea unei clase de a face mai multe lucruri, diferite, sau de a utiliza o clasa sau alta pentru a realiza
lucrul dorit, avand functii similare. De exemplu, o rigla poate fi utilizata pentru a trasa linii dar si pt. a masura ceva, iar pentru a
trasa linii se poate folosi si alta rigla dreapta. Acesta e polimorfism.
Pentru cine este obijnuit cu modul de creare a claselor in PHP 4, incepand de la versiunea PHP 5 sunt unele schimbari de sintaxa:
- Proprietatile nu se mai declara cu var
- Metoda Constructor se defineste cu numele __construct

1. Creare clasa
Definirea unei clase incepe cu un cuvantul cheie "class", urmat de numele clasei si corpul ei (cuprins intre acolade). In corpul
clasei se definesc proprietatile si metodele ei.
- Proprietatile sunt variabile definite in interiorul clasei.
- Metodele sunt functii create in interiorul clasei.
Structura general de alcatuire a unei clase este urmatoarea:

class nume_clasa {
$proprietate;
function metoda() {
// Codul functiei
}
}

Pentru a construi o clasa profesionala, cu elemente incluse in PHP 5+, sunt necesare si alte lucruri care trebuie adaugate.
- La definirea unei clasei si a elementelor din ea (proprietati, metode) se pot aplica unele atribute speciale prin care se defineste
domeniul lor de lucru (de existenta). Acest atribut se adauga inaintea variabilei sau a cuvantului functions, si poate fi unul din
cuvintele:

public - valabil in tot scriptul


private - valabil doar in interiorul acelei clase
protected - valabil doar in acea clasa si sub-clasele extinse din ea

- Daca nu e adaugat nici un atribut, se considera "public".


Astfel, formula completa pentru crearea unei clase este:

class Nume_Clasa {
atribut $proprietate1;
atribut $proprietate2;
.................
atribut function metoda1() {
// Codul functiei
}
atribut function metoda2() {
// Codul functiei
}
.................
}

- Pentru o mai buna organizare, este indicata crearea fiecarei clase intr-un fisier PHP separat si cu o denumire de forma
"class.Nume_Clasa.php". Acest lucru nu e obligatorriu, doar ca indicatie; clasa poate fi creata si in scriptul unde e folosita.
Iata un exemplu de clasa simpla, ce contine doua proprietati, prima cu atribut public (denumita $site), a doua private(denumita
$categorie) si o metoda cu atribut public (cu numele "pagini").
Exemplu SiteClas
<?php
// Se defineste clasa SiteClas
class SiteClas {

public $site = 'www.marplo.net/';

// Proprietatea publica

private $categorie = 'php-mysq/';

// Proprietate privata

// Creare metoda, preia un argument


public function pagini($pag) {
// Afiseaza adresa URL formata din valoarea celor 2 proprietati si argumentul primit
echo '<br />'. $this->site. $this->categorie. $pag;
}
}
?>
- Aceasta este clasa "SiteClas", pentru a-o putea folosi in orice script, sa o salvam intr-un fisier separat, denumit
"class.SiteClas.php".
- Formula "$this->site" indica /face sa fie apelata proprietatea "site" a obiectului curent din aceasta clasa (termenul$this (acesta,
aceasta) indica precis ca se face referire la proprietatea respectiva, din instanta curenta).
Cand se acceseaza proprietati se foloseste un singur caracter $. Sintaxa este $obj->proprietate, desi variabila e definita
"$proprietate".

2. Utilizare clasa
Dupa ce o clasa e creata, pentru a putea fi utilizata trebuie creata o instanta de obiect a clasei. Aceasta instanta se declara in
scriptul PHP, cu formula:
$nume_obiect = new Nume_Clasa();
- "nume_obiect" este numele obiectului prin care pot fi utilizate proprietatile si metodele acelei clase.
Iata cum poate fi utilizata clasa "SiteClas" prezentata mai sus (pt. explicatii, studiati si comentariile din cod).
<?php
include('class.SiteClas.php');

$objSite = new SiteClas();

echo $objSite->site;

// Include clasa

// Creare instanta de obiect la clasa SiteClas

// Afisaza valoarea proprietatii "site"

// Apeleaza metoda pagini() [cu un argument, dupa cum a fost definita]


$objSite->pagini('oop-clase-obiecte.html');

// Modifica valoarea proprietatii "site" si apeleaza iar metoda pagini()


$objSite->site = 'www.alt-site.net/';
$objSite->pagini('oop-clase-obiecte.html');
?>
- La include() trebuie adaugata calea si numele fisierului cu clasa, in raport cu scriptul curent (aici sunt in acelasi director).
- Inainte de a putea utiliza proprietati si metode din clasa, trebuie creata o instanta de obiect, deoarece prin aceasta se apeleaza
aceste elemente, dupa sintaxa:
$obiect->element
- Prin apelarea metodei "pagini()" ( $objSite->pagini('oop-clase-obiecte.html'); ) se va executa codul functiei "pagini()" definita in
clasa, care afiseaza intr-un sir o adresa URL compusa din valorile proprietatilor si argumentul primit.
- Observati ca valoarea proprietatilor poate fi modificata in cadrul scriptului. Proprietatea "site" poate fi apelata atat pentru a fi
utilizata /afisata valoarea ei cat si pentru adaugarea altei valori (aici sirul 'www.alt-site.net/').
- In browser va afisa:
www.marplo.net/
www.marplo.net/php-mysq/oop-clase-obiecte.html
www.alt-site.net/php-mysq/oop-clase-obiecte.html
Daca se incearca apelarea proprietatii private (aici "categorie"), de ex.: echo $objSite->categorie; , va determina o eroare ca cea de
jos. Aceasta proprietate fiind declarata private poate fi utilizata doar in codul din interiorul clasei.
Fatal error: Cannot access private property SiteClas::$categorie in E:\server\www\index.php on line 15
Valoarea data unei proprietati definita in clasa poate fi de orice tip: sir (string), numar, Array sau Object.

3. Metoda constructor
Metoda constructor e un tip special de functie din interiorul Clasei. Se declara cu numele __construct (doua caractere "_" in
fata). Aceasta metoda este mereu "public" chiar daca nu se mentioneaza special atributul "public". Diferenta fata de celelalte

functii este aceea ca Metoda Constructor e apelata automat cand se creaza o instanta la clasa respectiva, codul din ea se executa
in momentul cand e creat obiectul (cu new).
Iata o noua versiune a clasei "SiteClas", care include si metoda constructor, plus o metoda cu atribut protected.
<?php
// Se defineste clasa SiteClas
class SiteClas {
public $site = 'www.marplo.net/';

// Proprietate publica

private $categorie = 'php-mysq/';

// Proprietate privata

// Definire metoda constructor


public function __construct($nume) {
// Afiseaza un mesaj de bun venit, incluzand proprietatea "site"
echo 'Bine ai venit '. $nume. ' pe '. $this->site. '<br />';
echo $this->Mesaj();

// adauga si ce returneaza metoda Mesaj()

// Metoda protected
protected function Mesaj() {
// Returneaza un mesaj cu proprietatea 'categorie'
return 'Categoria de cursuri '. $this->categorie;
}
// Creare metoda, preia un argument
public function pagini($pag) {
// Afiseaza adresa URL formata din valoarea celor 2 proprietati si argumentul primit
echo '<br />'. $this->site. $this->categorie. $pag;
}
}
?>
- Deoarece Metoda Constructor preia un parametri ($nume) [se pot adauga mai multi, ca la orice functie], cand se creaza o instanta
la aceasta clasa trebuie sa fie adaugat si un argument.
<?php
include('class.SiteClas.php');

// Include clasa

// Creare instanta de obiect la clasa SiteClas, cu argumentul necesar


$objSite = new SiteClas('Marius');
?>
- Prin executia metodei "__construct()", apelarea $this->Mesaj() determina si executia metodei Mesaj(), care avand atribut
"protected" poate fi apelata doar in codul din corpul clasei sau alte clase extinse din ea (despre clase extinse intr-o lectie viitoare).
- Acest cod simplu va returna in fereastra urmatorul mesaj:
Bine ai venit Marius pe www.marplo.net/
Categoria de cursuri php-mysq/
- Fapt ce demonsreaza ca Metoda Constructor este apelata automat si se executa codul din ea cand e creata instanta de obiect.
Dupa cum se arata in exemplu de sus, in metoda constructor pot fi apelate si alte metode sau proprietati definite in clasa, cu
sintaxa $this-> , fapt ce va face ca si acele metode sa fie executate cand e creat obiectul.
- Daca se apeleaza in script (in afara clasei) o metoda "protected" sau "private" (de ex., aici: $objSite->Mesaj();) va genera eroare.

Daca metoda constructor e definita cu un anumit numar de parametri, fara valoare initiala, cand se creaza instanta de obiect,
clasa trebuie sa fie apelata cu acelasi numar de argumente, altfel returneaza eroare.
De ex., metoda constructor din exemplu precedent e definita cu un parametru ($nume), daca s-ar crea o instanta fara argument, de
forma: $obj = new SiteClass(), va genera o eroare de genul:

Missing argument 1 for SiteClas::__construct(), called in ...


Dar se pot declara parametri cu valoare deja atribuita, astfel, argumentul pentru ei devine optional.
De ex., in clasa Test de mai jos, metoda constructor e definita cu parametru $nume='Tu'.
<?php
class Test {
// Constructor (cu un parametru cu valoare predefinita)
public function __construct($nume='Tu') {
echo '<br />Salut '. $nume;
}
}
?>
- Daca instanta e creata fara argument, metoda constructor va folosi parametru $nume cu valoarea lui prestabilita ("Tu"), iar cand e
adaugat argument, preia valoarea acestuia; dupa cum arata rezultatul afisat de scriptul urmator, in care se creaza doua instante de
obiect la clasa Test.
<?php
// Creare instanta de obiect la clasa Test, fara argument
$obj1 = new Test();

// A doua instanta de obiect la clasa Test, cu argument


$obj2 = new Test('Marius');
?>
- Acest exemplu arata si faptul ca se pot crea si folosi mai multe instante de obiect la aceeasi clasa.
- In browser apare:
Salut Tu
Salut Marius
In lectia urmatoare sunt prezentate metodele accesor si _destruct().

1. Metoda Accesor
Variabilele (proprietatile) create intr-o clasa pot avea de la inceput o valoare sau pot fi doar simplu declarate, urmand ca
valoarea lor sa fie atribuita prin intermediul unei functii (metode). Aceasta functie e denumita genericMetoda Accessor, e la fel
ca oricare alta metoda, doar ca scopul ei este de a atribui valori proprietatilor; in rest, se construieste si se apeleaza la fel ca
celelalte.
Ca sa vedeti cum functioneaza "metoda accessor", incercati urmatorul exemplu, in care este creata o clasa "SiteClas" cu doua
proprietati ('site' si 'categorie'), ambele fara valoare, iar metoda Constructor e folosita si ca accesor, atribuie valori proprietatilor
prin parametri ei.
<?php
// Se defineste clasa SiteClas
class SiteClas {
public $site;

// Proprietate declarata fara valoare

private $categorie;

// Proprietate privata, fara valoare

// Constructor
public function __construct($site, $categorie) {
// Atribuie proprietatilor valoarea din parametri
$this->site = $site;
$this->categorie = $categorie;
}

// Metoda pt. afisare adresa pagini


public function pagini($pag) {

// Afiseaza un sir cu adresa URL, www., valoarea celor 2 proprietati si argumentul primit
echo '<br />www.'. $this->site.'/'. $this->categorie.'/'. $pag;
}
}
?>
- Cand e creata instanta de obiect la clasa, metoda constructor (care se executa automat) atribuie proprietatilor "site" si "categorie"
valorile din parametri, care trebuie adaugate la crearea instantei.
- Metoda pagini(), cand e apelata, afiseaza o adresa URL formata din valoarea proprietatilor "site", "categorie" (atribuite prin
constructor) si argumentul ei $pag.
- Salvam clasa intr-un fisier denumit "class.SiteClass.php", iar pentru test, se adauga urmatorul cod intr-un fisier .php salvat in
acelasi director unde e si clasa.
<?php
include('class.SiteClas.php');

// Include clasa

// Creare instanta de obiect la clasa SiteClas, cu argumentele necesare


$objSite = new SiteClas('marplo.net', 'php-mysql');

$objSite->pagini('oop-clase-obiecte.html');

// Apelare metoda pagini()

?>
- Dupa executie, in browser va afisa:
www.marplo.net/php-mysql/oop-clase-obiecte.html
Valoarea proprietatii "site", avand atribut "public", poate fi modificata si pe parcurs in script, cu expresia:
$objSite->site = valoare;

2. Accesare si modifi care proprietati prin metode Accesor


Variabilele in PHP nu au un tip de date stabilit precis la declararea lor, de exemplu, o variabila poate sa contina initial ca valoare
un numar, iar pe parcursul scriptului sa i-se atribuie ca valoare un sir sau un Array. Aceasta flexibilitate este folositoare, dar in
unele situatii poate prezenta probleme in anumite contexte din codul unei metode.
De exemplu, daca intr-o metoda se parcurg datele dintr-o proprietate de tip Array iar in script acea proprietate primeste o valoare
de tip Sir, apar erori.
Pentru a fi siguri ca o proprietate primeste doar tipul de date care poate fi corect utilizat, se declara ca private si se folosesc
metode accesor pentru accesarea ei, cu functii PHP de verificare a tipului de date. Aceste functii sunt:

is_bool() - Boolean - una din valorile speciale: true sau false


is_integer() sau is_int() - Integer - numere intregi (fara virgula)
is_float() sau is_double() - Float /Double - numere cu zecimale (cu virgula)
is_numeric() - Number - orice numar sau sir ce reprezinta un numar
is_string() - String - siruri de caractere si cuvinte
is_array() - Array - Array
is_object() - Object - Obiect
is_resource() - Resource - un identificator pentru lucru cu date din sure externe (fisier, baza de date)
is_null() - Null - Valoare NULL sau nedefinita

Iata o alta versiune a clasei TestClas. Ambele proprietati sunt declarate "private", ca sa nu fie modificate in mod direct in afara
clasei. Valorile initiale le primesc la crearea instantei (prin constructor). Pentru a putea accesa si modifica proprietatea "categorie" in
script, se creaza special cate o metoda accesor: getCategorie() si setCategorie() (vedeti si explicatiile din cod).
<?php
// Se defineste clasa SiteClas
class SiteClas {
// Definire proprietati private, fara valoare
private $site;
private $categorie;

// Constructor
public function __construct($site, $categorie) {

// Atribuie proprietatilor valoarea din parametri


$this->site = $site;
$this->categorie = $categorie;
}

// Metoda accesor - returneaza valoarea proprietatii 'categorie'


public function getCategorie() {
return $this->categorie;
}

// Metoda accesor pt. setare valoare la "categorie"


public function setCategorie($val) {
// Daca $val e de tip Sir (string) si are cel putin un caracter
// Atribuie valoarea lui proprietatii 'categorie'
// Altfel, returneaza eroare
if(is_string($val) && strlen($val)>0) {
$this->categorie = $val;
}
else throw new Exception('Valoare incorecta pt. categorie');
}

// Metoda pt. afisare adresa pagini


public function pagini($pag) {
// Afiseaza un sir cu adresa URL, www., valoarea celor 2 proprietati si argumentul primit
echo '<br />www.'. $this->site.'/'. $this->categorie.'/'. $pag;
}
}
?>
- Prin declararea proprietatilor ca "private", se respinge accesul direct la ele in afara clasei, iar pt. proprietatea "categorie" s-a creat
posibilitatea de a fi accesata si modificata valoarea ei prin metodele accesor: getCategorie() sisetcategorie($val).
- In setCategorie($val) se atribuie valoarea transmisa pt. $val la "categorie" (prin formula $this->categorie = $val;) doar daca $val e
de tip Sir (String) si are cel putin un caracter; altfel, utilizand formula speciala "throw new Exception('Eroare')" returneaza un mesaj
de eroare.
- Pentru a testa efectul acestor metode, se executa scriptul urmator, in care e utilizata o instanta la aceasta clasa.
<?php
include('class.SiteClas.php');

// Include clasa

// Creare instanta de obiect la clasa SiteClas


$objSite = new SiteClas('marplo.net', 'php-mysql');

// Afiseaza valoarea returnata de getCategorie() (reprezentand valoarea proprietatii "categorie")


echo $objSite->getCategorie();

// Modifica prin setCategorie() valoarea proprietatii "categorie"


$objSite->setCategorie('html');

$objSite->pagini('introducere.html');

// Apelare metoda pagini()

?>
- In browser scriptul va afisa:
php-mysql
www.marplo.net/html/introducere.html
- "php-mysql" este valoarea initiala data proprietatii "categorie" prin crearea instantei la clasa. Dar prin modificarea ei cu $objSite>setCategorie('html');, metoda pagini() va utiliza proprietatea "categorie" cu aceasta valoare (html).

3. Metoda Destructor
Metoda Destructor se creaza cu numele __destruct (doua caractere '_' la inceput). Aceasta metoda este opusul
lui __construct. Daca metoda constructor e apelata automat cand se creaza o instanta de obiect la clasa, metoda Destructor se
apeleaza automat cand e stearsa, cu unset(), instanta la acea clasa.
Se intelege mai bine din urmatorul exemplu. Clasa Test de mai jos contine o proprietate privata, "nume", o metoda accesor
"setNume()", metoda constructor si destructor.
<?php
// Clasa Test
class Test {
private $nume;

// Constructor
public function __construct($nume) {
// Atribuie proprietatii 'nume' valoarea din parametru
// si afiseaza un mesaj
$this->nume = $nume;
echo 'Bine ai venit '. $this->nume. '<br />';
}

// Metoda accesor - schimba valoarea proprietatii 'nume'


public function setNume($nume) {
$this->nume = $nume;
}

// Metoda Destructor
function __destruct() {
echo 'Cu bine '. $this->nume;
}
}
?>
- Ca sa testam efectul metodei __destruct, se foloseste urmatorul script (vedeti explicatiile din cod).
<?php
// Creare instanta de obiect la clasa Test
$obj = new Test('Mar');

// Apeleaza metoda setNume(), care seteaza alta valoarea la prop. 'nume'


$obj->setNume('Plo');

// Sterge instanta de obiect $obj

unset($obj);
?>
- Prin argumentul 'Mar' adaugat la crearea instantei, metoda constructor atribuie aceasta valoare proprietatii "nume", pe care o
afiseaza in mesajul returnat.
- Apelarea metodei setNume() modifica valoarea acestei proprietati, iar cand instanta de obiect e stearsa, cuunset($obj), se
autoapeleaza metoda "__destruct" si determina executia codului din ea, care va afisa alt mesaj, cu proprietatea "nume" avand
ultima valoare setata.
- Rezultatul afisat in browser este:
Bine ai venit Mar
Cu bine Plo
Metoda destructor este utila cand se doreste executarea automata a unor ultime instructiuni cand instanta la clasa e stearsa din
memorie prin apelarea functiei PHP unset().

In lectia urmatoare sunt prezentate Constante si elemente Statice in Clasele PHP.

1. Constante
Pe langa proprietati (variabile) si metode (functii), in corpul clasei pot fi definite si constante, prin cuvantul const. Sintaxa
generala este:
const NUME_CONSTANTA;
- Diferenta principala dintre constante si proprietati e faptul ca valoarea constantei ramane aceeasi, nu mai poate fi modificata.
- La constante nu se foloseste atribut (public, private, protected), doar cuvantul const, ele sunt recunoscute ca publice.
- Constantele se acceseaza prin numele clasei si operatorul doua-puncte (::) (atat in interiorul clasei cat si in script unde e creata
instanta), cu formula:
Nume_Clasa::NUME_CONSTANTA
Pentru a se distinge mai clar proprietatile de constante, se obisnueste ca numele constantelor sa fie scris cu majuscule.

Iata un exemplu de clasa cu o constanta, si cum poate fi aceasta utilizata. Clasa Test de mai jos contine o proprietate "raza", o
constanta "PI", metoda constructor si o metoda "getArea()".
<?php
// Clasa Test
class Test {
public $raza;
const PI = 3.14;

// Proprietate
// Constanta

// Constructor
public function __construct($raza) {
// Daca $raza e un numar, atribuie valoarea la proprietatea "raza"
// Altfel, seteaza un mesaj de eroare
if(is_numeric($raza)) $this->raza = $raza;
else throw new Exception('Valoare incorecta pt. raza');
}

// Returneaza aria cercului


public function getArea() {
return Test::PI * pow($this->raza, 2);
}
}
?>
- Metoda constructor verifica daca argumentul adaugat la crearea instantei este de tip numar, in caz Adevarat, atribuie acea valoare
la proprietatea "raza". Altfel, returneaza eroarea definita in Exception().
- Metoda getArea() returneaza aria cercului (formula matematica este PI*Raza2).
- Pentru a testa aceasta clasa si modul de accesare a constantei, folosim urmatorul script.
<?php
echo Test::PI;

// Afiseaza valoarea constantei PI din clasa Test

// Creare Instanta la clasa Test

$objTest = new Test(78);

// Afiseaza aria cercului cu raza 78, returnata de metoda getArea()


echo '<br /> Aria = '. $objTest->getArea();
?>
- Observati cum e accesata constanta "PI", cu aceeasi formula in interiorul clasei si in script, inainte de a crea instanta la clasa.
Astfel, constantele pot fi accesate si fara a crea o instanta de obiect la acea clasa.
- Rezultatul afisat de acest exemplu este:
3.14
Aria = 19103.76
Daca se incearca modificarea valorii constantei, in clasa sau in afara ei (Clasa::CONSTANTA=alta_valoare;), va genera eroare.
- In interiorul clasei, constantele pot fi accesate si prin cuvantul special self in loc de numele clasei:
self::CONSTANTA
- In afara clasei, constantele pot fi accesate si prin intermediul instantei de obiect, dar dupa crearea ei. In exemplu de mai sus, dupa
declararea instantei se poate folosi si $objTest::PI;

2. Proprietati si metode Statice


Pe langa atributele: "public", "private" si "protected"; prin care se defineste domeniul de acces al proprietatilor si metodelor;
acestea pot fi create si ca statice, astfel, vor apartine exclusiv clasei, si nu pot fi apelate prin instanta de obiect a clasei, ci direct
prin ea, cu operatorul doua-puncte (::).
Pentru a defini o proprietate sau metoda ca statica, se foloseste cuvantul static inaintea atributului, cand sunt create aceste
elemente. Sintaxa generala este:
static atribut $proprietate
static atribut function Metoda()
- atribut este unul din cuvintele: public, private sau protected; care stabilesc domeniul de existenta.
Aceste elemente statice nu pot fi apelate prin instanta de obiect deoarece nu apartin ei, ele apartin clasei si pot fi apelate cu
formula:
NumeClasa::$proprietate
NumeClasa::metoda()
- Observati ca la proprietate, cand e statica trebuie adaugat si caracterul $ (fara caracterul '$', sintaxa "NumeClasa::proprietate"
este confundata cu cea pt. constante).
In interiorul clasei, elementele statice pot fi apelate si prin cuvantul special self in loc de numele clasei:
self::$proprietate
sau
self::Metoda()
Iata un exemplu din care se intelege mai bine. In clasa urmatoare, denumita "elStatic" se definesc doua proprietati statice: una cu
atribut "private" (site), a doua publica (id); o metoda constructor si alta statica.
<?php
// Clasa elStatic
class elStatic {
// Definire proprietati statice
static private $site = 'www.marplo.net';
static public $id = 78;

// Privata

// Publica

// Constructor
public function __construct($site) {
// Daca parametru $site e de tip String si cel putin 4 caractere
// Atribuie valoarea la proprietatea "site" si apeleaza metoda getProp()
// Altfel, seteaza un mesaj de eroare
if(is_string($site) && strlen($site)>3) {
elStatic::$site = $site;
self::getProp();

// Apelare prin cuvantul special self

}
else throw new Exception('Valoare incorecta pt. site');
}

// Metoda statica
static public function getProp() {

// Afiseaza valoarea proprietatilor statice (folosind numele clasei, dar si cuvantul self )
echo '<br /> ID = '. elStatic::$id. ' - site: '. self::$site;
}
}
?>
- Vedeti explicatiile din cod si modul de lucru, cum sunt accesate proprietatile si metoda statica.
- Deoarece elementele statice apartin direct clasei, pentru utilizarea lor nu e nevoie de crearea unei instante la aceasta clasa. Dar se
pot folosi si instante, acestea determina auto-apelarea metodei constructor, dupa cum puteti vedea in scriptul urmator, care
foloseste elemente din clasa "elStatic" si o instanta la ea.
<?php
echo elStatic::$id;

// Afiseaza valoarea proprietatii statice "id"

elStatic::getProp();

// Apeleaza metoda statica getProp()

elStatic::$id = 89;

// Modifica valoarea proprietatii statice "id"

// Creare Instanta la clasa elStatic


$obj = new elStatic('www.php.net');
?>
- Observati ca valoarea proprietatii statice care e publica (aici "id") poate fi schimbata in afara clasei si influenteaza dupa ea toate
instructiunile in care e folosita (ca si cum ar fi modificata in clasa), inclusiv orice instanta la clasa, creata dupa modificare.
- Acest exemplu va afisa in browser urmatorul rezultat:
78
ID = 78 - site: www.marplo.net
ID = 89 - site: www.php.net
- Prin crearea instantei s-a obtinut rezultatul dat de metoda constructor.
Intr-o clasa se pot folosi combinate: constante, metode si proprietati statice si generale (fara "static"), dar in corpul metodelor
statice se pot utiliza doar elemente care si ele sunt statice, sau constante. Accesarea in codul dintr-o metoda statica a unei
proprietati cu formula $this->proprietate genereaza eroare.
$this face referire la instanta de obiect curenta, self se refera la clasa curenta.

La pagina Functii - clase si obiecte sunt prezentate cateva functii PHP pentru Clase si Obiecte.
In lectia urmatoare e prezentata utilizarea mostenirii si clasele extinse.
Mostenirea este unul din cele mai utile instrumente ale Programarii Orientate pe Obiect - OOP.
Prin mostenire se intelege transmiterea proprietatilor, constanttelor si a functiilor de la o clasa la alta, intr-o structura ierarhica.
Prima clasa este clasa de baza, denumita "parinte", legata de aceasta se poate crea o sub-clasa, denumita "copil"; sub-clasa
'copil' mosteneste proprietatile si metodele clasei 'parinte' (cele care sunt cu atribut "public" sau "protected"), le poate folosi in
instructiunile din propriul cod si le transmite cand se creaza o instanta de obiect la ea.Precum in natura copii mostenesc genele
parintilor.

1. Creare clasa copil


Sub-clasa "copil" se creaza cu formula:
class ClasaCopil extends ClasaParinte
Iata cum se aplica acest procedeu in programarea PHP OOP.
In exemplu prezentat aici se construieste intai o clasa de baza, denumita Site, cu doua proprietati: una cu atribut private (site), alta
cu atribut public (categorie), constructor si o metoda getPag().
<?php
// Clasa Site
class Site {
// Definire proprietati, private si public
private $site;
public $categorie = 'php-mysql';

// Constructor
public function __construct($site) {
// Daca parametru $site e un Sir cu cel putin 5 caractere, atribuie valoarea la proprietatea "site"

// Altfel, seteaza un mesaj de eroare


if(is_string($site) && strlen($site)>4) $this->site = $site;
else throw new Exception('Valoare incorecta pt. site');
}

// Metoda getPag()
public function getPag($pag) {
// Defineste si returneaza adresa URL a paginii
$url = $this->site. '/'. $this->categorie. '/'. $pag;
return $url;
}
}
?>
- Metoda Constructor atribuie valoarea din parametru $site la proprietatea "site".
- Metoda getPag() returneaza o adresa URL formata din proprietatile clasei si parametru ei.
Salvam aceasta clasa intr-un fisier "class.Site.php".
Aceasta clasa poate fi utilizata pentru afisarea unui sir cu o adresa URL, prin apelarea metodei getPag(). Daca vrem sa obtinem
aceasta adresa intr-un tag HTML tip link (<a>) se poate crea o noua metoda, pentru alta facilitate alta metoda, si tot asa se
aglomereaza codul clasei, fapt ce devine o problema in cazul unor clase mari. O alta varianta este crearea unei sub-clase extinse din
aceasta. Sub-clasa (copil) are abilitatea de a mosteni /utiliza toate proprietatile si metodele definite ca publice si protected in clasa
de baza (parinte) ca si cum ar fi create in ea (fara sa mai fie scrise inca o data). Astfel, in clasa copil se creaza doar instructiunile cu
noua functie pe care o dorim, si nici nu mai trebuie modificata clasa parinte.
In continuarea acestui exemplu se creaza o alta clasa, denumita LinkSite, ca extindere a clasei Site. Ea contine doar o metoda
getLink() pentru afisarea unui link.
<?php
include('class.Site.php');

// Include clasa parinte (Site)

// Creare clasa copil LinkSite, extinsa din Site


class LinkSite extends Site {
// Metoda getLink()
public function getLink($pag) {
// Afiseaza un link format din getPag() si "categorie" din clasa parinte
echo '<a href="http://'. $this->getPag($pag). '" title="'. $this->categorie. '">Link</a><br />';
}
}
?>
Salvam aceasta clasa, cu denumirea "class.LinkSite.php" in acelasi director unde e salvata si clasa Site.
Acum, atentie la explicatii:
- Pentru a avea acces la definitiile din clasa principala Site, deoarece se afla intr-un fisier extern, o includem cuinclude().
- Cuvantul special "extends" stabileste identitatea clasei LinkSite ca fiind o extindere a clasei Site.
- In metoda getLink() se folosesc proprietatea "categorie" si metoda "getPag()" din clasa parinte ca si cum ar fi fost definite in
aceasta clasa.
Aceste elemente pot fi accesate in clasa copil deoarece au atribut "public" (functioneaza si cu "protected"). Dar proprietatea
"site", care are atribut "private" in clasa parinte, nu poate fi accesata in cea copil.
- Desi aceasta clasa nu are o metoda constructor, ea mosteneste constructorul clasei parinte, astfel, cand se creaza o instanta de
obiect la clasa LinkSite trebuie adaugat si un argument de tip Sir, deoarece asa e definita metoda "__construct($site)" in clasa de
baza (Site).
Sa testam aceasta clasa copil, cu scriptul urmator.
<?php
include('class.LinkSite.php');

// Include fisierul cu subclasa LinkSite

// Creare instanta la clasa copil LinkSite


$objLink = new LinkSite('www.marplo.net');

// Apeleaza metoda getLink() (definita in clasa copil);


$objLink->getLink('oop-clase-extinse-mostenire.html');

// Modifica valoarea proprietatii "categorie" (aflata in clasa parinte)


$objLink->categorie = 'ajax';

// Afiseaza rezultatul dat de metoda getPag() (creata in clasa parinte)


echo $objLink->getPag('introducere.html');
?>
- Deoarece clasa LinkSite se afla intr-un fisier PHP extern, o includem cu include().
- La crearea instantei de obiect se adauga si argumentul necesar, un sir ('www.marplo.net'), cerut de metoda constructor a clasei de
baza, care e si ea mostenita.
- Observati cum sunt accesate proprietatea "categorie" si metoda "getPag()" (care se afla in clasa parinte), prin instanta de obiect la
clasa copil (LinkSite) ca si cum ar fi create in ea. Acesta este efectul mostenirii, atat de util in OOP.
In browser va afisa urmatorul rezultat:
Link
www.marplo.net/ajax/introducere.html

2. Redefi nire metode


In exemplu de mai sus, clasa copil LinkSite a mostenit si metoda "__construct()" din clasa parinte Site, fapt ce determina
executarea codului din acel Constructor si cand e creata instanta la clasa copil. Uneori aceasta functie nu e adecvata in sub-clasa.
Pentru a evita acest lucru, metodele inadecvate pot fi rescrise prin adaugarea uneia cu acelasi nume in clasa copil, astfel, la
crearea instantei, va fi utilizata metoda, cu acelasi nume, din clasa copil.
- Rescrierea unei metode nu afecteaza cu nimic pe cea originala, modificarile efectuate sunt valabile doar in clasa copil in care se
face rescrierea, respectiv, in alte sub-clase ale ei.
Iata o alta sub-clasa (PagSite) extinsa din Site. Aici se adauga si o metoda "__construct()" care o va anula pe cea din clasa parinte,
se rescrie si metoda getPag().
<?php
include('class.Site.php');

// Include clasa parinte (Site)

// Creare clasa copil PagSite, extinsa din Site


class PagSite extends Site {
public $domeniu = 'marplo.net';

// Proprietate

// Constructor, rescrie pe cel din parinte (Site)


function __construct() {
// Fara instructiuni, executa nimic
}

// Metoda getPag(), rescrisa


public function getPag($pag) {
// Preia functionalitatea metodei getPag() din clasa parinte
$url = parent::getPag($pag);

// ... alte instructiuni pt. metoda getPag()

// Adauga in $url si valoarea proprietatii "domeniu"


$url = $this->domeniu. $url;

return 'Pagina: '. $url;

}
}
?>
- Prin crearea in aceasta sub-clasa a metodei "__construct()" se anuleaza efectul celei din clasa parinte, si neavand parametru, nici
la creare instantei nu se mai adauga vreun argument.
- Pentru a pastra si functionalitatea initiala (din clasa parinte) a metodei rescrise, in corpul functie care face rescrierea, se adauga cu
formula parent::nume_metoda() (tehnica folosita si in exemplu de sus, la getPag()).
In scriptul urmator se foloseste aceasta a doua sub-clasa.
<?php
include('class.PagSite.php');

// Include fisierul cu aub-clasa PagSite

// Creare instanta la clasa copil PagSite


$objPag = new PagSite();

// Modifica valoarea proprietatii "categorie" (aflata in clasa parinte)


$objPag->categorie = 'html';

// Afiseaza rezultatul dat de metoda getPag() (rescrisa)


echo $objPag->getPag('introducere.html');
?>
- Instructiunea $objPag->getPag('introducere.html') apeleaza metoda "getPag()" din clasa la care s-a creat instanta de obiect
(PagSite) deoarece exista cu aceasta denumire in ea. Se observa si din rezultatul afisat:
Pagina: marplo.net/html/introducere.html

3. Metode fi nale
In exemplu prezentat mai sus se vede cum o metoda din clasa de baza poate fi rescrisa in sub-clasa copil, dandu-i alta
functionalitate. Sunt situatii in care nu se doreste ca o metoda sa poata fi rescrisa, in acest caz, prin adaugarea cuvantului final la
inceputul declararii metodei se blocheaaaza posibilitatea rescrierii ei.
- De exemplu:
<?php
// Clasa Baza
class Baza {
// Metoda final
final public function numeMet() {
// Instructiunile functiei
}
}

// Definire clasa-copil din Baza


class CopilBaza extends Baza {
// Rescriere metoda numeMet()
public function numeMet() {
// Alte Instructiuni
}
}
?>
- Va genera eroarea:
Fatal error: Cannot override final method Baza::numeMet() in ...
- Deoarece metoda "numeMet()" este declarata cu atribut "final".

4. Clase fi nale

Precum metodele declarate cu "final" nu mai pot fi modificate in sub-clasa copil, asa se pot crea si clase care sa ramana fixe,
fara sa se poata crea din ele alta sub-clasa. Acest lucru se obtine prin adaugarea cuvantului final inainte de class.
- De exemplu:
<?php
// Clasa Baza
final class Baza {
// ... Instructiuni
}

// Definire clasa-copil din Baza


class CopilBaza extends Baza {
// ... Alte Instructiuni
}
?>
Mostenirea este unul din cele mai utile instrumente ale Programarii Orientate pe Obiect - OOP.
Prin mostenire se intelege transmiterea proprietatilor, constanttelor si a functiilor de la o clasa la alta, intr-o structura ierarhica.
Prima clasa este clasa de baza, denumita "parinte", legata de aceasta se poate crea o sub-clasa, denumita "copil"; sub-clasa
'copil' mosteneste proprietatile si metodele clasei 'parinte' (cele care sunt cu atribut "public" sau "protected"), le poate folosi in
instructiunile din propriul cod si le transmite cand se creaza o instanta de obiect la ea.Precum in natura copii mostenesc genele
parintilor.

1. Creare clasa copil


Sub-clasa "copil" se creaza cu formula:
class ClasaCopil extends ClasaParinte
Iata cum se aplica acest procedeu in programarea PHP OOP.
In exemplu prezentat aici se construieste intai o clasa de baza, denumita Site, cu doua proprietati: una cu atribut private (site), alta
cu atribut public (categorie), constructor si o metoda getPag().
<?php
// Clasa Site
class Site {
// Definire proprietati, private si public
private $site;
public $categorie = 'php-mysql';

// Constructor
public function __construct($site) {
// Daca parametru $site e un Sir cu cel putin 5 caractere, atribuie valoarea la proprietatea "site"
// Altfel, seteaza un mesaj de eroare
if(is_string($site) && strlen($site)>4) $this->site = $site;
else throw new Exception('Valoare incorecta pt. site');
}

// Metoda getPag()
public function getPag($pag) {
// Defineste si returneaza adresa URL a paginii
$url = $this->site. '/'. $this->categorie. '/'. $pag;
return $url;
}
}

?>
- Metoda Constructor atribuie valoarea din parametru $site la proprietatea "site".
- Metoda getPag() returneaza o adresa URL formata din proprietatile clasei si parametru ei.
Salvam aceasta clasa intr-un fisier "class.Site.php".
Aceasta clasa poate fi utilizata pentru afisarea unui sir cu o adresa URL, prin apelarea metodei getPag(). Daca vrem sa obtinem
aceasta adresa intr-un tag HTML tip link (<a>) se poate crea o noua metoda, pentru alta facilitate alta metoda, si tot asa se
aglomereaza codul clasei, fapt ce devine o problema in cazul unor clase mari. O alta varianta este crearea unei sub-clase extinse din
aceasta. Sub-clasa (copil) are abilitatea de a mosteni /utiliza toate proprietatile si metodele definite ca publice si protected in clasa
de baza (parinte) ca si cum ar fi create in ea (fara sa mai fie scrise inca o data). Astfel, in clasa copil se creaza doar instructiunile cu
noua functie pe care o dorim, si nici nu mai trebuie modificata clasa parinte.
In continuarea acestui exemplu se creaza o alta clasa, denumita LinkSite, ca extindere a clasei Site. Ea contine doar o metoda
getLink() pentru afisarea unui link.
<?php
include('class.Site.php');

// Include clasa parinte (Site)

// Creare clasa copil LinkSite, extinsa din Site


class LinkSite extends Site {
// Metoda getLink()
public function getLink($pag) {
// Afiseaza un link format din getPag() si "categorie" din clasa parinte
echo '<a href="http://'. $this->getPag($pag). '" title="'. $this->categorie. '">Link</a><br />';
}
}
?>
Salvam aceasta clasa, cu denumirea "class.LinkSite.php" in acelasi director unde e salvata si clasa Site.
Acum, atentie la explicatii:
- Pentru a avea acces la definitiile din clasa principala Site, deoarece se afla intr-un fisier extern, o includem cuinclude().
- Cuvantul special "extends" stabileste identitatea clasei LinkSite ca fiind o extindere a clasei Site.
- In metoda getLink() se folosesc proprietatea "categorie" si metoda "getPag()" din clasa parinte ca si cum ar fi fost definite in
aceasta clasa.
Aceste elemente pot fi accesate in clasa copil deoarece au atribut "public" (functioneaza si cu "protected"). Dar proprietatea
"site", care are atribut "private" in clasa parinte, nu poate fi accesata in cea copil.
- Desi aceasta clasa nu are o metoda constructor, ea mosteneste constructorul clasei parinte, astfel, cand se creaza o instanta de
obiect la clasa LinkSite trebuie adaugat si un argument de tip Sir, deoarece asa e definita metoda "__construct($site)" in clasa de
baza (Site).
Sa testam aceasta clasa copil, cu scriptul urmator.
<?php
include('class.LinkSite.php');

// Include fisierul cu subclasa LinkSite

// Creare instanta la clasa copil LinkSite


$objLink = new LinkSite('www.marplo.net');

// Apeleaza metoda getLink() (definita in clasa copil);


$objLink->getLink('oop-clase-extinse-mostenire.html');

// Modifica valoarea proprietatii "categorie" (aflata in clasa parinte)


$objLink->categorie = 'ajax';

// Afiseaza rezultatul dat de metoda getPag() (creata in clasa parinte)


echo $objLink->getPag('introducere.html');
?>
- Deoarece clasa LinkSite se afla intr-un fisier PHP extern, o includem cu include().
- La crearea instantei de obiect se adauga si argumentul necesar, un sir ('www.marplo.net'), cerut de metoda constructor a clasei de
baza, care e si ea mostenita.

- Observati cum sunt accesate proprietatea "categorie" si metoda "getPag()" (care se afla in clasa parinte), prin instanta de obiect la
clasa copil (LinkSite) ca si cum ar fi create in ea. Acesta este efectul mostenirii, atat de util in OOP.
In browser va afisa urmatorul rezultat:
Link
www.marplo.net/ajax/introducere.html

2. Redefi nire metode


In exemplu de mai sus, clasa copil LinkSite a mostenit si metoda "__construct()" din clasa parinte Site, fapt ce determina
executarea codului din acel Constructor si cand e creata instanta la clasa copil. Uneori aceasta functie nu e adecvata in sub-clasa.
Pentru a evita acest lucru, metodele inadecvate pot fi rescrise prin adaugarea uneia cu acelasi nume in clasa copil, astfel, la
crearea instantei, va fi utilizata metoda, cu acelasi nume, din clasa copil.
- Rescrierea unei metode nu afecteaza cu nimic pe cea originala, modificarile efectuate sunt valabile doar in clasa copil in care se
face rescrierea, respectiv, in alte sub-clase ale ei.
Iata o alta sub-clasa (PagSite) extinsa din Site. Aici se adauga si o metoda "__construct()" care o va anula pe cea din clasa parinte,
se rescrie si metoda getPag().
<?php
include('class.Site.php');

// Include clasa parinte (Site)

// Creare clasa copil PagSite, extinsa din Site


class PagSite extends Site {
public $domeniu = 'marplo.net';

// Proprietate

// Constructor, rescrie pe cel din parinte (Site)


function __construct() {
// Fara instructiuni, executa nimic
}

// Metoda getPag(), rescrisa


public function getPag($pag) {
// Preia functionalitatea metodei getPag() din clasa parinte
$url = parent::getPag($pag);

// ... alte instructiuni pt. metoda getPag()

// Adauga in $url si valoarea proprietatii "domeniu"


$url = $this->domeniu. $url;

return 'Pagina: '. $url;


}
}
?>
- Prin crearea in aceasta sub-clasa a metodei "__construct()" se anuleaza efectul celei din clasa parinte, si neavand parametru, nici
la creare instantei nu se mai adauga vreun argument.
- Pentru a pastra si functionalitatea initiala (din clasa parinte) a metodei rescrise, in corpul functie care face rescrierea, se adauga cu
formula parent::nume_metoda() (tehnica folosita si in exemplu de sus, la getPag()).
In scriptul urmator se foloseste aceasta a doua sub-clasa.
<?php
include('class.PagSite.php');

// Include fisierul cu aub-clasa PagSite

// Creare instanta la clasa copil PagSite


$objPag = new PagSite();

// Modifica valoarea proprietatii "categorie" (aflata in clasa parinte)


$objPag->categorie = 'html';

// Afiseaza rezultatul dat de metoda getPag() (rescrisa)


echo $objPag->getPag('introducere.html');
?>
- Instructiunea $objPag->getPag('introducere.html') apeleaza metoda "getPag()" din clasa la care s-a creat instanta de obiect
(PagSite) deoarece exista cu aceasta denumire in ea. Se observa si din rezultatul afisat:
Pagina: marplo.net/html/introducere.html

3. Metode fi nale
In exemplu prezentat mai sus se vede cum o metoda din clasa de baza poate fi rescrisa in sub-clasa copil, dandu-i alta
functionalitate. Sunt situatii in care nu se doreste ca o metoda sa poata fi rescrisa, in acest caz, prin adaugarea cuvantului final la
inceputul declararii metodei se blocheaaaza posibilitatea rescrierii ei.
- De exemplu:
<?php
// Clasa Baza
class Baza {
// Metoda final
final public function numeMet() {
// Instructiunile functiei
}
}

// Definire clasa-copil din Baza


class CopilBaza extends Baza {
// Rescriere metoda numeMet()
public function numeMet() {
// Alte Instructiuni
}
}
?>
- Va genera eroarea:
Fatal error: Cannot override final method Baza::numeMet() in ...
- Deoarece metoda "numeMet()" este declarata cu atribut "final".

4. Clase fi nale
Precum metodele declarate cu "final" nu mai pot fi modificate in sub-clasa copil, asa se pot crea si clase care sa ramana fixe,
fara sa se poata crea din ele alta sub-clasa. Acest lucru se obtine prin adaugarea cuvantului final inainte de class.
- De exemplu:
<?php
// Clasa Baza
final class Baza {
// ... Instructiuni
}

// Definire clasa-copil din Baza


class CopilBaza extends Baza {
// ... Alte Instructiuni

}
?>

Metode magice __get, __set, __call, __toString


In Programarea Orientata pe Obiecte (OOP) din PHP exista cateva metode mai speciale, care incep cu "__" (doua caractere '_'),
precum __construct(). Acestea sunt numite generic Metode Magice (Magic Methods) si se executa automat in situatii mai
speciale, cum ar fi de exemplu __get() pentru accesari de proprietati inexistente.
In aceasta lectie sunt prezentate cateva din cele mai folosite astfel de metode: __get(), __set(), __call() si__toString().
- Toate aceste metode magice trebuie sa fie definite cu atribut public.

1. Metode __get si __set


Metodele magice: __get() si __set() se folosesc de obicei impreuna si sunt create pentru lucru cu proprietati care nu sunt
definite.

__get($name) - E apelata automat cand se acceseaza o proprietate care nu exista. Preia numele ei in parametru $name.
__set($name, $value) - Se apeleaza automat cand se atribuie o valoare unei proprietati care nu exista. Preia numele ei
in parametru $name si valoarea in parametru $value.

Iata un exemplu din care se intelege mai bine rolul lor. O clasa in care sunt folosite aceste metode, se creaza o instanta de obiect la
ea apoi e accesata o proprietate inexistenta.
<?php
// Definire clasa AClas
class AClas {
// Proprietate care va retine valori atribuite unor proprietati nedeclarate
public $prop = array();

// Metoda magica __get() (pt. accesari proprietati nedefinite)


public function __get($name) {
// Daca exista element cu cheia '$name' in $prop, afiseaza valoarea lui
// Altfel, mesaj ca proprietatea nu exista
if(array_key_exists($name, $this->prop)) echo $this->prop[$name]. '<br />';
else echo 'Proprietatea <b>'. $name. '</b> nu exista.<br />';
}

// Metoda magica __set() (pt. cand se atribuie valori unor proprietati nedefinite)
public function __set($name, $value) {
// Adauga in $prop element cu cheia $name si valoarea value
$this->prop[$name] = $value;
echo 'Proprietatea <b>'. $name. '</b> nu exista. S-a atribuit valoarea <i>'. $value. "</i> la proprietatea:
<b>prop['$name']</b><br />";
}
}

// Creare instanta de obiect la clasa AClas


$obj = new AClas();

// Apelare proprietate neexistenta


$obj->noprop;

// Va determina executia metodei __get()

// Atribuire valoare la proprietate inexistenta


$obj->noprop = 'Valoare pt. noprop - PHP OOP';

// Va determina executia metodei __set()

// Apelare din nou a aceleiasi proprietati neexistente


$obj->noprop;

// Va determina executia metodei __get()

// Se verifica direct si elementul pe care-l creaza __set()


echo 'Verificare: '. $obj->prop['noprop'];
?>
- $prop e definita ca tip Array ca sa stocheze, prin metoda __set(), valorile atribuite unor proprietati nedefinite.
- Cand prin instanta de obiect la clasa e accesata o proprietate care nu exista ($obj->noprop;), se executa automat metoda __get().
Aici e definita sa verifice in $prop daca are element cu cheia $name (numele proprietatii accesate), daca exista acel element,
afiseaza valoarea lui, altfel, afiseaza un mesaj.
- Cand se atribuie o valoare la proprietatea nedefinita ($obj->noprop = '...';), se executa automat metoda __set(). Aici e definita sa
adauge in $prop un element cu numele proprietatii (cheie) si valoarea transmisa.
Vedeti si explicatiile din cod.
- Acest script va afisa urmatorul rezultat:
Proprietatea noprop nu exista.
Proprietatea noprop nu exista. S-a atribuit valoarea Valoare pt. noprop - PHP OOP la proprietatea:prop['noprop']
Valoare pt. noprop - PHP OOP
Verificare: Valoare pt. noprop - PHP OOP

2. Metoda __call
Metoda magica __call() e creata pentru cazuri cand sunt apelate metode inexistente. Sintaxa ei este:
__call($nume, $array_argumente)
- $nume reprezinta numele metodei apelate
- in $array_argumente sunt retinute intr-un Array argumentele adaugate la apelarea metodei.
In urmatorul exemplu e definita o astfel de metoda "__call()" care afiseaza un mesaj cu numele metodei inexistente care a fost
apelata si argumentele transmise.
<?php
// Definire clasa AClas
class AClas {
// Metoda magica __call() (pt. apelari metode nedefinite)
public function __call($name, $args) {
// Afiseaza un mesaj cu numele metodei apelate si argumentele transmise
echo 'Metoda <b>'. $name. '</b> nu exista. Argumente: <i>'. implode(', ', $args). '</i>';
}
}

// Creare instanta de obiect la clasa AClas


$obj = new AClas();

// Apelare metoda inexistenta


$obj->site('cursuri', 'tutoriale');

// Va determina executia metodei __call()

?>
- In browser va afisa:
Metoda site nu exista. Argumente: cursuri, tutoriale
Incepand cu PHP 3.0 e adaugata o metoda similara, __callStatic(), aceasta se executa automat cand e apelata o metoda statica
nedeclarata, prin formula: NumeClasa::metodaStatica()

3. Metoda __toString
Cu metoda __toString() se determina modul de reactie a clasei cand instanta de obiect la ea este folosita ca o variabila de tip
sir (String), de exemplu cu "echo".
In urmatorul exemplu e definita o clasa cu o metoda __construct() si una "__toString()" care afiseaza valoarea unei proprietati
"mesaj".
<?php
// Definire clasa AClas

class AClas {
private $mesaj;

// Proprietate

// Metoda Constructor
public function __construct($mesaj) {
// Atribuie valoarea din parametru la proprietatea "mesaj"
$this->mesaj = $mesaj;
}

// Metoda magica __toString()


public function __toString() {
return $this->mesaj;

// Returneaza valoarea proprietatii "mesaj"

}
}

// Creare instanta de obiect la clasa AClas


$obj = new AClas('Fii bine primit');

// Apelare instanta, ca pe o variabila de tip String


echo $obj;

// Va determina executia metodei __toString()

?>
- In browser va afisa:
Fii bine primit
- Fara metoda __toString() adaugata in clasa, accesarea instantei de obiect simpla, cu "echo" sau "print" genereaza o eroare de
genul:
Catchable fatal error: Object of class AClas could not be converted to string in ...
Mai sunt si alte metode magice, mai putin folosite, cum ar fi: __isset (se apeleaza cand e verificata cu "isset()" o proprietate
inexistenta), __invoke (se executa cand instanta de obiect e apelata ca o functie), si altele; le puteti gasi la pagina oficiala
PHP.net Metode Magice

OOP - Clase abstract si interface


Abstract si Interface (interfata) sunt tipuri de clase mai speciale in OOP, pentru lucru mai avansat in programarea orientata
pe obiecte.

1. Clase si Metode abstract


Clasele abstracte se declara folosind cuvantul abstract inaintea lui "class".
La aceste tipuri de clase nu se poate crea instanta de obiect, ele pot fi doar mostenite de alte clase extinse din ele.
In clasele abstracte se definesc si metode abstracte, acestea se declara cu acelasi cuvant "abstract" si fara corpul de acolade,
doar numele si parantezele rotunde, cu parametri necesari.
- Iata un exemplu de clasa cu o proprietate "protected" o metoda abstracta si una accesor:
<?php
// Definire clasa abstracta
abstract class Fructe {
protected $color;

// Proprietate

// Definire metoda abstracta


abstract function Stoc($luna);

// Metoda accesor pt. "color"


public function setColor($c) { $this->color = $c; }

}
?>
- Daca se creaza o instanta de obiect la aceasta clasa (de ex.: $obj = new Fructe();), va genera eroare de genul:
Fatal error: Cannot instantiate abstract class
- Metodele abstracte se creaza doar in clase abstracte.
- Rolul claselor si metodelor abstracte este acela de a crea un model minim de metode obligatorii care trebuie definite in sub-clase
normale derivate din ele (cu extends). Metodele abstracte definite in cea parinte trebuie create in orice clasa copil extinsa din cea
abstracta, cu acelasi numar de parametri (numele poate fi difereit).
De ex., orice sub-clasa extinsa din clasa Fructe (definita mai sus) trebuie sa contina metoda Stoc() cu un parametru, cum ar fi cea
din urmatorul exemplu, denumita Mere.
<?php
// Definire clasa copil, extinsa din cea abstracta
class Mere extends Fructe {
private $kg;

// Proprietate

// Metoda obligatorie (seteaza valoarea proprietatii "Kg")


public function Stoc($kg) {
$this->kg = $kg;
}

// Alta Metoda - optionala (returneaza valoarea proprietatii "kg")


public function getKg() {
return $this->kg. ' kg';
}
}
?>
- Deoarece clasa Mere extinde Fructe, trebuie sa contina, pe langa alte elemente, si metodele abstracte declarate in aceea (anume
Stoc(), cu un parametru). Daca aceasta sub-clasa nu ar avea metoda Stoc(), va genera eroare de genul:
Fatal error: Class Fructe contains 1 abstract method and must therefore be declared abstract or implement the remaining methods
(Mere::Stoc) in...
- Sub-clasele care extind o clasa abstracta pot fi utilizate normal, se pot crea si folosi instante de obiect la ele, mostenesc si pot
folosi elementele cu atribut "public" si "protected" din cea parinte.
De exemplu:
<?php
// Creare instanta de obiect la clasa Mere si apelare metode
$obj = new Mere();
$obj->Stoc(78);
echo $obj->getKg();

// Afiseaza: 78 kg

?>

2. Interfaces
Ca rol, se poate spune ca Interface este asemanatoare cu clasa "abstract".
Clasa Interface este folosita ca tipar, sau template pentru clase cu functii similare, care trebuie sa respecte o anumita structura
de metode.
Sintetizat, Interface este o clasa cu o lista de metode obligatorii ce trebuie sa fie create in clasele unde este implementata. Toate
metodele specificate in "Interface" sunt cu atribut public si trebuie sa fie definite in clasele in care e aplicata, avand acelasi numar
de parametri cati sunt indicati in "Interface".
Creare interface
Clasa interface se creaza similar cu celelalte tipuri de clase. Diferenta e aceea ca la definirea ei, in loc de cuvantul "class" se
foloseste cuvantul "interface"; in plus, in corpul ei se scrie doar o lista cu metode publice fara, alt cod.
Sintaxa generala este urmatoarea:

interface numeInterfata {
public function numeMetoda();
public function altaMetoda()
...........
}

- La declararea metodelor in Interface nu se adauga acoladele sau codul lor, si nici alt atribut diferit de "public".
Iata un exemplu cu o Interface, denumita "ITest", in care sunt definite 2 metode: "Links()" si "Tutoriale()".
<?php
// Definire Interface ITest
interface ITest {
// Lista cu metode
public function Links();
public function Tutoriale($str, $nota);
}
?>
Implementare interface
Dupa ce a fost definit tiparul "interface", se pot crea clase care implementeaza metodele stabilite in acel tipar, respectand si
numarul de parametri.
Implementarea se face adaugand cuvantul implements si numele Interfatei la definirea claselor, dupa numele lor.
class NumeClasa implements numeInterfata {
// Instructiuni
}
Acestea trebuie sa contina in corpul lor toate metodele definite in "interface", cu atribut "public", si numarul de parametri stabiliti
pt. fiecare (numele la parametri poate fi diferit). Pe langa acestea pot contine si alte metode.
Iata un exemplu cu o clasa care implementeaza interfata ITest creata mai sus.
<?php
// Creare clasa care aplica Interfata ITest
class WebDevelopment implements ITest {
// Definire proprietate 'link' (cu atribut "protected")
protected $link = 'www.marplo.net';

/* Definire metodele obligatorii (Links si Tutoriale), din interface */

// Returneaza valoarea proprietatii 'site'


public function Links() {
return $this->link;
}

// Returneaza valoarea unei variabile din ea ($re), ce preia argumentele transmise


public function Tutoriale($gen, $nota) {
$re = $gen. '-'. $nota;
return $re;
}

// Se pot crea si alte metode, suplimentare


// Aceasta modifica valoare proprietatii "link"
public function setLink($link) {
$this->link = $link;
}
}
?>

- Metodele obligatorii (aici "Links()" si "Tutoriale()") respecta exact numarul de parametri stabiliti in "interface" "ITest". Alte metode
(aici "setLink()") si proprietati sunt optionale, in functie de rolul fiecarei clase.
- Numele parametrilor nu conteaza (observati ca in loc de $str s-a folosit $gen), dar numarul lor trebuie sa fie aceleasi ca in
"interface".
- Daca vreuna din conditii nu ar fi respectata in clasa, cum ar fi: nedefinirea unei metode, adaugarea de parametru in plus sau
minus; scriptul genereaza eroare.
Astfel, implementarea de "interface" este utila mai ales cand sunt create mai multe clase cu roluri similare si dorim ca acestea sa
aibe toate o anumita ordonare si structura minima de metode, mai usor de retinut.

3. Interface ca tip de date


Interfata poate fi utilizata si ca tip de data la parametri de functii, astfel, acel parametru poate fi utilizat ca instanta de obiect la
orice clasa din cele ce folosesc acea "interface".
Se intelege mai bine din urmatorul exemplu, in care e creata si folosita inca o clasa (LimbiStraine) ce aplica Tiparul din "ITest";
contine o proprietate si metodele obligatorii stabilite.
<?php
// Creare clasa care aplica Interfata ITest
class LimbiStraine implements ITest {
// Definire proprietate
protected $adr = 'www.marplo.net/';

/* Definire metodele obligatorii (Links si Tutoriale), din interface */

// Returneaza expresia 'Cale buna'


public function Links() {
return'Cale buna';
}

// Returneaza valoarea unei variabile din ea (re), ce preia argumentele "nr", "gen" si proprietatea "adr"
public function Tutoriale($gen, $nr) {
$re = $nr.'-'. $this->adr. $gen;
return $re;
}
}
?>
Intr-un script PHP se scrie urmatorul cod:
<?php
// Se includ fisierele cu clasele create mai sus (daca sunt in fisiere externe): ITest (Interfata), WebDevelopment si LimbiStraine
include('interf.ITest.php');

// Interface

include('class.WebDevelopment.php');
include('class.LimbiStraine.php');

// Creare functie care accepta doar argument cu obiect la clasele care au implementata Interfata "ITest"
function cursuri(ITest $obj) {
// Apeleaza metodele comune (stabilite in ITest) prin parametru $obj
echo '<br />'. $obj->Links();
echo '<br />'. $obj->Tutoriale('php-mysql', 4);
}

// Creare instante de obiect la clasele folosite

$web_development = new WebDevelopment();


$limbi_straine = new LimbiStraine();

// Apeleaza functia cu instantele de obiect ale claselor ce au aplicat ITest


cursuri($web_development);
cursuri($limbi_straine);

// "www.marplo.net" si "php-mysql-4"
// "Cale buna" si "4-www.marplo.net/php-mysql"

?>
- Functia "cursuri()" creata cu aceasta formula intre acolade "function cursuri(ITest $obj)" face ca ea sa accepte ca argument doar
obiect care are implementat "ITest".
- Observati ca apeland functia cu argumente diferite, reprezentand numele instantelor la clase, foloseste parametru $obj ca instanta
la clasa respectiva, si poate apela aceleasi metodele ("Links()" si "Tutoriale()") pt. fiecare deoarece aceste fiind specificate in
"interface" ele trebuie sa existe in fiecare clasa ce apartine acelei Interfate, cu acelasi numar de parametri.
- Prin aceasta tehnica nu mai e nevoie de a crea aceeasi functie pt. fiecare instanta.
Acest exemplu va afisa in browser urmatorul rezultat:
www.marplo.net
php-mysql-4
Cale buna
4-www.marplo.net/php-mysql