duminică, 28 octombrie 2012

Povestea porcilor mei trişti

Ce e respectul şi cum să câştigă el? 

Mergi pe stradă şi te trezeşti împroşcat, la propriu, cu noroi, din cap până-n picioare. Evident, nu-ţi convine, dar cine-i de vină? Idiotul de la volan, căruia i se rupe, efectiv, de toate gângăniile care se deplasează per pedes? Nu, nici vorbă, nu poate fi vorba despre el, la urma-urmei nici nu te cunoaşte, ce motiv ar avea să nu te respecte? Şi, ce căutai pe carosabil? Că, da, nu erai pe trotuar, coborâseşi pe carosabil. Adică, tu să nu respecţi regulile, dar alţii să le respecte. Eşti respectabil, nu? Vai de capul tău! Dacă ai fi, n-ai umbla pe jos ...

Atunci, poate că e domnu’ de la Primărie, ăla care trebuia să se ocupe de drumuri. Să astupe gropile, să cureţe canalizarea. Mai ales că ăla te şi cunoaşte. Acu’ câteva luni a dat mâna cu tine, ţi-a spus două vorbe frumoase, şi ţi-a dat şi un pliant colorat. Da, dar asta era acum câteva luni, atunci era campanie, acum nu mai e. Acum nu te mai cunoaşte. Dacă vrei să te cunoască din nou, n-ai decât s-aştepţi următoarea campanie. 

Da’ şi dacă te-ar cunoaşte, ce-ar fi? Chiar, ce-ar fi? N-ar fi nimic. Sau, poate că tocmai de aia. Tocmai că te cunoaşte, şi ştie câte parale faci, de-aia nici nu se sinchiseşte. Când a fost cu vizita lu’ nu-ştiu-cui, ce-a făcut? A reparat bulevardul central, a curăţat pomii, a pus flori. Tocmai pentru că ăla era un om, o valoare. Tu, ce valoare ai? Tu eşti un vierme.
Drept e că şi domnu’ cu crâşma, dacă nu-şi scotea tot calabalâcul pe trotuar, ai fi putut să mergi mai aproape de zid, şi astfel ai fi scăpat. Nu te-ar mai fi împroşcat ăla cu maşina. Sau, nu în halul în care a făcut-o.

Cum, Doamne, să mergi mai spre zid? Şi cu maşinile parcate acolo de facem? Da, ce facem? ... Ei, vezi că eşti prost? 

Oriunde mergi, dai de indivizi care nu te respectă nici măcar cât negru sub unghie. Dar asta nu e, desigur, din vina lor, ci dintr-a ta. Tu eşti cel care nu merită să fie respectat. Tu eşti cel care le ceri, practic, să nu te respecte. 

Când nu ai ce oferi, nu ai nici ce cere. Cum vrei să fii văzut ca un om, când eşti doar un gândac? 

Ţi-e ciudă pe ăla cu maşina, tu de ce umbli pe jos? 

Ţi-e ciudă pe ăla de la primărie, da’ pe ăla l-au ales oamenii, pe tine cine te-a ales? Poate nevastă-ta, dar nici asta nu-i sigur.

Ţi-e ciudă pe ăla cu crâşma, că a făcut avere.

Ţi-e ciudă pe toţi şi pe toate, te plângi că nu te respectă nimeni, dar tu ce faci pentru a le câştiga respectul? Fiindcă respectul nu se impune, ci se câştigă, nu-i aşa? 

Şi, tu ce-ai făcut ca să câştigi respectul oamenilor? 

Nu te respectă vecinii de bloc? Mută-te la vilă. 

Nu te respectă funcţionarii? Dă-le mită. Dacă tot nu te respectă, dă-le mai multă mită. 

Nu te respectă tipul ăla cu maşină de 20.000 de euro, cumpărată cu 7.000, la mâna a doua? Cumpără-ţi tu una de 50.000 de euro, la mâna a treia. 

Nu te respectă cârciumarul din colţ? Fă-i o consumaţie serioasă, măcar o dată pe săptămână.

