Dica rápida: PHP + BYTEA

Fala galera! Estava aqui tentando exibir imagens armazenadas em um campo bytea do PostgreSQL e apanhei feito mala velha usando o par de funções pg_escape_bytea e pg_unescape_bytea.

Consegui achar a solução em um comentário no manual do PHP: “To prevent any problems with encoding you could use hexadecimal or base64 input to save and retrieve data to the database”

Usei base64_encode/base64_decode e tudo funcionou perfeitamente. Então, se você está tentando usar pg_escape_bytea($content) e pg_unescape_bytea($content) mude para base64_encode($content) para inserir no banco e base64_decode($content) para exibir no browser.

Valeu Mike-RaWare!

Para quem quiser ver o post: http://php.net/manual/en/function.pg-escape-bytea.php

PHP-GTK2 + Glade 3 = fatal error

Você já viu esse erro?

(php.exe:4416): libglade-WARNING **: Expected <glade-interface>.  Got <interface>.
(php.exe:4416): libglade-WARNING **: did not finish in PARSER_FINISH state

Fatal error: Uncaught exception 'PhpGtkConstructException' with message 'could n
ot construct GladeXML object' in E:\Nodo3\PHP-GTK\Sample\Sample.phpw:6
Stack trace:
#0 E:\Nodo3\PHP-GTK\Sample\Sample.phpw(6): GladeXML->__construct('Sample.glade')

#1 {main}
  thrown in E:\Nodo3\PHP-GTK\Sample\Sample.phpw on line 6

Pois é, o erro é causado pelo formato do arquivo glade: o GtkBuilder, substituto do GladeXML que foi depreciado.

É muito difícil encontrar informações sobre php-gtk2, mas pelo que pude entender, ele não tem suporte total ao padrão GtkBuilder, logo .. é melhor continuar usando GladeXML.

Para resolver o problema, abra o menu Editar > Preferências, e altere o formato de saída do arquivo para Libglade.
Se alguém tiver informações mais precisas sobre o suporte do GtkBuilder no php-gtk2 compartilha aqui ok??

Abrasss

CodeIgniter: Associação de controllers e grupo de regras no config/Form_validation

O codeigniter permite criar uma associação do ‘controller/método’ no arquivo de configuração form_validation para facilitar e centralizar a validação de formulários. É realmente excelente, desde que você não tenha parâmetros em seu método 😐 … meio estranho mas blz.

Tive esse problema e achei esse post: http://codeigniter.com/forums/viewthread/104425/ que relata o problema e indica uma solução que consiste em alterar a classe form_validation. Essa solução funciona perfeitamente mas pode causar problemas se você decidir atualizar a versão do CI e esqueceu que mudou algo lá dentro.

Segui a idéia dele e fiz o ‘patch’ no próprio config/form_validation.
Ficou algo assim:

$CI =& get_instance();

$config = array(
	"blog/post/{$CI->uri->segment(3)}" => array(
		array(
				'field' => 'titulo',
				'label' => 'Título',
				'rules' => 'required'
			 ),
		array(
				'field' => 'conteudo',
				'label' => 'Conteúdo',
				'rules' => 'required'
			 )
		)
);

Espero ter ajudado.

Abrassss!!!

Codeigniter + jqTransform + Combos dinâmicos

Esse post é em homenagem a meu amigo Ubiracy mais conhecido como Bira-bira-birô hehehehe, que junto comigo, se mordeu todo pra tentar resolver esse problema. Depois de muito pesquisar e nada encontrar, conseguimos criar elementos options em tempo de execução no jqTransform, que é um plugin jquery pra customizar a cara dos formulários. Bonitinho mas ordinário.

Pois bem, vamos precisar de:

  • jqTransform
  • Algum conhecimento em JSON
  • Algum conhecimento em Ajax
  • Codeigniter (opcional)

