lunes, 30 de abril de 2012

Configuraciones universales o parámetros universales

Algunas veces nos encontramos con aplicaciones que requieren configuraciones, y estas, muchas veces, se hacen en un archivo de configuración. Pero luego, nos vamos dando cuenta que el archivo de configuraciones es tan grande, o que hay que darle acceso a varios colaboradores que implica que tengamos muchos detalles de seguridad que contemplar.

Indiferentemente a la tecnología, se puede construir un sistema de configuraciones que sea gestionable a nivel de base de datos y hacer una pantalla administrativa para sus diferentes valores.

¿Qué se puede guardar en un sistema de configuraciones?

Casi de todo: Traducciones, parámetros de configuración, plantillas de html, hojas de estilos css, llaves de acceso a APIs, definición de permisos, etc.

El esquema de la base de datos es la siguiente:

En donde:
  • config_id: Es un autonumérico, llave principal.
  • config_area: Nuestro proyecto puede tener varias áreas, aquí se pueden categorizar las diferentes configuraciones por cada uno de los módulos (usuarios, clientes, chat, agenda, facturas, etc)
  • config_texto: Es necesario que le pongamos un texto indicando de qué se trata la configuración.
  • config_parametro: Este es realmente el parámetro que será llamado desde el código, para poder hacer uso de su valor. Personalmente, acostumbro hacerlo memotécnico para poderlo leer o capturar fácilmente desde el código, por ejemplo: val_chat_permitir_salas_privadas, val_usuario_long_max_login, val_usuario_email_requerido, val_lang_en_register, etc
  • config_valor: Este es el valor que haremos uso en el aplicativo, el que mostraremos, o nos permitirá tener completamente configurado nuestro entorno. Sin importar el tipo de base de datos, es recomendable que sea de gran tamaño el archivo, para que su contenido pueda ser amplio.  en algunos proyectos, incluso aquí ingreso hasta la apariencia completa de la plantilla html del sitio.
Crear la tabla en SQLServer (2000, 2005, 2008)

CREATE TABLE [configuracion]( [config_id] [int] IDENTITY(1,1) NOT NULL, [config_area] [varchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, [config_texto] [varchar](1500) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, [config_parametro] [varchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, [config_valor] [text] COLLATE SQL_Latin1_General_CP1_CI_AS NULL, CONSTRAINT [PK_configuracion] PRIMARY KEY CLUSTERED ( [config_id] ASC ) ) END

Crear la tabla en MySQL
CREATE TABLE IF NOT EXISTS `configuracion` ( `config_id` int(11) NOT NULL AUTO_INCREMENT, `config_area` varchar(50) DEFAULT NULL, `config_texto` varchar(1500) DEFAULT NULL, `config_parametro` varchar(50) DEFAULT NULL, `config_valor` text, PRIMARY KEY (`config_id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;

Opcional a esto, se puede construir un administrador para estos datos, o se pueden gestionar todas las configuraciones a nivel de base de datos... eso ya depende del alcance que se le quiera dar al sistema de configuraciones universales.

Una sola función para invocar los valores
En VB.NET

Imports System.Data.SqlClient

    Function LN_obtener_configuracion(ByVal parametro As String) As String
        ' por defecto la respuesta de resultado es una cadena en blanco
        Dim rta As String = ""
        'se conecta a la base de datos
        Dim MyConnection As New SqlClient.SqlConnection("Data Source=server_name;Initial Catalog=my_db;Integrated Security=True")
        Dim MyCommand As SqlDataAdapter
        'hace la consulta en la base de datos
        MyCommand = New SqlDataAdapter("Select config_valor from configuracion where config_parametro='" & parametro.ToString() & "'", MyConnection)
        Dim DS As New DataSet
        Try
            MyCommand.Fill(DS, "res")
        Catch ex As Exception
            'aqui se controla cualquier error
        End Try
        'cierra las conexiones
        MyCommand.Dispose()
        MyConnection.Dispose()
        'extrae el valor, solo si hay algun contenido y existe el parámetro
        If DS.Tables("res").Rows.Count > 0 Then
            'Leemos la primera aparición de este valor en la BD, se supone que solo hay un registro con este parámetro
            rta = DS.Tables("res").Rows(0)("config_valor").ToString()
        End If
        'retorna el valor
        Return rta.ToString()
    End Function

En C#.NET
public string LN_obtener_configuracion(string parametro)
{
 // por defecto la respuesta de resultado es una cadena en blanco
 string rta = "";

 //se conecta a la base de datos
 System.Data.SqlClient.SqlConnection MyConnection = new System.Data.SqlClient.SqlConnection("Data Source=server_name;Initial Catalog=my_db;Integrated Security=True");
 SqlDataAdapter MyCommand = default(SqlDataAdapter);

 //hace la consulta en la base de datos
 MyCommand = new SqlDataAdapter("Select config_valor from configuracion where config_parametro='" + parametro.ToString() + "'", MyConnection);
 DataSet DS = new DataSet();
 try {
  MyCommand.Fill(DS, "res");
 } catch (Exception ex) {
  //aqui se controla cualquier error
 }

 //cierra las conexiones
 MyCommand.Dispose();
 MyConnection.Dispose();

 //extrae el valor, solo si hay algun contenido y existe el parámetro
 if (DS.Tables["res"].Rows.Count > 0) {
  //Leemos la primera aparición de este valor en la BD, se supone que solo hay un registro con este parámetro
  rta = DS.Tables["res"].Rows[0]["config_valor"].ToString();
 }
 //retorna el valor
 return rta.ToString();
}

En PHP
function LN_obtener_configuracion($parametro)
{
 $rta = "";
 $con = mysql_connect("localhost","peter","abc123");
 if (!$con) {
   die('Could not connect: ' . mysql_error());
 }
 
 mysql_select_db("my_db", $con);
 $result = mysql_query("Select config_valor from configuracion where config_parametro='" . $parametro . "'");
 while($row = mysql_fetch_array($result)) {
   $rta = $row['config_valor'];
 }
 
 mysql_close($con);
    return $rta;
}

Para su utilización simplemente ponemos en nuestro código:
VB.NET:
Dim txt_mensajebienvenida As String = LN_obtener_configuracion("val_lang_en_hello").ToString()

C#.NET:
string txt_mensajebienvenida = LN_obtener_configuracion("val_lang_en_hello").ToString();

PHP:
$txt_mensajebienvenida = LN_obtener_configuracion('val_lang_en_hello');

Y de esta manera la variable txt_mensajebienvenida tendrá a partir de este momento el valor que le hayamos puesto al parámetro de val_lang_en_hello en la base de datos.


Calcular edad con la fecha de nacimiento en PHP

 En este tutorial, aprenderemos cómo calcular la edad a partir de la fecha de nacimiento en PHP. Daré dos ejemplos de Cómo calcular la edad....