Mergi pe stradă şi nu te salută oamenii? Da’, cine eşti tu, ce vrei şi de ce să te salute oamenii? Mai du-te şi tu pe la televiziuni, apari pe sticlă măcar ca Ogică, dacă nu ca domnu’ Dan, şi-o să vezi c-o să-ţi ceară şi autograf. 

Nu te mai respectă nici soţia? Ia-ţi o amantă cu treij’ ani mai tânără, bagă o sută de mii de euro în curu’ ei, şi-o să vezi că o să înceapă să te respecte şi soţia. 

Nici măcar copiii nu te (mai) respectă? Da’ vilă şi maşină le-ai luat? Ia-le vilă şi maşină, bagă-i în ceva funcţii mari, şi-o să vezi ce te vor respecta.

Da’ tu n-ai făcut nimic din toate astea. Şi-atunci, de ce să fii respectat? 

Eu cred că respectul nu se câştigă. Eu cred că respectul nu se poate câştiga. Cum să-l câştigi? Să dai vreun examen, sau cum?

Acordând tu însuţi respect? Făcând, pe cât posibil, numai fapte bune, şi evitând cu străşnicie răul? Să nu greşeşti? Ei, nu zău? 

Păi, dacă ar fi aşa, să-mi explice un creştin, Hristos cu ce-a greşit? Pe cine-a jignit şi cui a făcut rău? Şi, de-aia, tot l-au răstignit. De ce?

Ei, problema cu respectul e cam aşa: respectul îl ai sau nu-l ai, şi îl acorzi sau nu îl acorzi, după cum vrei tu, nu după cum îl câştigă sau nu celălalt. Mergi pe stradă, întâlneşti un om, şi ce faci? Dacă ţi-a câştigat respectul, il saluţi, iar dacă nu, îi spui: „îmi pare rău, nu mi-ai câştigat respectul, prin urmare, nu te salut”? Sau, îl saluţi oricum, dacă eşti tu însuţi educat ... iar dacă nu, nu?

Respectul nu înseamnă favoruri, nu înseamnă iubire, nu înseamnă indulgenţă, înseamnă educaţie şi, până la urmă, normalitate şi corectitudine. Dacă un individ nu îţi este deloc simpatic, dacă e murdar, bolnav, sau tâmpit, nimeni nu-ţi cere să îl iubeşti sau să faci sluj, dar să te porţi normal şi să fii corect, ţi-o cer: educaţia, caracterul ... dacă le ai, fireşte. Dacă nu, nu.

Iar dacă nu poţi, şi nu poţi, şi nu poţi ... să respecţi pe cineva, atunci, încearcă măcar să nu mai spui idioţenia aia cu respectul care se câştigă, nu se impune. Fiindcă, dacă un anume om nu a reuşit să câstige respectul tău, asta nu înseamnă că nu se bucură de respect din partea nimănui. Dimpotrivă, se bucură de respectul tuturor persoanelor care sunt capabile să acorde respect ... ceea ce nu e cazul tău.

Atât despre oameni, dar în jur nu sunt  numai oameni. Când arunci o hârtie pe jos, sau cand tai un pom, nu e vorba de oameni, e vorba de mediu. Cu ar putea mediul să-ţi câştige respectul, dacă nu poate un om? 

Respectul pe care îl acorzi (sau nu) altora reflectă respectul pe care ţi-l acorzi ţie însuţi.   

Sunt oameni care nu te respectă? Consolează-te, tuturor li se intâmplă asta, uneori chiar prea des. Crezi că respectul se câştigă? Atunci, câştigă respectul unui porc. Va trebui să te bălăceşti în noroi, alături de el, dar nici atunci nu e sigur că te va respecta. Mai degrabă, îţi vei pierde şi respectul pe care ţi-l acorzi tu însuţi. Indiferent ce vei spune, şi ce indiferent ce vei face, un porc nu te va respecta niciodată, pentru că, din momentul în care o va face, nu va mai fi. Sau, nu va mai fi aşa de porc.  