A solução funciona da seguinte forma, você vai criar dois combos, um de estados e outro de cidades. Os itens do combo de cidades vão ser carregados dinamicamente via ajax a depender do que foi selecionado no combo de estados.

  1. JSON
    Crie um método em seu model que realiza a consulta de cidades
    public function lista_cidades($id_estado)
    {
        $this->db->select("id, nome");
        $this->db->where("id_estado", $id_estado);
    
        return $this->db->get("cidades");
    }
    

    Em seu controller, crie um novo método público que escreva no browser o resultado da consulta no padrão json.

    public function cidades($id_estado)
    {
        header('Content-type: application/json');
        $this->load->model("cidade_model");
        $cidades = $this->cidade_model->lista_cidades($id_estado)->result_array();
        $json = "[";
        foreach ($cidades as $cidade) {
    	$json.= '{"value": "{$cidade['id']}", "label": "{$cidade['nome']}",';
        }
        $json = preg_replace("/,$/", "", $json);
        $json.= "[";
    }
    

    Pronto, agora você já tem um método em seu controller que filtra as cidades por estado e gera um documento json.

  2. HTML
    <tr>;
    	<td>Estado:</td>
    	<td><div id="div_cmb_estado" class="select-menus"><?php echo form_dropdown('cmb_estado', $cmb_estado); ?></div></td>;
    	<td>Cidade:</td>
    	<td>
    		<div id="container">
    			<div id="div_cmb_cidade" class="select-menus"><select id="cmb_cidade" name="cmb_cidade"></select></div>
    		</div>
    	</td>
    </tr>
    


    Crie o combo de estados normalmente, se você estiver usando form helper como eu, chame a função form_dropdown passando os dados que irão compor este combo. Observe que a variável $cmb_estado contém o array de dados que popula o combo de estados.
    Já o combo cidades (neste nosso exemplo), não terá nenhum registro inicialmente. Ele será preenchido dinamicamente como falei anteriormente. O pulo do gato é a div container. Os elementos que irão compor o combo devem ficar dentro dessa div.

  3. Ajax
    Finalmente, o ajax para criar o options. Basta chamar a url do seu método que cria o json e fazer o parser no resultado.
    $(document).ready(function() {
    
    	// Aplica o skin com jqTransform
    	$("form.jqtransform").jqTransform();
    
             // OnClick no item do combo de estados
    	$("#div_cmb_estado div.jqTransformSelectWrapper ul li a").click(function(){
    
    	// Recupera o valor do item selecionado
    	var index = $(this).attr('index');
    	var value = $('#div_cmb_estado div.jqTransformSelectWrapper option:eq(' + index + ')').attr('value');
    
    	// Chamada ao método criado no controller via ajax
    	$.ajax({
    	    type: "GET",
    	    async: true,
    	    url: "/exemplo/cidades/" + value,
    	    dataType:"json",
    	    error: function(XMLHttpRequest, textStatus, errorThrown) {
    		   alert(textStatus);
    	    },
    	    success: function(resposta){
    
    		// Limpa o "combo" de cidades
    		var html_combo = '<div id="div_cmb_cidade" class="select-menus"><select id="cmb_cidades" name="cmb_cidades"></div>';
    		$("#container").html(html_combo);
    
    		// Faz o parser no json e cria os elementos
    		for (i = 0; i < resposta.length; i++) {
    		   $("#cmb_cidades").append('<option selected value="' + resposta[i].value + '">' + resposta[i].label + '</option>');
    		}
    
    		// Chama novamente o jqTransform para o select. Funciona como um refresh no layout
    	         $("#cmb_cidades").jqTransSelect();
    		}
    	    });
    	});
    });
    

Espero ter ajudado, até o próximo post.

obs: Esse editor do wordpress é muito bom, ¬¬

Blob do SQL Server truncados no PHP

Hello folks, depois de um bom tempo sem postar nada vai ai uma dica de configuração do PHP com SQL Server. Essa dica é para quem está recuperando um blob (varbinary, image, etc) e quando é exibido pelo PHP vem truncado… exibindo parte da imagem e o resto em cinza indicando que ali teria que ter algo =]. Para resolver basta alterar o valor das propriedades mssql.textlimit e mssql.textsize no php.ini. Lembrando que os valores estão em bytes.

Abrasss

Alternar CSS (Toggle)

Uma função simples para alternar css com PHP. Essa dica é útil para por exemplo, alternar cor de linhas de uma grade. E com essa função você leva inteiramente grátis uma outra para definir várias caso elas não existam, algo como a tag <CFPARAM> do ColdFusion.

Segue o código abaixo:


