Snippets úteis do Zend Framework

Compartilho aqui alguns snippets e comandos úteis do Zend Framework, para referência futura e quem sabe ajudar alguém que precise.

Retornar o código de resposta 404 (Not found).

 $this->_response->clearBody()->clearHeaders()->setHttpResponseCode(404)->sendResponse(); 


Redirecionar para URL com âncora (sharp/cerquilha/jogo da velha)

 $opt = array('module' => 'admin', 'controller' => 'galeria', 'action' => 'editar', 'id' => 1); $url = $this->_helper->getHelper('Url')->url($opt); $url .= "#descricao"; $this->_helper->redirector->gotoUrl($url); 


Trocar o layout no controller

 $this->_helper->layout->setLayout('servicos'); 


Timestamp no formato de banco de dados

 Zend_Date::now()->toString('yyyy-MM-dd HH:mm:ss'); 


Desabilitar layout

 $this->_helper->layout()->disableLayout(); 


Desabilitar renderização da view

$this->_helper->viewRenderer->setNoRender(true);


Debugar consultas no banco de dados

 $db = Zend_Db_Table::getDefaultAdapter(); $profiler = $db->getProfiler()->setEnabled(true); print_r($profiler->getLastQueryProfile()); 


Dados do usuário logado (caso esteja usando Zend_Auth)

Zend_Auth::getInstance()->getIdentity();


Utilizando transações:

$db = Zend_Db_Table::getDefaultAdapter();

try{
	$db->beginTransaction();
	// query
	$db->commit();
}
catch(Exception $e){
	$db->rollBack();
}

Gerar número sequencial em query do PostgreSQL

Dica rápida para quem precisa gerar um número sequencial para cada registro retornado por uma query no PostgreSQL:

SELECT row_number() OVER (PARTITION by 0) as _seq, id, FROM pessoa

A sequência retornada começa em 1. Se quiser que ela comece em 0, basta adaptar a consulta:

SELECT row_number() OVER (PARTITION by 0) - 1 as _seq, id, nome FROM pessoa

Caso você utilize uma cláusula ORDER BY, os números gerados provavelmente estarão fora de ordem. Para corrigir este problema, basta repetir a cláusula ORDER BY dentro da função OVER, ficando como no exemplo abaixo:

SELECT row_number() OVER (PARTITION by 0 ORDER BY data) - 1 as _seq, 
id, nome FROM pessoa 
ORDER BY data

Convertendo varchar para time without time zone no PostgreSQL

Dica rápida pra quem está precisando converter um valor em varchar para time without time zone no PostgreSQL.

Usando a função to_timestamp(valor, formato), o valor retornado é um timestamp with time zone.

Porém, basta adicionar ao final da chamada da função o tipo do retorno desejado:

to_timestamp('23:59:59', 'HH24:MI:SS')::time without time zone

Tive um problema com PHP, usando PDO com PostgreSQL e a função overlaps(). Precisava passar um valor time para a função e funcionou dessa maneira.

Espero ajudar alguém.

Restringindo caracteres digitados no EditText do Android

Desenvolvendo em Android, temos alguns casos em que precisamos restringir os caracteres que são permitidos em campos como o EditText.

Um exemplo, é um campo que aceite valores como 1,80 e 1.80. No caso, se a restrição fosse somente números com . (ponto) como separador decimal, bastaria definir o android:inputType como numberDecimal. Porém, número com , (vírgula) como separador não iriam funcionar.

Para tarefas como essa, o atributo android:digits está aí para salvar a pátria. Basta definir nele quais dígitos serão permitidos naquele EditText e o Android cuida do resto.

Exemplo:

Permitir somente números, tanto com . como , como separadores decimais:

<EditText android:digits="1234567890.," android:layout_width="wrap_content" android:layout_height="wrap_content" />

Fácil, não?

Essa solução também é util para ser usada em conjunto com o android:inputType=”numberDecimal”. Nesse caso, é apresentado o teclado numérico, permitindo que vírgulas também sejam incluídas.

Exemplo:

<EditText android:digits="1234567890.," android:inputType="numberDecimal" android:layout_width="wrap_content" android:layout_height="wrap_content" />

 

Outros exemplos

Números hexadecimais:

<EditText android:digits="abcdef1234567890" android:layout_width="wrap_content" android:layout_height="wrap_content" />

Somente números pares:

