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.