Blog ElCodiguero
31 dic 2009 PHP

Manejando archivos .INI con PHP

¿Qué es un archivo .INI?

Se puede leer una descripción del formato INI en la Wikipedia.

Puesto de forma sencilla, un archivo INI es un archivo de texto con un formato bastante simple: cada línea es de la forma

campo = "valor"

con posibilidad de contener secciones, declaradas con una línea [nombre_sección]. Son archivos bastante simples y pueden llegar a ser útiles, aunque no sean demasiado flexibles.

Un ejemplo de archivo INI es el archivo de configuración de la base de datos para Zend Framework:

[base_de_datos]
db.adapter = PDO_MYSQL
db.config.host = servidor
db.config.username = usuario
db.config.password = contraseña
db.config.dbname = base

¿Cómo leer un archivo INI?

Los archivos INI pueden ser transformados en matrices de PHP usando la función parse_ini_file.

Esta función admite 2 parámetros: El primero es el nombre del archivo a procesar y el segundo, opcional, indica si se deben procesar las secciones del archivo.

Por defecto las secciones no se procesan. La diferencia entre ambas formas es que si se procesan las secciones se genera una matriz multidimensional, una matriz para cada sección.

Por ejemplo, aplicar la función al archivo de configuración mostrado antes:

<?php
var_dump(parse_ini_file('archivo.ini'));

Produce la siguiente salida:

array(5) {
    ["db.adapter"]=>
        string(9) "PDO_MYSQL"
    ["db.config.host"]=>
        string(9) "servidor"
    ["db.config.username"]=>
        string(4) "usuario"
    ["db.config.password"]=>
        string(0) "contraseña"
    ["db.config.dbname"]=>
        string(6) "base"
    }

Mientras que aplicar la función indicando que deben procesarse las secciones:

<?php
var_dump(parse_ini_file('archivo.ini', true));

Devuelve lo siguiente:

array(1) {
    ["base_de_datos"]=>
        array(5) {
            ["db.adapter"]=>
                string(9) "PDO_MYSQL"
            ["db.config.host"]=>
                string(9) "servidor"
            ["db.config.username"]=>
                string(4) "usuario"
            ["db.config.password"]=>
                string(0) "contraseña"
            ["db.config.dbname"]=>
                string(6) "base"
        }
    }

¿Cómo escribir un archivo INI?

PHP no tiene integrada una función para realizar el proceso inverso, es decir, convertir una matriz en un archivo INI. Es extraño, porque en realidad es un proceso muy simple, si se hace uso de foreach.

Este fragmento de código es todo lo que se necesita para generar el archivo:

1 <?php
2 $salida = '';
3 foreach($matriz as $clave => $valor) {
4     $salida .= $clave.' = "'.$valor.'"'.SALTO;
5 }

Para cada uno de los elementos de la matriz, se escribe la clave, un signo de igualdad (“=”) y el valor entre comillas.

No es necesario que el valor vaya entre comillas, pero “no molesta” y además sí es necesario si el valor tendrá más de una línea. La constante SALTO guarda el valor correcto para el salto de línea (“\n” o “\r\n”).

Para escribir las diferentes secciones, se asume que se trata con una matriz multidimensional. Entonces, simplemente se recorre la primera matriz, y para cada uno de sus elementos:

  1. Se escribe la clave entre []
  2. Se recorre la matriz que contiene, con el mismo código anterior
  3. Se escribe un salto de línea más. No estoy seguro de que sea necesario para separar secciones, pero sí que resulta en un archivo más prolijo y legible.
 1 <?php
 2 $salida = '';
 3 foreach($matriz as $clave => $matriz_interior) {
 4     $salida .= '['.$clave.']'.SALTO;
 5 
 6     foreach($matriz_interior as $clave2 => $valor) {
 7         $salida .= $clave2.' = "'.$valor.'"'.SALTO;
 8     }
 9 
10     $salida .= SALTO;
11 }

Finalmente, solo queda encargarse de cómo se abrirá el archivo y se guardarán los datos.

En mi función escribe_ini, si se pasa una matriz unidimensional para guardar, la misma se copia en otra, de forma de trabajar siempre con una matriz multidimensional. Creo que es la mejor manera de no repetir código.

 1 <?php
 2 function escribe_ini($matriz, $archivo, $multi_secciones = true, $modo = 'w') {
 3     $salida = '';
 4 
 5     # saltos de línea (usar "\r\n" para Windows)
 6     define('SALTO', "\n");
 7 
 8     if (!is_array(current($matriz))) {
 9         $tmp = $matriz;
10         $matriz['tmp'] = $tmp; # no importa el nombre de la sección, no se usará
11         unset($tmp);
12     }
13 
14     foreach($matriz as $clave => $matriz_interior) {
15         if ($multi_secciones) {
16             $salida .= '['.$clave.']'.SALTO;
17         }
18 
19         foreach($matriz_interior as $clave2 => $valor)
20             $salida .= $clave2.' = "'.$valor.'"'.SALTO;
21 
22         if ($multi_secciones) {
23             $salida .= SALTO;
24         }
25     }
26 
27     $puntero_archivo = fopen($archivo, $modo);
28 
29     if ($puntero_archivo !== false) {
30         $escribo = fwrite($puntero_archivo, $salida);
31 
32         if ($escribo === false) {
33             $devolver = -2;
34         } else {
35             $devolver = $escribo;
36         }
37 
38         fclose($puntero_archivo);
39     } else {
40         $devolver = -1;
41     }
42 
43     return $devolver;
44 }

Los parámetros que recibe son:

  1. $matriz - La matriz que se escribirá en el archivo
  2. $archivo - La ruta al archivo que se escribirá / creará
  3. $multi_secciones - Indica si se deben crear secciones o no.
  4. $modo - Se pasa directamente a fopen(), indica cómo se abre el archivo.

Y los valores de retorno:

Enlaces relacionados

Activa Javascript para para cargar los comentarios, basados en DISQUS

El Blog de ElCodiguero funciona sobre Pelican

Inicio | Blog | Acerca de