Factory
Il pattern OOP factory viene utilizzato per creare tipi di istanze differenti di una classe in base a diversi parametri che possiamo passare. Basandoci sulla classe singleton creata precedentemente, possiamo generare una classe factory che crea un tipo di connessione a seconda del driver utilizzato da PDO. Per esempio collegandoci col driver MySQL, SQLite, Oracle…
Creiamo un file DbFactory.php che conterrà la classe DbFactory
namespace App\DB; use App\DB\DBPDO; class DbFactory { }
inseriamo un metodo pubblico statico che riceverà un array di opzioni simile a quello singleton
public static function create(array $options)
nel metodo create() andremo a fare uno switch sulla chiave driver contenuta nel file di configurazione db. Per prima cosa verifica se è settato un driver col metodo array_key_exists() di php
if (!array_key_exists('driver', $options)) {
throw new \InvalidArgumentException('Nessun driver predefinito'); }
se la chiave driver non esiste sollevo un’eccezione throw e usando la classe InvalidArgumentException() do un messaggio di errore. Ora passiamo ai casi a seconda del driver
$dsn = ''; switch ($options['driver']) { case 'mysql': case 'oracle': case 'mssql': $dsn = $options['driver'].':host='. $options['host']; $dsn .= ';dbname=' .$options['database'].';charset='.$options['charset']; break; case 'sqlite': $dsn = 'sqlite' . $options['database']; break; default : throw new \InvalidArgumentException(' driver non impostato o sconosciuto'); }
Abbiamo impostato di default un’eccezione col messaggio. La parte più rilevante è la costruzione dei parametri di connessione memorizzati in $dsn che dovrà essere per esempio per MySQL:
$dsn = 'mysql:host=localhost;dbname=nomedatabase;charset=utf8';
visto che abbiamo costruito il dsn di connessione alla fine quello da noi costruito dobbiamo assegnarlo alla chiave di $options
$options['dsn'] = $dsn;
se il don è già costruito, tutto questo codice non serve, quindi possiamo fare un controllo a monte
if(!array_key_exists('dsn',$options)) { codice per costruire il dsn fatto in precedenza }
ora possiamo ritornare, alla fine del nostro file, il metodo statico getInstance() della classe singleton:
return DBPDO::getInstance($options);
dicendo preventivamente di usarla col comando use che si utilizza per richiamare una classe in presenza dei namespace :
use App\DB\DBPDO;
Ora includendo il file DbFactory.php possiamo richiamare la factory che crea la connessione in base al database utilizzato col metodo create()
require_once __DIR__.'/../app/db/DbFactory.php';
$pdoConn = \App\DB\DbFactory::create($data);
Per verificare se è impostato il charset del db e impostarlo aggiungiamo il codice:
if(!array_key_exists('charset', $options)) { $options['charset'] = 'utf8'; }
ecco il codice della nostra classe factory completo:
namespace App\DB; use App\DB\DBPDO; class DbFactory { public static function create(array $options) { if(!array_key_exists('charset', $options)) { $options['charset'] = 'utf8'; } if(!array_key_exists('dsn',$options)) { if (!array_key_exists('driver', $options)) { throw new \InvalidArgumentException('Nessun driver predefinito'); } $dsn = ''; switch ($options['driver']) { case 'mysql': case 'oracle': case 'mssql': $dsn = $options['driver'].':host='. $options['host']; $dsn .= ';dbname=' .$options['database'].';charset='.$options['charset']; break; case 'sqlite': $dsn = 'sqlite' . $options['database']; break; default : throw new \InvalidArgumentException(' driver non impostato o sconosciuto'); } $options['dsn'] = $dsn; } return DBPDO::getInstance($options); } }