Jump to content

Archived

This topic is now archived and is closed to further replies.

João Batista Neto

Criando arquivos .ini com PHP usando Composite

Recommended Posts

Analisando um arquivo .ini é possível perceber que se trata de uma composição de comentários e seções onde cada seção possui um ou mais parâmetros e cada parâmetro é composto pelo par nome=valor.

Para criar esse tipo de arquivo é possível utilizar um padrão de projeto chamado composite:

Imagem Postada


Apesar de termos conhecimento de que o arquivo .ini é de fato uma composição, cada item dessa composição possui regras próprias e, para que não tenhamos que conhecer essas regras em um único objeto deixamos com que cada item da composição faça seu trabalho permitindo que tratemos todos os elementos de uma forma comum.

Para o nosso arquivo .ini os participantes são:

Comentários e valor de um parâmetro Imagem Postada Leaf Imagem Postada São elementos finais, que não possuem nós filhos.
Nome de um parâmetro, seção e o próprio arquivo.ini Imagem Postada Composite Imagem Postada Possuem um ou mais nós filhos.

Uma implementação simples em PHP ficaria assim:

INIFormat.php

<?php
/**
* Define a interface do Component
*/
interface INIFormat extends IteratorAggregate {
/**
* Adiciona um nó filho ao componente
* @param INIFormat $leaf
*/
public function add( INIFormat $leaf );

/**
* Grava o componente no arquivo
* @param IFileObject $fo
* @param string $eol Delimitador de fim de linha
*/
public function write( IFileObject $fo , $eol = PHP_EOL );
}



AbstractINIComposite.php

<?php
/**
* Define a interface da composição
* @abstract
*/
abstract class AbstractINIComposite implements INIFormat {
private $leafs;

/**
* Inicializa o objeto da composição
*/
public function __construct(){
$this->leafs = new ArrayIterator();
}

/**
* Adiciona um nó filho ao componente
* @param INIFormat $leaf
*/
public function add( INIFormat $leaf ){
$this->leafs[] = $leaf;
}

/**
* Recupera um Iterator com os nós filhos da composição
* @return ArrayIterator
*/
public function getIterator(){
return $this->leafs;
}
}



AbstractINILeaf.php

<?php
/**
* Define a interface para os nós que não possuem filhos
* @abstract
*/
abstract class AbstractINILeaf implements INIFormat {
/**
* @param INIFormat $leaf
* @throws LogicException Como uma folha não pode ter nós filhos, sempre dispara um LogicException
*/
public function add( INIFormat $leaf ){
throw new LogicException( 'Um nó final não pode ter nós filhos.' );
}

/**
* Como uma folha não pode ter nós filhos, sempre retorna um Iterator vazio
* @return ArrayIterator
*/
public function getIterator(){
static $iterator = null;

if ( $iterator == null ) $iterator = new ArrayIterator();

return $iterator;
}
}



INIParameter.php

<?php
/**
* Parâmetro de uma seção
*/
class INIParameter extends AbstractINIComposite {
/**
* @var string
*/
private $name;

/**
* Constroi um novo parâmetro de seção
* @param string $name O nome do parâmetro
*/
public function __construct( $name ){
parent::__construct();
$this->name =& $name;
}

/**
* Implementa o método write para gravar no arquivo
* @param IFileObject $fo Objeto que será usado para gravar no arquivo
* @param string $eol Delimitador de fim de linha
*/
public function write( IFileObject $fo , $eol = PHP_EOL ){
$iterator = $this->getIterator();
$name = $this->name;

if ( ( $total = $iterator->count() ) >= 1 ){
if ( $total > 1 ){
$name = sprintf( '%s[]' , $name );
}

foreach ( $iterator as $leaf ){
$fo->write( sprintf( '%s=' , $name ) );
$leaf->write( $fo , $eol );
}
} else {
throw new LogicException( sprintf( 'O parâmetro %s precisa possuir pelo menos 1 valor.' , $this->name ) );
}
}
}



INIValue.php

<?php
/**
* Valor de um parâmetro
*/
class INIValue extends AbstractINILeaf {
private $value;

/**
* Constroi o valor de um parâmetro
* @param string $value
*/
public function __construct( $value ){
$this->value =& $value;
}

/**
* Grava o valor no arquivo
* @param IFileObject $fo
* @param string $eol
*/
public function write( IFileObject $fo , $eol = PHP_EOL ){
$fo->write( sprintf( '%s%s' , $this->value , $eol ) );
}
}



INIComment.php

<?php
/**
* Comentário de um arquivo ou seção
*/
class INIComment extends AbstractINILeaf {
/**
* @var string
*/
private $comment;

/**
* Constroi o comentário
* @param string $comment
*/
public function __construct( $comment ){
$this->comment =& $comment;
}

/**
* Grava o comentário no arquivo
* @param IFileObject $fo
* @param string $eol
*/
public function write( IFileObject $fo , $eol = PHP_EOL ){
$fo->write( sprintf( '; %s%s' , $this->comment , $eol ) );
}
}