Un porc, un adevărat porc, nu e niciodată trist. Poate speriat, hăituit, îngrozit, sau bolnav, dar trist, nu. Meditativ, îngândurat, năpădit de regrete? Nu, nu, niciodată. Porcii trişti nu trăiesc decât în poveşti.  Viaţa noastră cea de toate zilele e plină, in schimb, de porci veseli şi bine-dispuşi, pasionaţi de lături şi tăvălit prin noroi. Poate, de aia ne plac unora poveştile. 

Deja, ai citit până-aici? Atunci, te salut cu respect ... şi te mai aştept pe aici.

vineri, 26 octombrie 2012

Emularea polimorfismului în PHP


        Supraîncarcarea (overloading) si redefinirea/suprascrierea (overridding) reprezinta cele doua forme de manifestare ale polimorfismului, unul din cele trei concepte-cheie ale paradigmei obiectuale în programare.
        Supraîncarcarea reprezinta capacitatea unei functii/metode sau a unui operator de a se adapta dinamic unui anumit context. Pentru a întelege mai bine acest concept, voi folosi o metafora din lumea înconjuratoare. Sa presupunem ca un „obiect medical” este înzestrat cu „metoda” „acorda primul ajutor”. În functie de contextul în care se aplica, aceasta metoda poate însemna cu totul si cu totul altceva, de exemplu masaj cardiac, respiratie artificiala, oprirea hemoragiei, sau multe alte lucruri. În viata de toate zilele spunem ca expresia sau cuvântul care defineste „metoda” noastra este polisemantic – are mai multe întelesuri, care depind, evident, de context. Tot astfel, în programarea orientata pe obiecte, o functie – voi folosi, în continuare, acest termen, deoarece el este uzitat în PHP – este supraîncarcata daca „stie” sa faca mai multe lucruri, în functie de context. Aceasta presupune fie faptul ca poate primi parametri de diferite tipuri, fie ca poate primi un numar variabil de parametri, fie amândoua. Sa presupunem, de exemplu, ca avem o functie scurteaza() care, daca primeste un parametru numeric real, extrage partea sa întreaga (deci scurteaza(3.14) == 3), iar daca primeste un string, elimina spatiile goale (deci scurteaza( ”un text oarecare”) == ”untextoarecare”) – acesta este un exemplu de functie care „stie” sa faca lucruri diferite în functie de tipul parametrului primit. Un exemplu de functie care accepta un numar variabil de parametri este usor de imaginat, de exemplu o functie aduna() ar putea fi conceputa astfel încât sa accepte oricâti termeni.
        Suprascrierea reprezinta capacitatea unei functii mostenite a unui obiect de a face altceva decât functia similara din clasa parinte. De exemplu, considerând clasa ”lumea vie”, vom constata ca trebuie sa îi implementam o functie de „hranire”, fiindca orice instanta a ei – adica orice organism viu – are aceasta functie. Presupunând ca am alcatuit o ierarhie de clase în care clasa lumea_vie a fost extinsa succesiv, astfel încât a rezultat o ierarhie de clase precum lumea_vie => lumea_animala => vertebrate => mamifere => hominide => om, vom constata ca functia „hranire” a clasei „om”, chiar daca „mosteneste” anumite caracteristici (=comportament) functia similara a clasei parinte, trebuie, totusi, sa îl modifice, pentru a implementa „abilitatea” omului de a se hrani cu alimente procesate, ca si pentru a renunta la unele deprinderi precum a ceea de a scuipa cojile semintelor pe jos. În acest sens, în functie de modul în care este conceputa, functia „hranire” a omului va prelua o parte din „codul” functiei „hranire” a hominidelor, va renunta la alta parte, si va modifica o alta parte. Putem sa ne imaginam, de asemenea, ca din clasa „lumea_vie” deriva si clasa „lumea_vegetala”, care, bineînteles, trebuie sa aiba definita si ea functia „hranire”. Numai ca diferentele între ceea ce se întelege între a „hrani” o planta (de ex. a o stropi, de a o orienta spre soare etc.) si a „hrani” un animal sunt atât de mari, încât, poate ca nu exista niciun element comun, care sa poata fi mostenit atât de clasa „lumea_animala”, cât si de clasa „lumea_vegetala”. În acest caz, solutia este aceea a definirii unei functii abstracte (si implicit, declararea ca abstracta a clasei „lumea_vie”), fara niciun fel de cod, lasând claselor derivate responsabilitatea de a defini, în mod concret, functia „hranire”. În alte cuvinte, functia „hranire” nu spune si nu face nimic despre ea însasi în clasa „lumea_vie”, dar obliga orice „obiect” de acest fel sa aiba o astfel de functie, care sa fie (re)definita în clasa de care apartine: toate organismele vii (= instante ale unor clase concrete derivate din clasa „lumea_vie”) sunt „obligate” sa se „hraneasca”, dar, ce înseamna, la modul concret, pentru fiecare organism viu în parte, este definit la nivelul clasei de care apartine.
        Dupa cum se stie, PHP nu a fost conceput, de la bun început, ca un limbaj obiectual, ci ca unul structural, adica unul in care codul este scris respectând paradigma programarii structurate Böhm-Jacopini. De aceea, creatorii limbajului PHP au ales sa îl faca loosely-typed, pentru un spor de versatilitate si eficienta. Pe de alta parte, aceasta optiune a facut, practic, imposibila, supraîncarcarea functiilor, cel putin pe baza tipului parametrilor.
        Sa consideram urmatorul exemplu:
