Posts Tagged ‘ PHP

Classe PHP para gerar XML

Ano passado fiz uma classe simples para gerar arquivos XML a partir de um Array Associativo de um modo mais prático. Fiquei surpreso semana passada com o número de downloads e o feedback positivo que tive ao publica-la no phpclasses.org, por isso vou postar aqui também.

Exemplo de Uso

	header("Content-type:application/xml; charset=utf-8");
	$tmp = $this->Search("SELECT id, nome FROM usuarios");

	$objXml = new Xml();
	$objXml->addContent($tmp,'usuarios');
	echo $objXml->showXML();

Classe XML.Class.php

	/**
	* Classe responsável por formatar conteúdos em arquivos XMl
	*
	* @author Marcos Timm Rossow 
	* @version 0.1
	* @copyright Interwise
	* @access Public
	* @package ADM
	*/
	class Xml
	{
		/**
		* Variável com o nome do sistema
		* O nome do sistema é o root do documento xml
		* Por padrão define o sistema definido no arquivo de configuração
		* @access Private
		* @name $_root
		*/
		private $_root = "root";

		/**
		* Variável com o tipo de codificação
		* @access Private
		* @name $_root
		*/
		private $_codificacao = 'UTF-8';

		/**
		* Versão do documento de saída
		* @access Private
		* @name $_versao_xml
		*/
		private $_versao_xml = '1.0';

		/**
		* Objeto de construção do arquivo XML
		* @access Private
		* @name $_obj_xml
		*/
		private $_obj_xml;

		/**
		* Método construtor.
		* Inicia o objeto e cria o root com o nome do sistema especificado no arquivo de configuração
		* @access Public
		* @param String $_root possibilita definir outro nome ao root do documento diferente do informado no arquivo de configuração do sistema
		* @param String $_codificacao possibilita definir outro tipo de codificação. O padrão é UTF-8
		* @param String $_versao_xml possibilita alterar a versão de saída do arquivo XML. Por padrão, versão 1.0
		* @return bool
		*/
		public function __construct($_root = FALSE, $_codificacao = FALSE, $_versao_xml = FALSE)
		{
			// caso  tenha sido passado um nome para o sistema, define o mesmo
			if(isset($_root) AND "" != $_root)
				$this->_root = $_root;

			// caso  tenha sido passado a codificação do sistema, define o mesmo
			if(isset($_codificacao) AND "" != $_codificacao)
				$this->_codificacao = $_codificacao;

			// caso  tenha sido passado versão de saída do arquivo xml, define o mesmo
			if(isset($_versao_xml) AND "" != $_versao_xml)
				$this->_versao_xml = $_versao_xml;

			// inicia o objeto XmlWriter
			$this->_obj_xml = new XmlWriter();
			// inicia a memória
			$this->_obj_xml->openMemory();
			// inicia o documento passando como parâmetro a versão do documento xml e o tipo de codificação que será usada
			$this->_obj_xml->startDocument($this->_versao_xml, $this->_codificacao);
			// cria a raiz do documento com o nome do sistema
			$this->_obj_xml->startElement($this->_root);
			// habilita a identação do documento
			$this->_obj_xml->setIndent(TRUE);
			// define 3 espaços para serem utilizados como identação afim de ficar mais claro no debug
			$this->_obj_xml->setIndentString("   ");

			return true;
		}

		/**
		* Método para adicionar conteúdo ao XML
		* Inicia o objeto e cria o root com o nome do sistema especificado no arquivo de configuração
		* @access Public
		* @param String $_array_dados Array de forma associativa com dados a serem inseridos no objeto XML
		* @return bool
		*/
		public function addContent($_arr_dados, $_str_indice = FALSE)
		{
			// verifica se foi passado um array válido
			if(is_array($_arr_dados) AND 0 < count($_arr_dados))
			{
				// percorre os elementos do array
				foreach($_arr_dados as $chave => $valor)
				{
					// verifica se existem filhos para este array
					if(is_array($valor))
					{
						// abre o elemento
						$this->_obj_xml->startElement($_str_indice);
						// define o primeiro valor como atributo
						//$this->_obj_xml->writeAttribute("id", $valor[key($valor)]);

						// retira a chave
						//array_shift($valor);

						// recursividade para inserir um elemento interno
						$this->addContent($valor);

						// finaliza o elemento
						$this->_obj_xml->endElement();

						// continua percorrendo o array
						continue;
					}

					// insere elementos que não contenham mais filhos
					@$this->_obj_xml->writeElement($chave,$valor);
				}

				return true;
			}
			else
			{
				// debug
				// array inválido
			}
		}

		/**
		* Método para retornar o arquivo XML gerado
		* @access Public
		* @return string
		*/
		public function showXML()
		{
			// finaliza o objeto
			$this->_obj_xml->setIndent(true);
			$this->_obj_xml->endElement();

			// retorna o XML gerado
			return $this->_obj_xml->outputMemory(true);
		}
	}