<EditText android:digits=02468" android:inputType="number" android:layout_width="wrap_content" android:layout_height="wrap_content" />

 

Abraço!

Debugando seu aplicativo Android no tablet Coby Kyros Mid8024

Hoje precisei instalar uma app Android que desenvolvi no tablet de um cliente. Conectei o bicho no USB do computador e nada de reconhecer. Olhei no Gerenciador de Dispositivos do Windows 7 (infelizmente preciso trabalhar no maldito) e vi que existia um dispositivo não reconhecido, o S5P OTG-USB .

Após alguma procura, localizei o driver necessário, esse aqui. Agora, basta extrair os arquivos para alguma pasta,  ir novamente no Gerenciador de Dispositivos, clicar com o botão direito no S5P OTG-USB, clicar em Atualizar driver (ou instalar driver, se necessário) e localizar a pasta dos drivers.

Pronto. Para testar se funcionou, execute comando: adb devices e veja se seu dispositivo foi reconhecido. No meu caso, ele foi reconhecido como MID_Serials device.

Agora basta debugar seu aplicativo.

No no meu caso, eu fazia o download da app, começava a instalação, mas aparecia a mensagem: “O aplicativo não foi instalado“. Fiz o processo para debugar o aplicativo e descobri que o tablet não tinha a lib do Google Maps. O erro era esse: INSTALL_FAILED_MISSING_SHARED_LIBRARY.

O processo de debug direto no dispositivo me fez perceber o problema na hora. Se não tivesse debugado, estaria até agora tentando entender o erro. Fica a dica.

Download do driver

Link alternativo

Grande abraço!

Convertendo de UTF-8 para ISO-8859-1 em Java: A solução definitiva

Recentemente enfrentei problemas em um aplicativo Android que desenvolvi, o qual se comunica com o banco de dados de um dos sistemas da empresa, codificado em ISO-8859-1 (Firebird) através de um web service.

Os dados eram gravados de forma errada, muitas vezes truncavam e as vezes apareciam caracteres estranhos.

Depois de algumas tentativas, cheguei até a seguinte solução:






public static String convertUTF8toISO(String str) {
	String ret = null;
	try {
		ret = new String(str.getBytes("ISO-8859-1"), "UTF-8");
	} 
	catch (java.io.UnsupportedEncodingException e) {
		return null;
	}
	return ret;
}

Adicione o método acima à sua classe de utilidades e acabe com os seus problemas.

Abraço.

 

Acessando o localhost a partir do emulador do Android

Um requisito muito comum de um aplicativo desenvolvido para a plataforma Android é que o mesmo acesse um web service para troca de informações. No momento do desenvolvimento do aplicativo, geralmente o web service fica na mesma máquina em que se encontra o emulador.

Como faço pra acessar o localhost da máquina através do emulador? Usando “localhost” na string de conexão? Não funciona.

Uso o IP da minha máquina para conectar? Pode até funcionar, mas e se você estiver desconectado?

Neste caso, basta usar o IP mágico, 10.0.2.2. Através deste endereço, o emulador Android saberá que deve acessar o localhost da sua máquina, independente da configuração da sua rede e mesmo que você estiver desconectado.

Tente você mesmo. Com seu servidor web iniciado, acesse o endereço através do browser do emulador Android.

Saudações!

Tutorial de Instalação e Configuração do Doctrine 2.2

Olá! Esta é a primeira vez que arrumo tempo para testar a versão 2 deste famoso ORM para PHP, o Doctrine. Criei este tutorial para servir como referência futura e também para eventualmente auxiliar alguém que esteja estudando. Vale lembrar que você precisa ter o PHP 5.3.0 ou superior instalado na máquina devido aos namespaces utilizados no Doctrine 2.

 

Download e Instalação

Baixe a última versão (no momento em que escrevo é a 2.2): Crie uma pasta no seu servidor e extraia o conteúdo do arquivo recém baixado para dentro dela. Sua estrutura deverá ficar mais ou menos assim:

sua_pasta
|-- bin
|-- Doctrine
|-- entities

Logo após, crie na raiz um arquivo chamado "bootstrap.php". Este arquivo irá conter a configuração básica do Doctrine 2, bem como fornecerá uma instância do Entity Manager. Opa, Entity Manager? É meu amigo, dessa vez a semelhança com o Hibernate está maior ainda. As entidades tem até anotações! Claro que você pode definir as entidades com XML (argh) e YAML. Mas pelo menos pra mim, nada como definir como classes PHP! Crie também um banco de dados para testar o Doctrine 2.

 
// bootstrap.php 