<?php
class test {
    public function afiseazaMesaj1($un_parametru) {
        echo "Apelul functiei pentru un parametru: $un_parametru! <br/>";
    }

    public function afiseazaMesaj2($par1, $par2) {
        echo "Apelul functiei pentru doi parametri: $par1 $par2";
    }
}

$obj1 = new test;
$obj1->afiseazaMesaj1('Salut');
$obj1->afiseazaMesaj2('Salut,','lume!');
?>
        Dupa cum, probabil va asteptati, acest exemplu functioneaza perfect în PHP, producând iesirea:
Apelul functiei pentru un parametru: Salut! 
Apelul functiei pentru doi parametri: Salut, lume!
        Desigur, în acest exemplu nu este vorba de niciun polimorfism, ci, pur si simplu, de doua functii diferite, afiseazaMesaj1() si afiseazaMesaj2(), prima primind un parametru, cealalta doi parametri.
        Modificând putin acest exemplu, în sensul redenumirii functiilor afiseazaMesaj1() si afiseazaMesaj2() cu acelasi nume, afiseazaMesaj(), ca în exemplul de mai jos:
<?php
class Test {
    public function afiseazaMesaj($un_parametru) {
        echo "Apelul functiei pentru un parametru: $un_parametru! <br/>";
    }

    public function afiseazaMesaj($par1, $par2) {
        echo "Apelul functiei pentru doi parametri: $par1 $par2";
    }
}

$obj = new test;
$obj->afiseazaMesaj('Salut');
$obj->afiseazaMesaj('Salut,','lume!');
?>
primim eroarea fatala:
Fatal error: Cannot redeclare test::afiseazaMesaj() in ....
asta în timp ce codul similar din din Java:
public class transpusPHP {
 public static void main(String[] args) {
  transpusPHP obiect = new transpusPHP();
  obiect.afiseazaMesaj("Salut!");
  obiect.afiseazaMesaj("Salut, ","lume!");
 }
 public void afiseazaMesaj(String par){
  System.out.println(par);
 }
 public void afiseazaMesaj(String par1, String par2){
  System.out.print(par1);
  System.out.println(par2);
 }
}
functioneaza fara cusur si returneaza:
Salut!
Salut, lume!
        Cum putem rezolva aceasta problema?
        O prima idee este aceea de a folosi o functie cu parametri impliciti. PHP permite utilizarea functiilor cu parametri impliciti, al caror antet arata astfel:
