Hice una libreria hace tiempo (toca mejorarla pero cumple su trabajo) que lee archivos al estilo php.ini
- Admite comentarios de varios tipos incluso multilinea /* ...*/
- Lee variables del tipo a = 567 ó a$ = 700
- Listas
- Lo que TU definas
(puedes incluso cambiar las reglas de cualquier definicion)
Suponte que quieres guardar por ejemplo un diccionario de plurales asi:
Cita: ; Defino el plural y el singular que aparece en los nombres de las tablas de la db
; Se procesará de forma secuencial u ordenada
; english
access,access
countries,country
categories,category
;children,child
;women,woman
;people,person
;feet,foot
;mice,mouse
;teeth,tooth
;potatos,potato
;tomatoes,tomato
; spanish
ordenes,orden
promociones,promocion
colecciones,coleccion
direcciones_usuarios,direccion_usuario
colores,color
;peces,cardumen
;jauria,perro
; podria definir reglas, por ejemplo: si la palabra termine con 'consonante + y', normalmente cambiamos la 'y' por una 'i' y añadimos 'es'.
;(dies),(dy)
;(ties),(ty)
; o usar expresiones regulares encerradas entre corchetes []
; #^[(][a-z]{1,}[)],[(][a-z]{1,}[)]#i
; asignaciones
; variable = valor
// un comentario
/* comentario que *no* puede ser multi-linea */
Tu incluirias la libreria asi:
Código PHP:
<?php
$singulares = process_ini('singulars.ini');
var_dump($singulares);
y el RESULTADO seria:
Cita: array (size=7)
0 =>
array (size=2)
'fields' =>
array (size=2)
0 => string 'access' (length=6)
1 => string 'access
' (length=8)
'type' => string 'def' (length=3)
1 =>
array (size=2)
'fields' =>
array (size=2)
0 => string 'countries' (length=9)
1 => string 'country
' (length=9)
'type' => string 'def' (length=3)
2 =>
array (size=2)
'fields' =>
array (size=2)
0 => string 'categories' (length=10)
1 => string 'category
' (length=10)
'type' => string 'def' (length=3)
3 =>
array (size=2)
'fields' =>
array (size=2)
0 => string 'ordenes' (length=7)
1 => string 'orden
' (length=8)
'type' => string 'def' (length=3)
4 =>
array (size=2)
'fields' =>
array (size=2)
0 => string 'promociones' (length=11)
1 => string 'promocion
' (length=11)
'type' => string 'def' (length=3)
5 =>
array (size=2)
'fields' =>
array (size=2)
0 => string 'colecciones' (length=11)
1 => string 'coleccion
' (length=11)
'type' => string 'def' (length=3)
7 =>
array (size=2)
'fields' =>
array (size=2)
0 => string 'colores' (length=7)
1 => string 'color
' (length=7)
'type' => string 'def' (length=3)
Donde puedes ver que tienes el dicccionario cargado en un array
Otro ejemplo, quieres hacer faciles los INNTER JOINS asi que te guardas las relaciones en algun archivito INI:
Cita: /*
**
** Archivo que detalla como hacer los JOINs
** -eventualmente seria generado por CRUDO-
**
*/
// recordar que ya no se soportaran claves primarias compuestas !!!
;t1,t1_has_t2,t2
productos,carritos_has_productos,carritos
productos,colecciones_has_productos,colecciones
/* ... */
// ojo: estan los que enlazan a PRODUCTOS y los que ESTA enlaza en sentido opuesto
y la SALIDA seria:
Cita: array (size=2)
0 =>
array (size=3)
0 => string 'productos' (length=9)
1 => string 'carritos_has_productos' (length=22)
2 => string 'carritos
' (length=10)
1 =>
array (size=3)
0 => string 'productos' (length=9)
1 => string 'colecciones_has_productos' (length=25)
2 => string 'colecciones
' (length=13)
OK...y el codigo ?
Código PHP:
<?php
$singulares = process_ini('joins.ini');
var_dump($singulares);
/**
* Procesa un archivo de configuracion .INI y devuelve un arreglo
* @author Pablo Bozzolo (2011)
*
* @param file
* @return array of type,fields
*
* bastante complejos pueden ser los archivos INI, extrae asignaciones y demas
* en $new_defs se le pueden pasar nuevas "reglas" de procesamiento como array assoc
* o tambien se pueden redefinir las originales
*
* Comentarios soportados: multi-linea, (;) al comienzo de la linea,
* (#) al comienzo de la linea, doble barra (//)
*
*/
function process_ini($file,$new_defs=null){
// ejemplo de definiciones
if (!defined('DEF')) define ('DEF' ,'def' );
if (!defined('RULE')) define ('RULE' ,'rule' );
if (!defined('REGEX')) define ('REGEX','regex');
if (!defined('LET')) define ('LET' ,'let' ); # asignaciones
$rows = array();
/*
LET ejemplo: $a = 567 o a$ = 700
DEF: son definiciones por ejemplo sinonimos, ej: tree,arbol
RULE: es usado para determinar como cambia una palabra del singular al plural,
ej: (es),(s)
REGEX: aun no se definio
considero que las asignaciones (LET) se pueden hacer a numeros y strings y las variables pueden contener un $ delante o detras
*/
$exp = array(RULE =>"#^[(][a-z]{1,}[)],[(][a-z]{1,}[)]#i",
DEF=>"#^[a-z]{1,},[a-z]{1,}#i",LET=>"#^[$]?[a-z]{1,}[$]?[ ]{0,}[=][ ]{0,}[0-9a-z]{1,}#i",REGEX=>"#__defini_expresion__#");
// Nuevas reglas ?
if ($new_defs!=NULL)
{
foreach ($new_defs as $key => $def){
$exp[$key]=$def;
}
}
$handle = @fopen($file, "r");
if (!$handle){
throw new Exception ("Falla al abrir archivo $file");
}else{
$c =0; $ignore_ln = false;
while (($buffer = fgets($handle, 4096)) !== false) {
### elimino comentarios tipo doble barra (//)
$pos = strpos (' '.$buffer,'//');
if ($pos === false) {
}else{
$buffer = substr($buffer,0,$pos-1);
}
### comentarios tipo /* ... */
$out = null;
$len = strlen($buffer);
$pos = strpos (' '.$buffer,'/*');
$pos2= strpos ($buffer,'*/');
if (($pos !== false) and ($pos2 !== false))
{
// comentarios /* */ en la misma linea (mono)
$buffer = substr ($buffer,0,$pos-1).substr ($buffer,$pos2+2,$len-$pos2);
$ignore_ln = false;
}
// OK.. los mono-linea ya desaparecieron
// Ahora voy por los MULTIlinea
$len = strlen($buffer);
$pos = strpos (' '.$buffer,'/*');
$pos2 = strpos ($buffer,'*/');
if ($pos === false) {
// busco cierre de commentarios realmente multi-linea
if ($ignore_ln){
$pos2 = strpos ($buffer,'*/');
if ($pos2 === false){
}else{
$buffer = substr ($buffer,$pos2+2,$len-$pos2);
$ignore_ln = false;
}
}
}else{
// busco cierre de commentarios multi-linea en la misma linea de apertura
$buffer = substr ($buffer,0,$pos-1);
$pos2 = strpos ($buffer,'*/');
if ($pos2 === false){
// es realmente multi-linea
$out = substr ($buffer,0,$pos-1);
$ignore_ln = true;
}else{
}
}
// busco fin de commentarios multi-linea
if ($ignore_ln){
$pos2 = strpos (' '.$buffer,'*/');
if ($pos2 === false) {
}else{
// dejo solo lo posterior al fin del comentario multi-linea
$buffer = substr ($buffer,$pos2+1,$len-$pos2);
$ignore_ln = false;
}
}
// descarto la linea presente
if ($out==NULL){
if ($ignore_ln) continue;
}else{
$buffer = $out;
}
$lt = ltrim($buffer);
if (empty($lt))
continue;
### elimino blancos ( ) y comentarios tipo punto_y_coma (;)
if ($lt[0]==';' OR $lt[0]=='#')
continue;
if ( (strlen(trim($buffer))>0) ){
$fields = explode(',',$buffer);
switch (count($fields)){
# definicion o regla
case 2:
# definicion: plural, singular
if (preg_match($exp[DEF],$buffer)){
$rows[$c]['fields']= $fields;
$rows[$c]['type']= DEF;
}else{
# regla: (terminacion plural,terminacion singular)
if (preg_match($exp[RULE],$buffer)){
$rows[$c]['fields']= $fields;
$rows[$c]['type']= RULE;
}else{
# no es nada... podria generar excepcion, warning o ignorarlo
}
}
break;
# expresion regular
case 1:
# deberia *comprobar* es verdaderamente una expr. regular
if (preg_match($exp[REGEX],$buffer)){
$rows[$c]['fields']= $fields;
$rows[$c]['type']= REGEX;
}else{
if (preg_match($exp[LET],$buffer)){
# aca procesaria las asignaciones
$fields=explode('=',$buffer);
$rows[$c]['fields']= $fields;
$rows[$c]['type']= LET;
}
}
break;
default:
// CSV: devuelvo array de columnas (campo1,campo2,...campoN)
$rows[$c]= $fields;
break;
}
++$c;
} // while
}
if (!feof($handle)) {
throw new Exception("Error: unexpected fgets() fail\n");
}
fclose($handle);
}
return $rows;
} // en fn