Un punct de reper pentru a descoperi un programator bun, indiferent de limbajul de programare pe care îl utilizează, este abilitatea acestuia de a aplica tehnici cunoscute de design al aplicaţiei. Design patterns(sau proiectarea modelelor) sunt un un set de soluţii ce pot fi aplicate la diverse probleme ce se întâlnesc frecvent în cadrul programării orientate pe obiect.

În teorie, aceste modele nu au legătură cu codul scris de un programator. Sunt niște soluţii de eficientizare a problemelor des întâlnite, nişte indicaţii pe care programatorul trebuie să le transpună în limbajul de programare pe care îl foloseşte. Ne vom referi în continuare la aceste modele legat de limbajul PHP, modele care deşi pot fi implementate folosind şi programarea procedurală, ele sunt evidenţiate mai bine cu ajutorul programării orientate pe obiect.

Singleton

Modelul Singleton este probabil cel mai simplu model. El este făcut pentru a permite accesul la o singură resursă care nu va fi niciodată duplicată, dar care trebuie făcută disponibilă în orice moment al execuţiei aplicaţiei. Implementarea unui Singleton trebuie să satisfacă cele două condiţii de acces global şi instanţiere singulară a resursei respective. Are nevoie de un mecanism de acces la class Singleton fără a instanţia un obiect şi un mecanism de a păstra informaţia asupra resursei ce urmează a fi folosită. Astfel acest model poate fi cel mai uşor implementat prin crearea unei clase ce va conţine o metodă care va crea o nouă instanţă a clasei, dacă aceasta nu exista deja, iar dacă există o va returna pe aceasta. Pentru a fi siguri că acea clasă nu va fi instanţiată în alt fel, constructorul este declarat protejat. Exemplul cel mai simplu este acela în care se pune problema existenţei unei singure conexiuni la baza de date:

class database 
{
    private static $_singleton;
    private $_connection;
    
    protected function __construct()
    {
        $this->_connection = mysql_connect(SERVER, USER, PASSWORD);
    }
    
    public static function getInstance()
    {
        if (is_null(self::$_singleton))
        {
            self::$_singleton = new database();
        }
        
        return self::$_singleton;
    }
}

$cnx = database::getInstance();

Aşadar constructorul a fost declarat protejat pentru a controla accesul la el şi de a da posibilitatea apelării lui doar din interiorul clasei. Acest lucru este făcut cu ajutorul metodei statice getInstance, care verifică la fiecare apel al ei dacă există definit membrul static $_singleton, caz în care îl va returna, sau va încerca să creeze unul nou. Odată creat, metoda getInstance() nu va mai încerca să creeze unul nou ci-l va retuna pe cel creat tot timpul.

Factory

Modelul Factory se foloseşte în scenariile în care există o clasă generică (fabrica) care are posibilitatea de a crea o instanţă a una sau mai multe clase specializate în rezolvarea unei aceleaşi probleme dar în diferite moduri. Un astfel de exemplu îl reprezintă stocarea datelor de configurare într-o aplicaţie. Datele de configurare, precum credenţialele pentru conectarea la baza de date, sau căile de acces la diverse directoare, pot fi stocate în mai multe feluri: în fişiere XML, in fişiere INI sau chiar în baza de date. Astfel putem crea un mecanism care să returneze un obiect ce va şti să lucreze cu un anume mod de stocare a acestor date de configurare.

class configuration 
{
    const STORE_IN_INI = 1;
    const STORE_IN_DB = 2;
    const STORE_IN_XML = 3;
    
    public static function factory($type = self::STORE_IN_INI)
    {
        switch ($type)
        {
            case self::STORE_IN_INI:
                return new configuration_ini();
            case self::STORE_IN_DB:
                return new configuration_db();
            case self::STORE_IN_XML:
                return new configuration_xml();
            default:
                throw new Exception('Tip de stocare necunoscut');
        }
    }
}

Este evident faptul că toate cele 3 clase specializate de tratare a fișierelor de configurare (ini, xml, db) trebuiesc definite şi implementate, un avantaj fiind definirea lor conform unei clase abstracte. Apelarea “fabricii” se face după cum urmează:

$storage = configuration::factory(configuration::STORE_IN_XML);

Registry

Modelul Registry este un model Singleton mai evoluat, în sensul că permite stocarea mai multor resurse, ca într-un registru. Un exemplu ar fi acela în care, deşi avem conexiunea stabilită către baza de date printr-un Singleton, şi prin această conexiune se fac toate interogările, există posibilitatea ca din aplicaţie să fie nevoie de conexiunea în paralel către o alta bază de date pentru a efectua şi acolo diverse operaţiuni. Cu un simplu Singleton nu s-ar fi putut realiza aşa ceva însă cu un Registry acest lucru este posibil. Un astfel de Registry va trebui să implementeze metode de adăugare, verificare a existenţei şi de returnare a informaţiilor cerute.

class registry
{
    private static $_register;
    
    public static function add(&$element, $name)
    {
        $name = strtolower($name);
        self::$_register[$name] = $element;
    }
    
    public static function exists($name)
    {
        $name = strtolower($name);
        if (array_key_exists($name, self::$_register))
        {
            return true;
        }
        return false;
    }
    
    public static function &get($name)
    {
        $name = strtolower($name);
        if (self::exists($name))
        {
            return self::$_register[$name];
        }
        else 
        {
            throw new Exception('Elementeul cerut nu exista in registru.');
        }
    }
    
}

O folosirea a cestul model este următorul cu precizarea ca în acest exemplu clasa database nu este un Singleton:

$db = new database();
registry::add($db, 'dbCnx');
/*
verificarea conexiunii
*/
if (registry::exists('dbCnx'))
{
    $db = registry::get('dbCnx');
}

Model-View-Controller

Spre deosebire de celelate modele discutate anterior, Model-View-Controller(denumit şi MVC) este un model destul de complex. Scopul lui este de a oferi o metodă de separare dintre logica aplicaţiei (model), modului de afişare (view) şi structura decizională (controller), aplicaţiile MVC fiind astfel usor de modificat atunci când se doreşte modificarea doar a modului de afişare sau a modului în care este tratată o cerere.

Logica unei astfel de aplicaţii este următoare: o cerere este făcută către aplicaţie şi este apelat controller-ul care va decide cum va trata cererea. Controller-ul va chema o clasă din Model, care efectiv va efectua interogări către baza de date, prelucrările necesare ale datelor sau orice alte operaţiuni necesare. Rezultatul, de regulă un set de date, va fi întors către Controller care va transmite aceste date părţii vizuale a aplicaţiei(View) unde deja există o structură de afişare a datelor ce tocmai au fost primite. Avantajul enorm al acestui model este separarea clară între cele 3 compomente şi uşurinţa cu care se pot extinde aplicaţiile dezvoltate pe acest model.