Está bem comentada. Acho que é bem fácil de entender.

Quem preferir baixar diretamente do PHPClasses: Simple XML Generator

Em breve vou postar outras Classes PHP que ajudam a tornar a vida mais simples.

Menu em ExtJS com Permissões usando PHP e Mysql

Uma das coisas que mais me deu dor de cabeça quando comecei a trabalhar com ExtJS foi montar uma estrutura de Menu Dinâmico de acordo com as permissões do usuário logado. Por isso vou compartilhar minha solução:

Primeiro de tudo vamos criar o nosso banco de dados. Vamos precisar de duas tabelas: uma para o nosso menu e outra com as permissões de cada usuário.

A tabela do Menu terá os campos de id (o id do objeto no Extjs para facilitar manipulação posterior), o nome, o ícone, a pai (caso exista), a ordem e é claro a função que será chamada na ação do clique. Na segunda tabela vamos ter apenas duas chave, o id do usuário e o id do menu. Segue abaixo de exemplo a que eu utilizei:

MySQL

#
# Estrutura da Tabela Menu
#

CREATE TABLE /*!32312 IF NOT EXISTS*/ `menu` (
  `id_menu` int(3) NOT NULL AUTO_INCREMENT,
  `id` varchar(20) DEFAULT NULL,
  `menu` varchar(70) DEFAULT NULL,
  `ordem` int(3) DEFAULT NULL,
  `pai` int(3) DEFAULT NULL,
  `ico` varchar(50) DEFAULT NULL,
  `funcao` varchar(80) DEFAULT NULL,
  PRIMARY KEY (`id_menu`)
) TYPE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=latin1;

#
# Estrutura da Tabela de Permissões
#

CREATE TABLE /*!32312 IF NOT EXISTS*/ `permissoes` (
  `id_usuario` int(3) NOT NULL DEFAULT '0',
  `id_menu` int(3) NOT NULL DEFAULT '0',
  PRIMARY KEY (`id_menu`,`id_usuario`)
) TYPE=MyISAM DEFAULT CHARSET=latin1;

Dica: Vale lembrar que o ícone dos pais são definidos pelo nome da classe CSS e os filhos devemos especificar o caminho físico da imagem. Não sei por que, mas sub-menus não possuem o atributo “iconCls”. No PHP já vamos levar isso em conta.

A outra parte do nosso Menu é a montagem do Json que irá ser lido no ExtJS. Este método foi testado apenas com 1 sub-nível de menu, mas é fácil de modificar para funcionar com mais. Se alguém fizer, comente a experiência. O método é bem simples de entender. Basicamente buscamos os ítens do Menu principal e percorremos ele em busca de sub-menus alocando tudo em um array associativo.