function ($par_1, ..., $par_i, $par_j = val_j, ... , par_n = var_n){
//cod PHP
}
        Apelul unei astfel de functii se face pentru cel putin i parametri ($par_i este ultimul parametru care nu este definit implicit) , si pentru cel mult n. Daca parametrii care urmeaza dupa par_i (par_j si celialti) nu sunt definiti în mod explicit, atunci se folosesc valorile implicite corespunzatoare, iar daca, la un moment dat, un parametru este definit implicit, toti parametrii care urmeaza (pâna la n) sunt definiti implicit
        Cu ajutorul parametrilor impliciti, am putea implementa supraîncarcarea astfel:
<?php
class Test { 
    public function afiseazaMesaj($par1='', $par2='', $par3='') {
  if ($par3){
   echo "Apelul functiei pentru trei paramentri: 
/**/ $par1 $par2 $par3 <br/>";
  } elseif ($par2) {
   echo "Apelul functiei pentru doi parametri: 
/**/ $par1 $par2<br/>";
  } elseif ($par1) {
   echo "Apelul functiei pentru un parametru: 
/**/ $par1 <br/>";
  } else {
   echo "Nu a fost transmis niciun parametru <br/>";
  }
 }
}

$obj = new Test;
$obj->afiseazaMesaj('Salut');
$obj->afiseazaMesaj('Salut,','lume!');
$obj->afiseazaMesaj('Primul parametru, ', 'Al doilea, ', 'Al treilea');
$obj->afiseazaMesaj();
?>
        Efectul executiei programului este urmatorul:
Apelul functiei pentru un parametru: Salut 
Apelul functiei pentru doi parametri: Salut, lume!
Apelul functiei pentru trei paramentri: Primul parametru,  Al doilea, Al treilea 
Nu a fost transmis niciun parametru
        Principalele probleme pe care le ridica o astfel de abordare sunt urmatoarele:
  • Daca o un parametru nu este definit, sau are o valoare egala cu cea implicita, atunci toti parametrii care îi urmeaza primesc valorile implicite.
  • Nu putem, în acest fel, sa implementam functii care accepta oricât de multi parametri.
        O alta abordarea poate viza utilizarea functiei magice __call(), ca în exemplul urmator:
<?php
class Test
{
    public function __call($nume, $parametri)
    {
  $nr_parametri = sizeof($parametri);
  if ($nr_parametri){
   if ($nr_parametri == 1) {
    echo "Apelul functiei $nume pentru un 
/**/singur parametru: ";
   } elseif ($nr_parametri == 2) {
    echo "Apelul functiei $nume pentru 
/**/doi parametri: ";
   } else {
    echo "Apelul functiei $nume pentru 
/**/$nr_parametri parametri: ";
   } 
  } else {
   echo "Nu ati introdus niciun parametru.";
  }
        
  foreach ($parametri as $cheie => $valoare){
    echo $valoare;
  }
  echo "<br/>";
    }   
}
$obj = new Test;
$obj->afiseazaMesaj('Salut, ','lume!');
$obj->afiseazaMesaj('Salut!');
$obj->afiseazaMesaj('Salut, lume!');
$obj ->afiseazaMesaj('Primul parametru ', 'Al doilea parametru ', 
/**/'Al treilea parametru');
$obj->afiseazaMesaj();
?>
        Programul va afisa:
Apelul functiei afiseazaMesaj pentru doi parametri: Salut, lume!
Apelul functiei afiseazaMesaj pentru un singur parametru: Salut!
Apelul functiei afiseazaMesaj pentru un singur parametru: Salut, lume!
Apelul functiei afiseazaMesaj pentru 3 parametri: Primul parametru Al doilea parametru Al treilea parametru
Nu ati introdus niciun parametru.
        Functia __call() nu este o functie sistem, si prin urmare nu poate fi apelata precum functiile sistem. Dimpotriva, __call este un identificator care permite programatorului sa construiasca o functie proprie, în care sa indice ceea ce trebuie sa se întâmple în cazul în care programul încearca sa acceseze, în mod nepermis, o functie-membra a unei clase, respectiv o functie care nu exista (nu este definita).
        În exemplul de mai sus, functia afiseazaMesaj() nu exista (nu este definita) pentru un obiect de tip Test. Încercarea de a o apela transmite functiei __call() cei doi parametri solicitati: primul parametru (case-sensitive) fiind chiar numele functiei apelante, iar al doilea, un sir indexat numeric, ale carui componente sunt chiar parametrii cu care a fost apelata functia apelanta.
        De exemplu, apelul:
