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);
}
}