PHP

		private function trataObjJson($strJson,$arrObjs)
		{
			foreach($arrObjs AS $obj)
				$strJson = str_replace(&amp;amp;amp;quot;\&amp;amp;amp;quot;&amp;amp;amp;quot; . $obj . &amp;amp;amp;quot;\&amp;amp;amp;quot;&amp;amp;amp;quot;,$obj,$strJson);
			return $strJson;
		}

		public function getMenu()
		{
			if($this-&amp;amp;amp;gt;Search(&amp;amp;amp;quot;SELECT id_usuario FROM usuarios WHERE id_usuario=&amp;amp;amp;quot; . $_SESSION['id_usuario']))
			{
				$menu = &amp;amp;amp;quot;&amp;amp;amp;quot;;
				$tmpMenuPai = $this-&amp;amp;amp;gt;Search(&amp;amp;amp;quot;SELECT A.id_menu,id,menu,ordem,pai,ico,funcao FROM menu A JOIN permissoes B ON A.id_menu=B.id_menu WHERE A.pai=0 AND B.id_usuario=&amp;amp;amp;quot; . $_SESSION['id_usuario'] . &amp;amp;amp;quot; ORDER By A.ordem&amp;amp;amp;quot;);
				$i=0;
				$funcoes = array();
				foreach($tmpMenuPai AS $item)
				{
					$menu[$i]['text'] 			= $item['menu'];
					$menu[$i]['iconCls'] 		= $item['ico'];
					$menu[$i]['tabIndex'] 		= $i;
					if($item['funcao']) {
						$menu[$i]['id'] 		= $item['id'];

						$menu[$i]['handler'] 	= $item['funcao'];
						$funcoes[] = $item['funcao'];
					}

					$tmpMenuFilho = $this-&amp;amp;amp;gt;Search(&amp;amp;amp;quot;SELECT A.id_menu,menu,id,ordem,ico,funcao FROM menu A JOIN permissoes B ON A.id_menu=B.id_menu WHERE A.pai=&amp;amp;amp;quot; . $item['id_menu'] . &amp;amp;amp;quot; AND B.id_usuario=&amp;amp;amp;quot; . $this-&amp;amp;amp;gt;_id . &amp;amp;amp;quot; ORDER By A.ordem&amp;amp;amp;quot;);
					$arrFilho = Array();
					$j=0;
					foreach($tmpMenuFilho AS $filho)
					{
						$arrFilho[$j]['text']			= $filho['menu'];
						$arrFilho[$j]['icon']			= $filho['ico'];
						if($filho['funcao']) {
							$arrFilho[$j]['id'] 		= $filho['id'];

							$arrFilho[$j]['handler'] 	= $filho['funcao'];
							$funcoes[] = $filho['funcao'];
						}
						$j++;
					}
					if($arrFilho)
						$menu[$i]['menu'] = $arrFilho;
					$i++;
				}
				header(&amp;amp;amp;quot;Content-Type: application/json&amp;amp;amp;quot;);
				echo $this-&amp;amp;amp;gt;trataObjJson(json_encode($menu),$funcoes);
			}
		}

Observe que precisamos de um método auxiliar para tratar as funções. Isso se deve pelo fato da função json_encode do PHP colocar áspas em tudo, então para o ExtJS não interpretar nossa função como uma string e gerar um erro, utilizamos uma função para retira-las.

Agora que já temos a nossa estrutura de menu em Json, bastam poucas linhas em ExtJS para finalizar:

ExtJS

Ext.onReady(function(){
 	var conn = new Ext.data.Connection();
	conn.request({
		url: 'inc/php/menu.class.php',
		success: function(a){Ext.getCmp('menuPrincipal').bottomToolbar.add(Ext.util.JSON.decode(a.responseText));},
		failure: function(){Ext.MessageBox.alert('Erro', 'Erro ao carregar menu. Atualize a página.');}
	});
});

Espero ter ajudado.

The Ubuntu Counter Project - user number # 31874