use DoctrineORMToolsSetup; 
require_once "entities/Cidade.php"; 
require_once "entities/Pessoa.php"; 

require_once "Doctrine/ORM/Tools/Setup.php"; 

Setup::registerAutoloadPEAR(); 

$debug = true; 
$config = Setup::createAnnotationMetadataConfiguration(array(__DIR__."/entities"), $debug); 

// Configuração de acesso ao banco de dados 
$conn = array( 
    'driver' => 'pdo_mysql', 
    'user' => 'usuario', 
    'password' => 'senha', 
    'dbname' => 'doctrine2_test' 
); 

// Obtendo uma instância do Entity Manager 
$entityManager = DoctrineORMEntityManager::create($conn, $config); 

 

Definindo as entidades

Agora que você já configurou o bootstrap, vamos criar as entidades (classes) que serão usadas para a persistência no banco de dados. Na pasta "entities", criada anteriormente, crie os arquivos "Cidade.php" e "Pessoa.php" com o conteúdo abaixo:

 
// entities/Cidade.php 

use DoctrineCommonCollectionsArrayCollection; 

/** * @Entity @Table(name="cidade") */ 
class Cidade { 
    /** @Id @Column(type="integer") @GeneratedValue */ 
    protected $id; 

    /** @Column(type="string") */ 
    protected $nome; 

    /** @Column(type="string") */ 
    protected $uf; 

    /** * @OneToMany(targetEntity="Pessoa", mappedBy="cidade") * 
    @var Pessoa[] */ 
    protected $habitantesCidade = null; 

    public function __construct() { 
        $this->habitantesCidade = new ArrayCollection(); 
    } 

    public function getId() { 
        return $this->id; 
    } 

    public function getNome() { 
        return $this->nome; 
    } 

    public function setNome($nome) { 
        $this->nome = $nome; 
    } 

    public function getUf() { 
        return $this->uf; 
    } 

    public function setUf($uf) { 
        $this->uf = $uf; 
    } 

    public function adicionarHabitante($pessoa) { 
        $this->habitantesCidade[] = $pessoa; 
    } 
}

 


 
// entities/Pessoa.php 

/** * @Entity @Table(name="pessoa") */ 
class Pessoa { 
    /** @Id @Column(type="integer") @GeneratedValue */ 
    protected $id; 

    /** @Column(type="string") */ 
    protected $nome; 

    /** @Column(type="datetime") */ 
    protected $dataHoraCadastro; 

    /** * @ManyToOne(targetEntity="Cidade", inversedBy="habitantesCidade") */ 
    protected $cidade; 

    public function getId() { 
        return $this->id; 
    } 

    public function getNome() { 
        return $this->nome; 
    } 

    public function setNome($nome) { 
        $this->nome = $nome; 
    } 

    public function getDataHoraCadastro() { 
        return $this->dataHoraCadastro; 
    } 

    public function setDataHoraCadastro(DateTime $dataHoraCadastro) { 
        $this->dataHoraCadastro = $dataHoraCadastro; 
    } 

    public function getCidade() { 
        return $this->cidade; 
    } 

    public function setCidade($cidade) { 
        $this->cidade = $cidade; 
    } 
}

 

Criação das tabelas

A criação das tabelas no banco de dados será feita através da linha de comando. Caso não queira usar a linha de comando, o arquivo com os comandos SQL se encontra para download no final do post, juntamente com o projeto completo.

 

Utilizando a linha de comando

Se você deseja usar a linha de comando do Doctrine 2, faça uma pequena alteração no arquivo bin/doctrine, adicionando a seguinte linha antes do include:

 set_include_path(get_include_path() . PATH_SEPARATOR . '../'); 

Crie na raiz um arquivo chamado config-cli.php, que irá conter a configuração para rodar o Doctrine Tool através do terminal do Linux (ou prompt do Windows).

 
// config-cli.php 

require_once "bootstrap.php"; 

$helperSet = new SymfonyComponentConsoleHelperHelperSet(array( 'em' => new DoctrineORMToolsConsoleHelperEntityManagerHelper($entityManager) )); 

