The Pokedex Project(5) — Agregando un archivo de configuración al proyecto.
Un archivo de configuración nos facilita la forma de acceder a información delicada del proyecto, por ejemplo: credenciales a base de datos, secrets y tokens para servicios de terceros y apis, etc. Por cuestiones de seguridad usaremos archivos .env para obtener este tipo de información en nuestro Pokedex.
Usaremos el paquete “dotenv” para leer este tipo de archivos, para esto ejecutamos en la terminal:
Copiar código:composer require vlucas/phpdotenv
Creación de clases para encapsular el paquete “dotenv”
Encapsularemos el paquete recién instalado (dotenv) en una clase; crearemos primero la interface Configuration(Utils/Configuration/Configuration) y después la clase Env(Utils/Configuration/Env):
Copiar código:mkdir src/Utils/Configuration && cd src/Utils/Configuration && touch Configuration.php && touch Env.php
Editaremos la interface Configuration.php:
Copiar código:<?php
namespace Utils\Configuration;
interface Configuration
{
public function load();
public function getDotEnv();
}
Editaremos la clase Env.php, aquí implementaremos la interface Configuration.php:
Copiar código:<?php
namespace Utils\Configuration;
use Dotenv\Dotenv;
class Env implements Configuration
{
protected $dirPath;
protected $dotEnv;
public function __construct(string $dirPath)
{
$this->dirPath = $dirPath;
}
public function load()
{
$dotEnv = Dotenv::createImmutable($this->dirPath);
$this->_setDotEnv($dotEnv);
$dotEnv->load();
}
private function _setDotEnv($dotEnv)
{
$this->dotEnv = $dotEnv;
}
public function getDotEnv()
{
return $this->dotEnv;
}
public static function checkIfValueIsBoolean(string $value)
{
$varValue = strtolower($value);
return [
'result' => ($varValue == 'true' || $varValue == 'false'),
'value' => ($varValue === 'true'),
];
}
}
Aquí carga nuestro archivo .env en la super global $_ENV e implementa los métodos del paquete “dotenv” para cargar sus clases.
Creación de archivos .env.example y .env
Para que el paquete funcione necesita tener creado el archivo .env en la raíz de nuestro proyecto. También para cuestiones de desarrollo este archivo no debe ir subversionado ya que puede tener información diferente entre ambientes de desarrollo. Así que crearemos nuestra copia del archivo .env y lo nombraremos .env.example; el cual nos dará la estructura del archivo .env y en caso de que se agreguen, quiten o modifiquen pues ya se estarán guardando estos cambios en el repositorio.
Creamos el archivo .env.example:
Copiar código:touch .env.example
Editamos el archivo .env.example:
Copiar código:APP_ENV=dev
Copiamos el archivo .env.example a .env:
Copiar código:cp .env.example .env
Probando el acceso a las variables de entorno del archivo .env con “dotenv”
Ahora probaremos el acceso a la variable que le pusimos a nuestro archivo .env.
Modificamos el archivo routes/web.php en la ruta ‘/’:
Copiar código:$route->add('/', function () {
//echo '<h1>Hello Pokedex!</h1><br>';
//$template = new Utils\View\View();
//$template->render('pokedex.html');
view('pokedex.html', [
'pokemonName' => 'Balbusaur',
'appEnv' => $_ENV['APP_ENV'],
]);
});
Modificamos el archivo resources/views/pokedex.html:
Copiar código:{% block content %}
<h1>Hello {{ pokemonName }}!</h1>
<h3>Ambiente: {{ appEnv }}</h3>
{% endblock %}
Deberíamos de ver algo así:
Encapsulando el acceso a las variables de entorno con un Helper
Encapsularemos el uso de $_ENV en un helper, esto para tener acceso mas fácil a este tipo de información y refactorizar el código.
Modificamos el archivo src/Utils/helpers.php y agregamos lo siguiente:
Copiar código:if (! function_exists('env_var')) {
function env_var(string $varName, $fallBackValue = '')
{
$envVarValue = $fallBackValue;
if (! empty($_ENV[$varName])) {
$checkIfValIsBool = Env::checkIfValueIsBoolean($_ENV[$varName]);
$envVarValue = ($checkIfValIsBool['result']) ? $checkIfValIsBool['value'] : $_ENV[$varName];
}
return $envVarValue;
}
}
Modificamos el archivo resources/web.php:
Copiar código:view('pokedex.html', [
'pokemonName' => 'Balbusaur',
'appEnv' => env_var('APP_ENV', 'dev'),
]);
Ahora cada vez que queramos acceder a las variables de entorno usaremos la función env_var(). El fall back value es para cuando se nos olvide configurar esa variable y le dejemos el valor vacío, esto regresara el fall back value, si no se le quiere poner este valor simplemente lo omitimos y regresara un string vacío.
Agregando lógica de negocio con las variables de entorno.
Tenemos la variable APP_ENV la cual nos indica en que ambiente de desarrollo estamos(desarrollo, pruebas, producción, etc ..), en la vista de nuestro controlador de excepciones o errores, no queremos que nos muestre el texto de la información del error cuando este en ambiente de “pruebas” y “producción”. Entonces pondremos una variable de entorno la cual nos dirá si estamos debuggeando el código o no .
Para esto modificamos el .env.example y agregamos:
Copiar código:APP_DEBUG=true
Lo mismo lo hacemos para nuestro archivo “.env”.
Modificamos la clase ExceptionHandler(src/Utils/Exceptions):
Copiar código:private function _initException($exception)
{
view('errors/500-internal-error.html', [
'debug' => env_var('APP_DEBUG'),
'exceptionMessage' => $exception->getMessage(),
'exceptionFile' => $exception->getFile(),
'exceptionLine' => $exception->getLine(),
]);
}
Modificamos la vista 500-internal-error.html(resources/views/errors):
Copiar código:{% if debug %}
<blockquote>
<b>Message:</b> {{ exceptionMessage }} <br>
<b>File:</b> {{ exceptionFile }} <br>
<b>Line:</b> {{ exceptionLine }} <br>
</blockquote>
{% endif %}
Para probar solamente cambiamos el valor de “APP_DEBUG” por false y ya no deberíamos de ver los mensajes de error.
APP_DEBUG = true:
APP_DEBUG = false:
Con el helper de las variables de entorno nos da ya mayor flexibilidad a la hora de agregar lógica de negocio a nuestra app con la configuración. Y aparte se puede escalar ya que se encapsulo en una clase. El archivo de configuración .env lo usaremos mas adelante cuando lleguemos a la capa de datos del Pokedex.
Pueden consultar el código de esta publicación en este repositorio: https://github.com/krsrk/pokedex-vanilla-php
La siguiente publicación esta lista y la puedes revisar, en ella agregaremos métodos en nuestra clase Request para obtener información de la petición:
https://link.medium.com/rNvJ5jDjH9
Si les gusto la publicación denle claps, likes y comentarios.