if ( ! function_exists('def')) {

	function def(&$var, $default = "", $type = NULL, $pattern = NULL)
	{
		if (empty($var) || !isset($var)) {
			$var = $default;
		}

		if (! is_null($pattern)) {

			if (preg_match($pattern, $default) === 0) {
				throw new Exception("The default value assigned is incorrect");
			}
		}

		if (! is_null($type)) {
			settype($var, $type);
		}
	}
}

/**
 * Alterna estilos css
 *
 * @param string
 * @param string
 * @param string
 * @return string
 */
if ( ! function_exists('toggle_css') ) {

	function toggle_css(&$class, $class_1, $class_2)
	{
		def($class, '');

		$class = ( $class == $class_1) ? $class_2 : $class_1;
		return $class;
	 }
}

Pronto, para usar, siga o exemplo abaixo:

// Loop
<div class="<?php echo toggle_css($css, 'class1', 'class2');?>">Linha 1</div>

Abrasss

PHP 5.2.13 + Apache 2.2.15 (Windows)

Eu e algumas muitas pessoas, estão encontrando muita dificuldade para instalar o PHP 5.2.13 com Apache 2.2.15. Páginas em branco, erro no php5ts.dll ao tentar iniciar o apache são alguns dos sintomas.

Consegui com muito custo resolver o problema. Vamos a solução!

Ingredientes

  • PHP 5.2.13
  • Apache 2.2.15
  • msvcr71.dll (em alguns casos)

Instale normalmente o Apache e o PHP. Depois vá até o prompt de comando e execute (se o PHP não estiver no path do sistema, acesse o diretório de instalação do PHP):

C:\php -v

Provavelmente você receberá algumas mensagens de erro sobre extensões. Desabilite as extensões que estão dando erro e que você não utiliza. No meu caso desabilitei as extensões do oracle, snmp, sqlite e sybase.

Em alguns casos o PHP reclama da biblioteca msvcr71.dll, se for o seu caso, baixe aqui e salve-a na pasta windows/system32.

Salve suas alterações no php.ini e rode novamente o comando php -v. Desabilite as extensões até que nenhuma mensagem de erro seja exibida.

Crie um script php com o conteúdo <?php phpinfo();?> e coloque no document root. Inicie o apache e acesse essa página. Ficou em branco? Algum extensão que está habilitada não apareceu? Abra o seu httpd.conf e adicione a diretiva PHPIniDir apontando para o caminho do seu php.ini. Algo como PHPIniDir “C:/PHP/php.ini”.

Reinicie o apache e tente executar o script novamente.

Até o próximo post.

Postgres (Large Objects) + CodeIgniter (Image_Lib)

Estou no início do meu aprendizado com CodeIgniter e PostgreSQL e nesse pouco tempo não vi nenhuma referência à manipulação de blobs na documentação ou mesmo no código do framework. Para contornar o problema criei um helper para me auxiliar nessa tarefa. Utilizando as funções nativas do PHP em conjunto com o CodeIgniter, você pode manipular facilmente seus large objects. O único problema que tive foi com a image_lib usando gd2 e imagens geradas com pg_lo_read_all, sendo totalmente on the fly, isso ficará para um outro post.

Ok, vamos ao que interessa:

  • Exportando o large object – método 1
if ( ! function_exists('pgsql_lo_export')) {

	function pgsql_lo_export($id_object, $caminho_arquivo)
	{
		$CI =& get_instance();

		// Inicia a transação
		$CI->db->trans_start();

		// Exporta o arquivo
		$retorno = pg_lo_export($id_object, $caminho_arquivo);

		// Encerra a transação
		$CI->db->trans_complete();

		return $retorno;
	}
}

linha 5: Recupera a instância do CodeIgniter, sem isso não é possível usar as bibliotecas.

linha 8 e 14: Todas as funções de manipulação dos large objects devem estar dentro de uma transação e também precisam de um resource para a conexão. Essas linhas resolvem os dois problemas, engloba a chamada da função em uma transação e também cria uma conexão padrão. Não entendeu? clique aqui.

linha 11: Faz a mágica da exportação

  • Exibir a imagem – método 1
