Ficheros de configuración en Silex

Posted by victor on August 10th, 2013
silex-logoSilex no incorpora de serie ningún mecanismo para cargar ficheros de configuración. Existen varios ServiceProviders pero ninguno se adaptaba a mis necesidades por lo que he escrito un proveedor de servicio basado en Symfony Config component que aprovecha la mayoría de sus características a excepción de la caché que, por el momento, no tengo nada pensado.

ConfigServiceProvider

ConfigServiceProvider permite cargar de serie configuraciones con formato Yaml y Toml, y es posible escribir cargadores para otros formatos, como Json, fácilmente. El resultado de interpretar cada fichero de configuración es almacenado en un repositorio y los repositorios se pueden mezclar, para dar como resultado otro repositorio, y validar su esquema para asegurarnos que las claves cumplen con la estructura y el dominio establecido. Usar el ConfigServiceProvider es sencillo. Como siempre, todo comienza con escribir la dependencia en composer.json de nuestro proyecto:
"require": {
    "yosymfony/config-serviceprovider": "1.0.*@dev"
}
Tras actualizar las dependencias con composer update hay que registrar el ServiceProvider:
$app->register(new ConfigServiceProvider());
El registro crea un nueva entrada en el DIC  -Contenedor de Servicios- en la que está disponible el componente. Para cargar un fichero de configuración se emplea el método load:
$repository = $app['configuration']->load('/var/www/config/user.yml');
Si tienes localizados los directorios donde se van a encontrar todas las configuraciones, puedes pasarlos en el constructor del ServiceProvider y la referencia a los ficheros de configuración será más sencilla:
$app->register(new ConfigServiceProvider(array(
    __dir__.'/config2',
    '/var/www/config'
)));

$repository = $app['configuration']->load('user.yml');
Hay que tener en cuenta que si existe más de un fichero user.yml, solo devolverá el primero. El acceso/modificación de los datos en el repositorio se puede realizar usando la interfaz típica de arrays o mediante los métodos set y get:
$repository->get('name', 'noname'); // Si 'name' no existe devuelve 'noname'
$repository['name']; // Obtiene el valor asociado a la clave 'name'

$repository->set('user, 'username'); // Equivale a 
$repository['user'] = 'username';

Validar el esquema de un fichero de configuración

Para validar que la estructura del fichero de configuración y el dominio de sus valores es el adecuado, debemos escribir una clase que usa TreeBuilder de Symfony Config component:
use Symfony\Component\Config\Definition\ConfigurationInterface;
use Symfony\Component\Config\Definition\Builder\TreeBuilder;

class MyConfigDefinitions implements ConfigurationInterface
{
    public function getConfigTreeBuilder()
    {
        $treeBuilder = new TreeBuilder();
        $rootNode = $treeBuilder->root(0);

        $rootNode->children()
            ->integerNode('port')
                ->end()
            ->scalarNode('server')
                ->end()
        ->end();

        return $treeBuilder;
    }
}
La clase anterior, permite validar la siguiente configuración:
# Yaml file
port: 25
server: "mail.yourname.com"
o esta otra:
# Toml file
port = 25
server = "mail.yourname.com"
La validación se realiza desde el repositorio $repository->validateWith(new MyConfigDefinitions());

Mezclar repositorios

Mezclar configuraciones es una tarea habitual cuando existe una jerarquía de las mismas. Dos repositorios, A y B se pueden mezclar y conseguir otro C en el que las claves de A tienen preferencia, en caso de conflicto, sobre las de B y las claves de B que no estén en A estarán añadidas en C:
$resultC = $repositoryA->mergeWith($repositoryB);
  Silex: Third Party ServiceProviders Packagist: config-serviceprovider Gist: Simple skeleton for Silex application

Comments

comments powered by Disqus