$obj->afiseazaMesaj('Salut, ','lume!');
determina transmiterea catre functia __call() a doi parametri si anume stringul $nume = ’afiseazaMesaj’ si array-ul $parametri([0]=>’Salut, ’, [1]=’lume!’). Dupa cum se vede, functia __call() nu utilizeaza, în acest caz, parametrul $nume, dar, în cazul în care sunt mai multe functii al caror comportament trebuie astfel descris, functia __call() va utiliza si acest parametru.
        În ceea ce priveste suprascrierea functiilor, aceasta functioneaza normal, faraniciun fel de probleme, ca în exemplul de mai jos:
<?php
class Bunic{
    public function afiseaza() {
        echo "Afisare din clasa Bunic<br/>";
    }
}


class Parinte extends Bunic{
    public function afiseaza() {
        echo "Afisare din clasa Parinte<br/>";
    }
}

class Copil extends Parinte { 

    public function afiseaza() {
  echo"<br/> Afisare din toate clasele<br/>";
  Bunic::afiseaza();
  Parinte::afiseaza();
        echo "Afisare din clasa Copil<br/>";
    }
}


$obj0 = new Bunic;
$obj1 = new Parinte;
$obj2 = new Copil;

$obj0->afiseaza();
$obj1->afiseaza();
$obj2->afiseaza();
?>
        Iesirea este urmatoarea:
Afisare din clasa Bunic
Afisare din clasa Parinte

Afisare din toate clasele
Afisare din clasa Bunic
Afisare din clasa Parinte
Afisare din clasa Copil
        Avem, asadar, o clasa Bunic, care este extinsa succesiv de clasa Parinte si clasa Copil. În clasa Bunic avem definita o functie afiseaza(), care afiseaza un mesaj corespunzator clasei respective. În clasa Parinte, redefinim aceasta functie, astfel incât sa afiseze un mesaj diferit. De remarcat ca functia afiseaza() din clasa Parinte este o functie complet noua, care nu refoloseste nimic din codul corespunzator din clasa Bunic. Pe de alta parte, functia afiseaza() din Copil reutilizeaza atât codul corespunzator din Bunic, cât si cel din Parinte.

joi, 25 octombrie 2012

Conversia tipurilor şi utilizarea operatorilor de atribuire (=) şi egalitate (==, ===) în PHP

        Utilizarea corectă a operatorilor uzuali este una dintre cele mai de bază cerinţe în învăţarea oricărui limbaj de programare. Cele mai multe limbaje de programare actuale (ex. Java, C++ etc.) impun reguli stricte de declararare a tipului unei variabile înainte de iniţializarea şi folosirea sa. Limbajul PHP nu face parte din această categorie – se spune că este loosely typed - iar conversiile implicite de tipuri pot fi puţin derutante pentru cei neobişnuiţi cu astfel de operaţiuni. Cum o bună stăpânire a acestor concepte este indispensabilă pentru înţelegerea limbajului, am socotit nimerit să prezint, în cele ce urmează, câteva consideraţii elementare despre conversia tipurilor în PHP şi utilizarea operatorilor de atribuire (=), egalitate lejeră (==), şi respectiv, de egalitate strictă sau identitate (===), lăsând deoparte, totuşi, operatorii de cast explicit, asupra cărora, poate, voi reveni.

