Entornos y flexibilidad de configuraci贸n
Tenemos un problema evidente con nuestra clase de base de datos en este momento. Los valores de conexi贸n han sido codificados de forma r铆gida. Entonces, 驴qu茅 sucede cuando llevamos el proyecto a producci贸n, donde el host y el puerto son completamente diferentes?
Que aprenderemos
- Environments
- Push Configurable Data Upward
Vamos a pasar la constante de PDO [PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC] dentro de la clase, y vamos a utilizar una nueva funci贸n de php http_build_query($data), que es lo que hace esta funci贸n?
Refactor 1 - Database.php
Nuestro primer intento podr铆a verse algo as铆:
<?php
// Conectarnos a la base de datos MySQL $dsn (data source name) y ejecutar un Query
class Database {
public $connection='';
public function __construct(){
$config = [
'host' => '127.0.0.1',
'port' => 3306,
'dbname' => 'phplaracast',
'charset' => 'utf8mb4',
];
$dsn = "mysql:host={$config['host']}, port={$config['port']}, dbname={$config['dbname']}, charset={$config['charset']} ";
$this->connection = new PDO($dsn, 'root', '', [PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC]);
}
public function query($query){
$statement = $this->connection->prepare($query);
$statement->execute();
return $statement;
}
}
http_build_query()
Lo que hace esta funci贸n es construir el query string por ejemplo, example.com?host=127.0.0.1&port=3306&dbname=phplaracast etc.. donde el query string es host=127.0.0.1&port=3306&dbname=phplaracast, para poder usarlo dentro de nuestro c贸digo tenemos que quitar los &, entonces podemos cambiar el & por ; como lo requiere nuestro $dsn de la siguiente manera:
$config = [
'host' => '127.0.0.1',
'port' => 3306,
'dbname' => 'phplaracast',
'charset' => 'utf8mb4',
];
dd(http_build_query($config, '', ';'));
Nos da la salida
string(59) "host=127.0.0.1;port=3306;dbname=phplaracast;charset=utf8mb4"
Podemos ver como ya empezamos a construir nuestro $dsn.
Para incluir el mysql: que necesitamos para el $dsn podemos concatenar el string as铆:
dd('mysql:' . http_build_query($config, '', ';'));
Lo cual nos da:
string(65) "mysql:host=127.0.0.1;port=3306;dbname=phplaracast;charset=utf8mb4"
Y es precisamente el $dsn que estamos buscando.
Refactor 2 - Database.php
Entonces ya podemos simplificar nuestro $dsn as铆:
class Database {
public $connection='';
public function __construct(){
$config = [
'host' => '127.0.0.1',
'port' => 3306,
'dbname' => 'phplaracast',
'charset' => 'utf8mb4',
];
$dsn = 'mysql:' . http_build_query($config, '', ';');
$this->connection = new PDO($dsn, 'root', '', [PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC]);
}
public function query($query){
$statement = $this->connection->prepare($query);
$statement->execute();
return $statement;
}
}
Todo funciona bien hasta aqu铆!
Refactor 3
Ahora tenemos el problema de que las variables de configuraci贸n est谩n grabadas en c贸digo dentro de la clase. Como un primer intento de sacar estas variables de la clase, podemos subirlas un nivel quedando as铆: En Database.php
class Database {
public $connection='';
public function __construct($config){
$dsn = 'mysql:' . http_build_query($config, '', ';');
$this->connection = new PDO($dsn, 'root', '', [PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC]);
}
public function query($query){
$statement = $this->connection->prepare($query);
$statement->execute();
return $statement;
}
}
Y le mandamos los los par谩metros de configuraci贸n desde index.php as铆:
$config = [
'host' => '127.0.0.1',
'port' => 3306,
'dbname' => 'phplaracast',
'charset' => 'utf8mb4',
];
$db = new Database($config);
Y todo sigue funcionando igual, pero aun siguen las variables de configuraci贸n grabadas en el c贸digo, en nuestro siguiente intento podemos subirlas otro nivel y sacarlas a un archivo de configuraci贸n donde vivir谩n todas nuestras variables de entorno, llamemos a ese archivo config.php:
<?php
return [
'host' => '127.0.0.1',
'port' => 3306,
'dbname' => 'phplaracast',
'charset' => 'utf8mb4',
];
Ahora en vez de declarar una variable, vamos hacer un return.
Y en index.php podemos requerir el archivo as铆:
$config = require('config.php');
$db = new Database($config);
Y todo sigue funcionando!
Aprendimos que la funci贸n return no solo se usa en funciones, si no que tambi茅n la podemos usar en archivos como este, lo que le estamos diciendo a php con la instrucci贸n $config = require('config.php'); es $config va a ser igual a lo que regrese el requerir al archivo config.php.
Si analizamos la clase en Database.php todav铆a tenemos pendiente refactor tanto el user como su password.
Refactor 4
public function __construct($config, $username = 'root', $password = ''){
$dsn = 'mysql:' . http_build_query($config, '', ';');
$this->connection = new PDO($dsn, $username, $password, [PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC]);
}
Refactor 5
Finalmente podemos agrupar las variables de config.php en una llave que le podemos llamar database:
<?php
return [
'database' => [
'host' => '127.0.0.1',
'port' => 3306,
'dbname' => 'phplaracast',
'charset' => 'utf8mb4',
],
];
Y mandarla llamar desde index.php as铆:
$config = require('config.php');
$db = new Database($config['database']);
Listo! Todo sigue funcionando correctamente! Pero ahora nuestro c贸digo a quedada sumamente mejorado.