Agora você já pode acessar a pasta "bin" através do terminal e gerar o SQL necessário para criar as tabelas usadas no exemplo. Para isto, basta entrar na pasta "bin" e rodar o comando:

fonini@valhalla:$ ./doctrine orm:schema-tool:create --dump-sql

Ou se preferir, você pode deixar o Doctrine conectar ao banco de dados e criar as tabelas para você. Para isto, basta remover o trecho "–dump-sql" do comando. Criado o banco de dados, vamos testar a persistência de uma entidade (vulgo insert). Crie um arquivo com o nome de sua preferência na raíz, com o seguinte conteúdo:

 
require "bootstrap.php"; 

$cidade = new Cidade(); 
$cidade->setNome('Marau'); 
$cidade->setUf('RS'); 

$entityManager->persist($cidade); 
$entityManager->flush(); 

echo "Cidade criada com o ID ".$cidade->getId()."n"; 

Rode o arquivo. Legal, não? Se não houve nenhum erro, dê uma olhada no banco de dados, que o seu registro estará lá. Caso houve algum erro, debugue até a morte para encontrar o maldito e deixar funcionando. Veja agora um exemplo de persistência de um objeto da classe Pessoa com um objeto da classe Cidade associado:

 
require "bootstrap.php"; 

$cidade = new Cidade(); 
$cidade->setNome('Marau'); 
$cidade->setUf('RS'); 

$pessoa = new Pessoa(); 
$pessoa->setNome('Jonnas Fonini'); 
$pessoa->setDataHoraCadastro(new DateTime("now")); 
$pessoa->setCidade($cidade); 

$entityManager->persist($cidade); 
$entityManager->persist($pessoa); 
$entityManager->flush(); 

echo "Pessoa criada com o ID ".$pessoa->getId()." e associada com a Cidade ".$cidade->getId(); 

 

Localizando uma entidade pelo ID

 
require "bootstrap.php"; 

$pessoa = $entityManager->find("Pessoa", 1); 
print 'Nome: ' . $pessoa->getNome() . ' '; 
print 'Cidade: ' . $pessoa->getCidade()->getNome(); 

Outros exemplos, como listagem, atualização e exclusão você encontra no arquivo disponível no final do post.

 

Conclusão

Apesar de ser a primeira vez que uso o Doctrine 2, posso dizer que está demais! Está bem mais organizado que a primeira versão, sem contar que as anotações facilitam muito o mapeamento do banco. Pra quem não gosta, pode usar XML e YAML. O bootstrap também está mais limpo e exige bem menos configuração.

 

Download

Baixe aqui os arquivos usados no exemplo. Grande abraço a todos e até a próxima.

“Doritos” na URL de logout do Google

Há algum tempo atrás pensei estar vendo coisas. Uma dessas coisas me pareceu ser a palavra “doritos” na URL de logout do Google. Mas o logout acontece tão rápido que nunca consegui tirar um print pra confirmar. E outra, não é sempre que aparece. Hoje pela manhã consegui! Veja na imagem abaixo:

FINALMENTE CAPTUREI O PRINT!

Repito: não é sempre que aparece.

Segundo o Bruno Bemfica (@ubuntroll), é  porque o Google não gosta de cookies e prefere usar Doritos em suas páginas.

Abraço e bom final de ano!

HTTPRequest, classe PHP para retornar conteúdo remoto em servidores sem cURL

Ataquei de freelancer recentemente, tendo que desenvolver um site. O cliente já havia contratado um popular provedor de acesso à internet da região para hospedar o site. Nada além do apocalipse poderia acontecer. Vou explicar. Os provedores da região na qual resido deveriam se preocupar um pouco mais em oferecer acesso de qualidade e deixar o ramo de hospedagem de aplicações web para quem realmente entende. O maldito servidor estava simplesmente “pelado”, extensões importantes faltando e metade dos recursos úteis desabilitados.

Aonde já se viu um servidor sem cURL? Pois é, ainda fiz uma última tentativa para obter conteúdo remoto (previsão do tempo, infelizmente ainda é uma triste realidade por aqui o cliente exigir isso no site) usando file_get_contents(), mas adivinhem: allow_url_fopen desabilitado.

Felizmente existem os sockets! Dei uma fuçada na net, juntei alguns snippets e criei uma classe para facilitar o serviço. Podem conferir o código e outras informações no meu Github.

Grande abraço!