// Método do controller
public function thumbnail($oid)
{
	// define os diretórios
	$diretorio_saida = str_replace(SELF,'',APPPATH)."uploads/";
	$arquivo_saida = tempnam($diretorio_saida,'fa_');

	// Exporta o large object
	pgsql_lo_export($oid, $arquivo_saida);

	$config['image_library'] = 'gd2';
	$config['source_image'] = $arquivo_saida;
	$config['dynamic_output'] = TRUE;
	$config['create_thumb'] = TRUE;
	$config['maintain_ratio'] = TRUE;
	$config['width'] = 160;
	$config['height'] = 120;

	// Carrega a image_lib
	$this->load->library('image_lib', $config);

	// Tenta redimensionar a imagem
	if ( ! $this->image_lib->resize())
	{
		echo $this->image_lib->display_errors();
	}

	// Apaga o arquivo temporário
	unlink($arquivo_saida);
}

linha 5 e 6: Define onde gerar os arquivos temporários. Atenção para a linha 6 que usa a função tempnam, essa função cria um arquivo temporário com nome único. Vai ser útil para evitar problemas com nomes de arquivos

linha 9: Exporta o blob para o arquivo temporário usando a função criada anteriormente

linha 13 e 14: A opção dynamic_output indica que a imagem não será salva no disco (on the fly) e create_thumb que o arquivo original não será modificado

linha 23: Redimensiona nossa imagem

linha 29: Apaga nosso arquivo temporário

  • Exibir a imagem – método 2 (sem churumelas)
if ( ! function_exists('pgsql_lo_read_all')) {

	function pgsql_lo_read_all($id_objeto)
	{

		$CI =& get_instance();

		// Inicia a transação
		$CI->db->trans_start();

		// Abre o OID para leitura e envia para o browser
		$hnd = pg_lo_open($id_objeto, "r");
		pg_lo_read_all($hnd);
		pg_lo_close($hnd);

		// Encerra a transação
		$CI->db->trans_complete();

	}
}

Essa função é bem parecida com a primeira função, a diferença é que ela não exporta o binário para um arquivo no disco, o conteúdo é enviado diretamente para o browser usando pg_lo_read_all.

É isso ai, chega de programar … agora é a vez da cremosa gelada. Boas festas e até o próximo post.

Dica rápida: Executar um arquivo batch através do PHP

Uma dica rápida pra quem está tentando executar um arquivo .bat usando o php. Dê permissão ao usuário do apache ou IIS para executar o cmd.exe, feito isso, chame o seu bat usando como ponte  prompt de comando: exec(“cmd.exe \c arquivo.bat”)

Lembre-se que seu script batch não deve ter interação com o usuário 😉

Abrasss

CodeIgniter: Remover index.php da URL

Estou iniciando com o CodeIgniter e me deparei com um pequeno problema que aparentemente não chegava nem a ser um problema – remover o index.php da URL. Aparentemente era só criar uma regra no htaccess e a mágica estaria feita … não foi bem assim que aconteceu 🙂

Resolvi da seguinte forma:

1. Habilitar o ModRewrite no Apache

Abra o httpd.conf e descomente a linha LoadModule rewrite_module modules/mod_rewrite.so e reinicie o apache.

2.  htaccess

Crie um .htaccess na raiz do seu projeto. O arquivo deve estar no mesmo nível da pasta system.

RewriteEngine on
RewriteCond $1 !^(index\.php|system|images)
RewriteRule ^(.*)$ /index.php/$1

Muita atenção com as barras (/). A maioria das dicas e tutoriais que você vai encontrar por ai leva em conta que seu projeto está no document root e não em um alias (diretório virtual). Se você estiver usando um diretório virtual use o RewriteBase para indicar qual a url base de seu projeto e em RewriteRule remova a barra da frente de index.php para indicar que o arquivo não está na raiz do servidor (document root) e sim no diretório virtual.

RewriteEngine on
RewriteBase /meu_projeto/
RewriteCond $1 !^(index\.php|system|images)
RewriteRule ^(.*)$ index.php/$1

3. config.php

Aqui foi onde eu apanhei feito mala velha. Depois de criar a regra no htacess, o modrewrite não funcionava .. não sei bem ainda o por quê, mas encontrei em um fórum que era necessário alterar uma linha do config.php na pasta application.
Altere a linha $config[‘index_page’] = “index.php” para $config[‘index_page’] = “”.

Pronto, problema resolvido.

Abraços