Operatorul de atribuire (asignare) (=) are forma:
$var = expresie;
        Se evaluează expresia din dreapta operatorului, atât ca tip, cât şi ca valoare, iar rezultatul este atribuit variabilei din stânga. Spre deosebire alţi operatori, dacă variabila din stânga nu există, operatorul de atribuire o creează fără a emite niciun avertisment. Returnează valoarea atribuită variabilei $var, şi asociază de la dreapta la stânga, ceea ce înseamnă că putem scrie atribuiri multiple, ca în exemplul de mai jos:
<?php
$a = 2 + 3; //$a primeşte valoarea întreagă 5
echo $a."<br/>";
$b = $a = 7; //$a  primeşte valoarea  7, apoi aceasta valoare 
//este atribuită şi lui $b
echo $a.' '.$b."<br/>"; 
$b = 5 + $a = 3; //$a primeşte valoarea întreagă 3, 
//iar $b primeşte valoarea întreagă  8
echo $a.' '.$b."<br/>"; 
?>
        Trebuie reţinut, aşadar, că operatorul de asignare nu realizează o comparaţie şi, ca orice alt operator, returnează un rezultat. Această informaţie banală este adesea ignorată de programatorii începători, care se bazează pe avertismentele de eroare emise de sistem. Să considerăm următorul exemplu:
<?php
$a = 'ceva';
if ($a = 'altceva'){
    echo 'Ce s-o fi întâmplat?
} else {
    echo '$a este ceva';
}
?>
        Rezultatul va fi că sistemul va afişa textul Ce s-o fi întâmplat?. Motivul este următorul: în antetul instrucţiunii if nu s-a realizat, de fapt, nicio comparaţie, ci o atribuire, de fapt o suprascriere a variabilei $a, care conţine acum 'altceva', indiferent de valoarea ei anterioară. Conform regulilor de conversie a tipurilor, rezultatul returnat de operatorul de atribuire (care este tot 'altceva') este evaluat la true, ceea ce conduce la afişarea textului menţionat.
        Să considerăm acum un alt exemplu:
<?php
$a = 1;
while ($a = 1) {
    echo '$a = '.$a."<br/>";
    $a++;
}
?>
        În acest caz, deoarece, în ciuda incrementării variabilei $a în interiorul buclei while, condiţia de ieşire din ciclu nu va fi îndeplinită niciodată, fiindce în antetul instrucţiunii while nu se face o comparaţie, ci o atribuire care va returna întotdeauna 1, adică true.

        Operatorii de egalitate lejeră (==) şi, respectiv, de egalitate strictă (===) returnează, ambii, un rezultat logic, adică true sau false. Deosebirea este că operatorul == ţine cont doar de conţinutul variabilelor comparate, ingnorând tipul lor – adică, de fapt, face conversia tipurilor -, operatorul === compară atât conţinutul variabilelor, cât şi tipul lor.
        Operatorul de egalitate lejeră funcţionează ţinând cont de următoarele reguli:
  • Din punct de vedere logic, orice număr întreg sau real, cu excepţia lui 0, orice string nevid, cu excepţia stringului "0", orice array nevid (care are măcar o componentă, indiferent ce fel de componentă, şi indiferent de valoare) sunt true. În schimb, sunt false: numărul 0, stringul "0" şi cel vid (""), array-urile vide (array()) şi null-urile.
  • Privite ca numere, true e echivalent cu 1, iar false cu 0.
  • Privite ca stringuri, true e echivalent cu "1", iar false cu "0".
  • Văzut ca număr, orice string este egal cu numărul care se poate forma cu cel mai mare număr din primele sale caractere, iar dacă acest număr este zero, atunci stringul este 0.De exemplu, "1001 dalmaţieni" este echivalent cu 1001, "-2e3p07MN" este echivalent cu -2*103 = -2000, iar "abracadabra" este echivalent cu 0. Atenţie, deci, la aceste echivalenţe, care nu sunt tranzitive – convertit în număr, "abracadabra" este 0, şi convertit în boolean, este false, pe câtă vreme, convertit direct în boolean, este true – şi, în mod evident, nici reflexive – privit ca boolean, "abracadabra" e true, dar true, văzut ca string, e "1".
        Aceste reguli sunt evidenţiate în tabelul de mai jos, unde sunt notate cu asterisc (*) comparaţiile care returnează true.