INISection.php

<?php
/**
* Seção de parâmetros
*/
class INISection extends AbstractINIComposite {
/**
* @var string
*/
private $name;

/**
* Constroi a nova seção
* @param string $name
*/
public function __construct( $name ){
parent::__construct();
$this->name =& $name;
}

/**
* Grava a seção no arquivo
* @param IFileObject $fo
* @param string $eol
*/
public function write( IFileObject $fo , $eol = PHP_EOL ){
$fo->write( sprintf( '[%s]%s' , $this->name , $eol ) );

foreach ( $this as $leaf ){
$leaf->write( $fo , $eol );
}
}
}



INIFile.php

<?php
/**
* Arquivo INI
*/
class INIFile extends AbstractINIComposite {
/**
* @var string
*/
private $file;

/**
* Constroi o novo arquivo
* @param string $file
*/
public function __construct( $file ){
parent::__construct();
$this->file =& $file;
}

/**
* Grava o arquivo em disco
* @param IFileObject $fo
* @param string $eol
*/
public function write( IFileObject $fo , $eol = PHP_EOL ){
$fo->open( $this->file , 'w+' );

foreach ( $this as $leaf ){
$leaf->write( $fo , $eol );
}

$fo->close();
}
}



Para demonstrar o funcionamento, vamos usar um objeto para gravar em disco que na verdade irá apenas exibir o conteúdo do arquivo INI gerado:
IFileObject.php

<?php
interface IFileObject {
public function close();
public function open( $name , $method );
public function write( $content );
}



FileObject.php

<?php
class FileObject implements IFileObject {
public function close(){
echo '--- Fechando o arquivo ---' , PHP_EOL;
}

public function open( $name , $method ){
echo '--- Abrindo o arquivo: ' , $name , ' ---' , PHP_EOL;
}

public function write( $content ){
echo $content;
}
}



Usando isso tudo:

<?php
$ini = new INIFile( 'teste.ini' );
$ini->add( new INIComment( 'Abaixo uma nova seção' ) );

$imasters = new INISection( 'iMasters' );
$imasters->add( new INIComment( 'O parâmetro teste possui vários valores' ) );
$teste = new INIParameter( 'teste' );
$teste->add( new INIValue( 'valor 1' ) );
$teste->add( new INIValue( 'valor 2' ) );
$teste->add( new INIValue( 'valor 3' ) );
$imasters->add( $teste );

$imasters->add( new INIComment( 'O parâmetro outro possui só um valor' ) );
$outro = new INIParameter( 'outro' );
$outro->add( new INIValue( 'apenas um' ) );
$imasters->add( $outro );

$ini->add( $imasters );
$ini->write( new FileObject() );



A saída:

--- Abrindo o arquivo: teste.ini ---; Abaixo uma nova seção[iMasters]; O parâmetro teste possui vários valoresteste[]=valor 1teste[]=valor 2teste[]=valor 3; O parâmetro outro possui só um valoroutro=apenas um--- Fechando o arquivo ---


Agora é só implementar a classe FileObject para que ela faça o que tem que fazer (gravar em disco) que tudo estará funcionando.

Imagem Postada

 

 

 

 

Share this post


Link to post
Share on other sites

Muito bom mesmo, mas havia lido direto pelo seu blog.

Share this post


Link to post
Share on other sites

Interessante, mas, na prática poderia ser assim?

 

//dados somente para demonstração
$ini = array(
			'db' => array(
							'host'  => 'localhost',
							'user'  => 'root',
							'pass'  => 'x12Hj456',
							'dbase' => 'database'
						),
			'app' => array(
							'path'  => '/var/www/site/',
							'app'   => '/var/www/site/app/',
							'libs'  => array(
											  'class'  => '/var/www/site/class/',
											  'helper' => '/var/www/site/helper/'
											 )
						)
		);

//mostrando o resultado na tela
echo '<pre>'.toIniFile($ini).'</pre>';

//ou gravando no arquivo
file_put_contents('./app.ini', toIniFile($ini));


//finalmente: função que transforma um array em arquivo .ini
function toIniFile(array $ini){	
$o = '';
foreach($ini as $k=>$v){
	$o .= '['.$k."]\n";		
	//segundo nó
	if(is_array($v)){
		foreach($v as $_k=>$_v){
			//terceiro nó
			if(is_array($_v)){
				foreach($_v as $__k=>$__v){
					if(is_array($__v)) $__v = print_r($__v, true);
					$o .= "\t".$_k.'['.$__k.'] = '.(is_numeric($__v)? $__v : '"'.$__v.'"')."\n";
				}
			}else $o .= "\t".$_k.' = '.(is_numeric($_v)? $_v : '"'.$_v.'"')."\n";				
		}
	}
}
return $o;	
}

Share this post


Link to post
Share on other sites

×

Important Information

Ao usar o fórum, você concorda com nossos Terms of Use.