bool
true
bool
false
int
1
int
0
int
-1
string
"1"
string
"0"
string
"-1"
NULL array()

string
"string"
string
""
true *
*
* *
*

*
false
*
*

*
* *
*
1 *
*

*





0
*
*







-1 *


*






"1" *
*

*





"0"
*



*




"-1" *





*



NULL
*





* *
*
array()
*





* *

"string" *








*
""
*





*

*

         Din tabelul de mai sus rezultă, cred, destul de clar, diferenţele dintre operatorul de egalitate lejeră şi cel de egalitate strictă, astfel încât nu voi da niciun exemplu cu privire la modul în care înlocuirea unui operator cu celălalt poate compromite logica unui program. Voi evidenţia, totuşi, modul în care se pot realiza câteva conversii simple, cât şi comportarea unor functii uzuale, precum isset(), is_type() (unde type e unul dintre cele 8 tipuri: integer, float, boolean, string, array, object, resursă şi null), şi settype(). Pentru determinarea tipului unei variabile se poate folosi, de asemenea, şi funcţia gettype(), dar ea este considerată învechită (deprecate) şi, probabil, va fi eliminată în viitoarele versiuni de PHP.
<?php
$ceva;
if (isset($ceva)) { 
    echo "Variabila $ceva este setată.<br/>";
} else {
    echo "Variabila \$ceva nu este setată.<br/>";
}
$ceva = NULL;
if (isset($ceva)) { 
    echo "Variabila $ceva este setată.<br/>";
} else {
    echo "Variabila $ceva nu este setată.<br/>";
}
$ceva = '1001 de nopţi';
if (is_string($ceva)) { 
    echo "Variabila $ceva este un string.<br/>";
} else {
    echo "Variabila $ceva nu este un string.<br/>";
}
$altceva = 2.5;
if (is_numeric($altceva)) { 
    echo "Variabila $altceva este un număr.<br/>";
} else {
    echo "Variabila $altceva nu este un număr.<br/>";
}
if (is_int($altceva)) { 
    echo "Mai precis, un număr întreg.<br/>";
} 
if (is_float($altceva)) { 
    echo "Mai precis, un număr real.<br/>";
} 
$ceva = $ceva + $ceva;
if (is_numeric($ceva)) { 
    echo "Variabila $ceva este un număr.<br/>";
} else {
    echo "Variabila $ceva nu este un număr.<br/>";
}
$ceva = $ceva.$ceva;
if (is_string($ceva)) { 
    echo "Variabila $ceva este un string.<br/>";
} else {
    echo "Variabila $ceva nu este un string.<br/>";
}
settype($ceva, 'bool');
if (is_bool($ceva)) { 
    echo "Variabila \$ceva este acum booleană şi are valoarea $ceva.<br/>";
} else {
    echo "Variabila $ceva nu booleană.<br/>";
}
$altceva = $altceva - $ceva;
echo "Variabila \$altceva are acum valoarea $altceva.<br/>";
if ($altceva) 
    $ceva = "101 dalmaţieni";
echo "Acum, \$ceva este $ceva<br/>";
$ceva += (int)$altceva;
echo "Acum, \$ceva este $ceva<br/>";
echo "În timp ce \$altceva a rămas $altceva.";
?>
Ieşirea programului este următoarea:
Variabila $ceva nu este setată.
Variabila nu este setată.
Variabila 1001 de nopţi este un string.
Variabila 2.5 este un număr.
Mai precis, un număr real.
Variabila 2002 este un număr.
Variabila 20022002 este un string.
Variabila $ceva este acum booleană şi are valoarea 1.
Variabila $altceva are acum valoarea 1.5.
Acum, $ceva este 101 dalmaţieni
Acum, $ceva este 102
În timp ce $altceva a rămas 1.5.