jun 30 2010

Use controle de versões, sempre!

Quando trabalhamos em um projeto grande e principalmente em conjunto com outros desenvolvedores, aquele simples backup que fazíamos, copiando a pasta manualmente, deixa de ser uma opção válida; já é chato manter vários backups de um projeto que está constantemente mudando, sem contar com o fato de que várias pessoas podem editar o mesmo arquivo ao mesmo tempo.

Qual a solução?

Controle de Versões!

Um sistema de controle de versões é um software usado para gerenciar diferentes versões do seu código, ou seja, todas as alterações de um projeto são sempre armazenadas e são identificadas através de revisões. A cada mudança que salvamos é criada uma nova revisão do projeto, permitindo assim que possamos reverter qualquer mudança danosa sem muito trabalho!

E tem mais!

Ao usar um sistema de controle de versões podemos:

» Criar snapshots (imagens) estáveis do projeto para distribuição, enquanto continuamos o desenvolvimento separadamente.

» Gerenciar conflitos (quando o mesmo arquivo é editado simultaneamente por pessoas diferentes) de uma maneira simples, sem dores de cabeça

» Criar um patch (correção específica em uma parte do código) e distribuí-la sem que seja necessário reinstalar a aplicação.

E não para por aí…!

Sistemas de Controle de Versões

Atualmente existem várias alternativas para controlar as versões do seu projeto, cada uma com suas vantagens e desvantagens. As mais comuns são:

Subversion (SVN)
Git
Mercurial
Bazaar
e, claro
CVS

De todos os softwares mencionados acima, o mais utilizado ainda é o SVN (subversion) e no meu próximo post irei demonstrar como criar um repositório SVN e trabalhar com ele.

Resumindo, independente do tamanho do projeto, e de qual software decidir usar, utilize sempre algum sistema de controle de versões para facilitar o seu trabalho e evitar imprevistos.

Leia mais sobre o assunto!

[]s


jun 23 2010

Evite SQL Injection usando Prepared Statements

Uma das maiores vulnerabilidades de sites, a injeção de SQL (SQL Injection) é também, no caso do PHP, uma das mais fáceis de prevenir. Infelizmente, muitos não tomam as devidas precauções e acabam tendo os seus dados comprometidos.

Neste tutorial, irei demonstrar como trabalhar com prepared statements usando a extensão PDO do PHP.

SQL Injection

Antes de começar, vale a pena ilustrar como funciona um ataque típico de SQL Injection:

// Temos esta consulta simples aonde os dados $username e $password vem de um formulário preenchido pelo usuário
$query = "SELECT * FROM tabela WHERE username = '$username'";

// Se não houver validação correta um usuário mal-intencionado poderia colocar algum código SQL no lugar do username:
$username = "' OR 1'";

// A consulta ficaria assim:
$query = "SELECT * FROM tabela WHERE username = "'' OR 1";

// Como a expressão 'OR 1' sempre resulta em TRUE, a consulta retornaria os dados de todos os usuários no sistema

Convenhamos, o exemplo acima é bobo, mas serve para mostrar a teoria por trás da técnica de injeção de sql. Se ainda não se convenceu de que é necessário, veja um exemplo mais grave:

// começamos com a mesma consulta
$query = "SELECT * FROM tabela WHERE username = '$username'";

// desta vez, o código inserido é bem mal-intencionado mesmo...
$username = "'; DELETE FROM tabela WHERE 1 OR username = '";

// a consulta final ficaria assim:
$query = "SELECT * FROM tabela WHERE username = ''; DELETE FROM tabela WHERE 1 OR username = ''";

// ou seja, se executada, a consulta excluiria todos os registros da tabela

Validação sozinha não resolve!
Você pode estar questionando se uma boa validação já não resolveria o problema, já que em ambos exemplos validar para aceitar somente letras funcionaria para bloquear ambas tentavas. Bom a resposta é: SIM e NÃO!

Por mais que a validação ajude, mesmo usando expressões regulares complexas, há meios de burlá-la utilizando outros charsets e técnicas maliciosas. Segurança nunca é demais e não custa se prevenir para proteger os seus dados ou os dos seus clientes.

O que são prepared statements?

Nada mais são do que consultas “pré-prontas”… A diferença é que em lugar das variáveis você coloca um placeholder (marcador de lugar) e na hora da consulta informa a ordem das variáveis a serem substituidas.

É mais fácil de explicar com um exemplo!

// a interrogação vai no lugar da variável
$query = "SELECT * FROM tabela WHERE username = ?";

// para fazer com vários parametros é a mesma coisa
$query = "SELECT * FROM tabela WHERE username = ? OR username = ?";

Depois, é só informar o que vai no lugar dos respectivos ‘?’ e a consulta estará protegida! Isto funciona porque ao prepararmos a consulta, avisamos ao MySQL (ou outro RDBMS que suporte prepared statements) como é a consulta e exatamente aonde vão as variáveis. Repare que nem precisamos mais colocar aspas em volta da variável, pois ele já sabe que é uma variável e a trata de acordo.

No PHP, a extensão MySQLi também suporta statements preparados, mas recomendo sempre utilizar o PDO pois ele facilita a migração para outros bancos, além de oferecer uma API concisa entre eles.

Como Funciona com PDO

// vamos partir do pressuposto que temos um objeto PDO instanciado e devidamente configurado e iremos trabalhar com a mesma consulta dos exemplos anteriores
$query = "SELECT * FROM tabela WHERE username = ?";

// o método PDO::prepare() retorna um objeto da classe PDOStatement ou FALSE se ocorreu algum erro (neste caso use $pdo->errorInfo() para descobrir o que deu errado)
$stmt = $pdo->prepare($query);

// agora que temos o statement preparado, precisamos "bindar" a variável
$username = "fulano";

// utilizamos o método PDOStatement::bindValue() que aceita como parâmetros a posição do ? que a variável irá substituir (a primeira é 1) e a própria variável
$stmt->bindValue(1, $username);

// executamos o statement
$ok = $stmt->execute();

// agora podemos pegar os resultados (partimos do pressuposto que não houve erro)
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);

Parece meio chato, ter que escrever tanto código a mais para executar uma simples consulta e se a questão da segurança não for motivo sufiente, que tal este: statements preparados são mais rápidos que consultas normais! Especialmente se a mesma consulta for executada diversas vezes durante um request (mudando ou não as variáveis).

Como o assunto é extenso, incluirei algumas informações adicionais para esclarecer alguns itens, se não precisar de tanto detalhe técnico pode pular ao final!

Informações Complementares

  • Há outro método para fazer “bind” das variáveis: o PDO::bindParam(), a síntaxe é exatamente a mesma mas ele recebe a variável por referência, enquanto PDO::bindValue() recebe por valor.
  • Tanto o bindValue() quanto o bindParam() aceitam um terceiro parâmetro opcional que é o tipo da variável (PDO::PARAM_STR, PDO::PARAM_INT, etc)
  • Se não gostou da sintaxe de colocar varias interrogações e depois substituir as variáveis de acordo com a posição da interrogação, também é possível utilizar placeholders nomeados:
    // em vez da interrogação utilizamos uma palavra prefixada de um ":"
    $query = "SELECT * FROM tabela WHERE username = :usuario OR username = :administrador";
    
    // na hora de fazer bind fica mais claro qual variável vai aonde
    $stmt->bindValue(":usuario", $username);
    $stmt->bindValue(":administrador", "admin");
    
    // este método também facilita fazer binds dentro de loops foreach aonde o placeholder é a chave e a variável é o valor
    foreach($variaveis as $k => $v){
        $stmt->bindValue(":$k", $v);
    }
    

E é isto, chegamos ao final! Espero que o artigo tenha ajudado e lembre-se, pular estes simples passos é o típico barato que sai caro!

[]s


jun 22 2010

Trabalhando com o Web SQL Database do HTML5

O joguinho do Pacman do Google mostrou ao mundo que o HTML5 já é uma realidade mas uma das funcionalidades mais legais ainda não foi muito divulgada, é o “Web SQL Database“.

O que é?

O Web SQL Database permite criar e acessar bancos de dados no lado do cliente (client-side) usando uma linguagem SQL.

Ou seja…

É uma alternativa a Cookies para armazenamento de dados no navegador e, mais legal ainda, dá uma independência maior as aplicações javascript, que em tese não dependerão mais de linguagens no lado do servidor (PHP, .NET, etc) para armazenar algo em um banco de dados.

O que não é

Isto tudo é muito legal, mas… é importante frisar algumas coisas:

  • Esta tecnologia não conecta a bancos de dados em servidores externos
  • O método é um pouco “caro” em termos de performance e somente deve ser usado se não houver outras alternativas
  • O navegador do usuário precisa suportar HTML5
  • Como a especificação e respectivas implementações do HTML5 ainda não estão 100% prontas, estes exemplos são mais provas de conceito do que qualquer outra coisa, a API poderá mudar na versão final

Tendo dito isto, vamos dar uma olhada mais a fundo e ver como funciona!  Se ainda não tiver o Google Chrome instalado, baixe ele agora pois é o browser que melhor suporta o Web SQL Database.

Como parto do pressuposto que estamos usando o Chrome, vou usar console.log() para as demonstrações, então abra o console do chrome (clique com o botão direito, em inspecionar elemento e na aba “Console”). Todo o código vai dentro de um tag <script> normal.

Como instanciar o objeto database

// o método OpenDatabase precisa de 4 parametros; o nome do banco de dados, a versão, a descrição e o tamanho estimado (em bytes)
var db = openDatabase("Teste", "1.0", "Teste Web SQL Database", 200000);

// deverá mostrar "Database"
console.log(db);

// de qualquer forma, sempre teste que o objeto foi instanciado direito antes de usá-lo
if(!db){
    alert('deu pau!');
}

O conceito de versões é um pouco enganoso, pois não é possível existirem múltiplas versões do mesmo banco ao mesmo tempo; ele é apenas para facilitar migrações entre versões de bancos.

Executando uma consulta

Para fazer consultas, utilizamos o método transaction do objeto database e, dentro dele, o método executeSql do objeto SQLTransaction:

// o método transaction aceita uma função anônima que recebe um objeto SQLTransaction como parâmetro
db.transaction(function(transaction){
    transaction.executeSql("SELECT COUNT(*) FROM Teste", null, null, null);
});

// os parametros são, respectivamente: a consulta, as variáveis a serem "bindadas", callback de sucesso e callback de erro, ou seja:

db.transaction(function(transaction){
    transaction.executeSql(
        // a consulta
        "SELECT COUNT(*) FROM Teste",
        // variáveis para bind, como é um SELECT, passamos um array vazio
        [],
        // callback de sucesso, uma função anônima que recebe um objeto SQLTransaction e um SQLResultSet
        function(transaction, result){
            console.log('deu certo!');
            console.log(result);
        },
        // callback de erro, função anônima que recebe um objeto SQLTransaction e um SQLError
        function(transaction, error){
            console.log('deu pau!');
            console.log(error);
        }
    );
});

Se rodar o código acima, verá que a consulta dará um erro e retornará um objeto SQLError, para acessar a mensagem de erro é só acessar as propriedades “code” e “message” do objeto.

Dê uma olhada na mensagem de erro… pois é não criamos a tabela!

Como criar e popular uma tabela

O SQL não é nenhuma novidade, só é necessário envolvê-lo nos métodos corretos:
(alias, ele utiliza statements preparados, para proteção contra SQL Injection, mas isto está fora do escopo deste artigo!)

db.transaction(function(transaction){
    // criar a tabela
    transaction.executeSql("CREATE TABLE Teste (id REAL UNIQUE, nome TEXT, timestamp REAL)", [], null, null);

    // num caso de verdade, iríamos incluir callbacks para verificar que deu tudo certo mas para não estender demais o código vou pular esta parte...

    // inserir dados
    // obs - repare que usamos um "statement preparado", colocamos interrogações no lugar das variáveis e as listamos em um array no segundo parametro, fazendo bind delas
    transaction.executeSql("INSERT INTO Teste (nome, timestamp) values(?, ?)", ['Alex', new Date().getTime()], null, null);
});

Pronto! Fácil né? Agora tente rodar a primeira consulta denovo… não deu erro né? Se deu tudo certo, o objeto retornado será do tipo SQLResultSet. Se inspecionar o objeto verá que ele tem algumas propriedades úteis: insertId (no caso de inserts), rowsAffected, rows (no caso de selects).

Utilizando os resultados

Para finalizar o artigo, vou mostrar como interagir com os resultados. Para isto, vamos mudar um pouco a consulta inicial:

db.transaction(function(transaction){
    transaction.executeSql(
        "SELECT * FROM Teste",
        [],
        function(transaction, result){
            console.log('deu certo!');
            console.log(result);

           for(var i = 0; i < result.rows.length; i++){
               console.log(result.rows.item(i)['nome']);
           }
        },
        function(transaction, error){
            console.log('deu pau!');
            console.log(error);
        }
    );
});

Repare que podemos tratar o objeto SQLResultSet como um array e não só ver a propriedade length() mas também fazer um loop e acessar o seu conteúdo!

Legal né?

Espero que tenham curtido o artigo e que se animem com as possibilidades que o HTML5 está trazendo!

[]s


jun 21 2010

Usando easing para animações com jQuery

Eu já havia mencionado o Easing em outro artigo, e me perguntaram estes dias como se usa o plugin para controlar melhor animações, então resolvi escrever um artigo rápidinho para esclarecer e mostrar o poder do easing.

Preparação

Se já não o tiver feito, vá para o site e baixe o plugin.  Vamos utilizar uma página bem simples em HTML:

<html>
<head>
<title></title>
<style type="text/css">
#target {
	background-color: red;
	width: 200px;
	height: 200px;
	position: relative;
}
</style>
<script src="http://www.google.com/jsapi"></script>
<script type="text/javascript">google.load("jquery", "1.4.2");</script>
<script type="text/javascript" src="jquery.easing.1.3.js"></script>
<script type="text/javascript">
    // nosso código irá aqui
</script>
</head>
<body>

<div id="target"></div>

</body>
</html>

Até aqui sem novidades, agora vamos fazer uma animação simples:

jQuery(document).ready(function($){
    $('#target').click(function(){
        $(this).animate(
            { left : 100 },
            1000
        );
    });
});

Beleza, quando clicamos no div anima a sua propriedade left até 100 em um intervalo de 1000ms.

E agora, para dar uma variada, vamos usar um pouco de easing!

jQuery(document).ready(function($){
    $('#target').click(function(){
        $(this).animate(
            { left : 100 },
            1000,
            'easeInBounce' // adicionamos um efeito easing
        );
    });
});

Legalzinho né? Bom, é isso ae, não tem segredo! Para o easing por sí só não é tão útil assim, mas pode ser combinado com vários outros plugins por exemplo o Cycle para refinar o controle sobre as animações.

O site do plugin possui alguns exemplos mas é meio confuso, recomendo dar uma olhada aqui para ver exatamente o que faz cada efeito disponível no plugin.

Até mais!

[]s


jun 20 2010

Testando as suas classes com PHPUnit

Artigo originalmente escrito para o PHPBrasil, apenas o trouxe para cá!

O que é Unit Testing?

  • Testes para pequenos trechos de código (unidades)
  • Verifica se o comportamento de classes e funções é o esperado
  • Caso erros são encontrados exceções são lançadas
  • Não interfere com o seu código-fonte

Qual a vantagem?

  • Os testes são automatizados
  • São executados continuamente durante o ciclo de desenvolvimento
  • Detectam falhas tanto de digitação e lógica e também comportamentos inesperados
  • Escalam conforme o desenvolvimento

Exemplo

require_once('Classe1.php');
// Teste da classe

$foo = new Classe1();

$soma = $foo->somar(2, 2);
$subracao = $foo->subtrair(2, 2);

echo '2 mais 2 = ' . $soma;
echo '2 menos 2 = ' . $subtracao;

// Funciona conforme esperado!

Apesar do exemplo simples, ilutra uma prática bem comum: a de inserir vários echo() e print() para confirmar o funcionamento de uma classe ou função.

O PHPUnit é uma framework que tem como objetivo automatizar e padronizar a forma como nosso código é testado.

“Whenever you are tempted to type something into a print statement or a debugger expression, write it as a test instead.” — Martin Fowler

Ou seja: “Toda vez que sentir vontade de escrever um print ou outra expressão de debug, pare e crie um teste!”

Testando a mesma classe do exemplo anterior com o PHPUnit

// Especifique o caminho do PHPUnit
require_once '/usr/share/php/PHPUnit/Framework.php';
// Especifique o caminho da classe a ser testada
require_once 'Classe1.php';

// Como a classe a ser testada se chama "Classe1", a classe de teste deverá se chamar "ClasseTest" e (neste caso) irá herdar de PHPUnit_Framework_TestCase
class Classe1Test extends PHPUnit_Framework_TestCase
{
        // Funções de teste devem ter o prefixo "test"
        public function testSoma()
        {
                // A classe a ser testada é instanciada
                $foo = new Classe1();
                // Testamos a afirmação que "4" é o resultado de passar "2" e "2" (ou seja, 2 + 2 = 4)
                $this->assertEquals('4', $foo->somar(2, 2));
        }

        public function testSubtracao()
        {
                // idem (veja função acima)
                $foo = new Classe1();
                $this->assertEquals('0', $foo->subtrair(2, 2));
        }
}

O resultado:

PHPUnit 3.3.16 by Sebastian Bergmann.

.

Time: 0 seconds

OK (2 tests, 2 assertions)

// Funciona conforme esperado!

O que aconteceu?
Criamos uma classe (Classe1Test) de teste para testar a nossa classe (Classe1) e usamos o PHPUnit para testar o funcionamento esperado

Não é mais complicado?
Sim e não! Inicialmente pode parecer bem mais simples inserir alguns print() ou echo() e verificar manaulmente, mas ao longo prazo usar o PHPUnit traz diversas vantagens:

  • Os testes ficam separados do código, assim não corremos o risco de esqueçer testes no meio do código. Devido à separação também não é necessário ficar voltando e comentando e descomentando as linhas de teste inseridas manualmente.
  • Para aplicações um pouco mais complexas (por exemplo com várias classes interagindo juntas ou com AJAX) as vezes não é possível colocar echo() ou print() em qualquer lugar. Até mesmo o FirePHP gera erros de ‘header’!
  • Usando o PHPUnit criamos vários testes e sempre que desejarmos podemos rodá-los novamente para testar modificações.
  • E o melhor de tudo, não precisamos fazer nada na hora de colocar a aplicação no ar. Simplesmente não fazemos o upload da pasta de testes! O código-fonte original segue intacto.

Como funciona?

  1. Crie uma classe de teste para testar uma classe já existente
  2. Execute os testes no terminal (ou prompt de comando) e veja os resultados
  3. A melhor maneira da aprender isto é através de exemplos então vamos instalar o PHPUnit e criar alguns testes!

Instalação do PHPUnit
Quem usa o linux pode fazer facilmente:

# se não tiver o PEAR instalado
sudo apt-get install pear

# descubra o canal do PHPUnit
sudo pear channel-discover pear.phpunit.de

# instale o phpunit
sudo pear install phpunit/PHPUnit

# Ele fica instalado por padrão no /usr/share/php/PHPUnit
# Agora é só incluir o framework nos arquivos de teste e começar!

Quem usa windows procure no google! Não deve ser muito complicado… (se não me engano ele já vem incluso no pacote XAMPP)

Guia para criar Unit Tests

  • Os testes para a classe “Classe1″ (Classe1.php) deverão ser localizados dentro da classe “Classe1Test” (Classe1Test.php), sempre use o sufixo “Test” (NomeDaClasseTest)
  • Na maioria dos casos a classe de teste irá herdar (extends) da classe PHPUnit_Framework_TestCase
  • Os testes deverão ser funções públicas com o prefixo “test” (testSomar, testSubtrair, etc)
  • Os testes são baseados em afirmações, ou seja: afirmamos que o resultado esperado da função X é Y, e testamos a afirmação pra ver se ela procede.
  • Usamos funções como assertEquals() para testar afirmações (exemplos a seguir)

Algumas Afirmações disponíveis (Funções de Teste)
Existem dezenas (veja a documentação), seguem algumas das mais comuns:

  • assertEquals($valor, funcao()) (afirma que o valor retornado da funcao é igual a $valor)
  • assertNotEquals($valor, funcao()) (afirma que o valor retornado da funcao não é igual a $valor)
  • assertSame($valor, funcao()) (testa se o objeto retornado é igual a $valor)
  • assertTrue(funcao()) (afirma que o valor retornado é === true)
  • assertFalse(funcao()) (=== false)
  • setExpectedException (avisa sobre uma exceção que deverá ser lançada)

Como rodar os testes
Através do terminal (ou prompt de comando), no diretório do arquivo de teste digite:

# para rodar os testes contidos no arquivo NomeDaClasseTest.php
phpunit NomeDaClasseTest

# também é possível rodar o PHPUnit nos conteudos de uma pasta inteira
phpunit NomeDaPasta/

Exemplos

O teste seguinte usa a função assertEquals() para checar o retorno de um método:

// Especifique o caminho do PHPUnit
require_once '/usr/share/php/PHPUnit/Framework.php';
// Especifique o caminho da classe a ser testada
require_once 'Classe2.php';

class Classe2Test extends PHPUnit_Framework_TestCase
{
    public function testCumprimentarSemParametro()
    {
        // O comportamento esperado é que retorne "Olá fulano", testa esta afirmação
        $this->assertEquals('Olá fulano', $foo->cumprimentar());
    }

    public function testCumprimentarComParametro()
    {
        // Instancia a classe e passa "Alex" ao construtor
        $foo = new Classe2('Alex');
        // O comportamento esperado é que retorne "Olá Alex", testa esta afirmação
        $this->assertEquals('Olá Alex', $foo->cumprimentar());
    }

        // Funções de teste também podem ser identificados pela anotação @test no DocBlock
        /**
         * @test
         */
         public function vaiDarErrado()
         {
                 // Instancia a classe e passa "ciclano" ao construtor
                $foo = new Classe2('ciclano');
                // O comportamento esperado é que retorne "Olá ciclano", mas vamos afirmar que retornará outro valor para forçar um erro
                $this->assertEquals('Olá Alex', $foo->cumprimentar());
         }
}

O teste retorna o seguinte:

PHPUnit 3.3.16 by Sebastian Bergmann.

..F

Time: 0 seconds

There was 1 failure:

1) vaiDarErrado(Classe2Test)
Failed asserting that two strings are equal.
expected string <Olá Alex>
difference      <     xxxx???>
got string      <Olá ciclano>
/caminho/para/o/arquivo/Classe2Test.php:35

FAILURES!
Tests: 3, Assertions: 3, Failures: 1.

Ou seja, quando um teste falha ele informa o arquivo e linha onde ocorreu o erro e explica também qual foi o erro:

O valor esperado era “Ola Alex” e o valor retornado foi “Ola ciclano”.

Fornecendo dados para os testes
As vezes não basta só um teste com um valor estático, neste caso podemos criar uma função para alimentar o teste usando vários valores (e nada impede que sejam de fontes externas como um banco de dados ou arquivo xml!). A função é identificada através da anotação @dataProvider no DocBlock.

// Demonstração de "Data Providers"
class Classe3Test extends PHPUnit_Framework_TestCase
{
    // Informa o nome do forneçedor de dados (@dataProvider) para a clase de teste
    /**
     * @dataProvider provider
     */

    // Recebe 3 parâmetros
    public function testCombine($a, $b, $c)
    {
        // Afirma que o valor do terceiro parâmetro é igual a concatenação dos primeiros dois separados por um espaço
        $this->assertEquals($c, $a . ' ' . $b);
    }

    // A função fornecedora de valores
    public function provider()
    {
        // retorna um array contendo 3 grupos de valores a serem testados
        return array(
            array('Hello', 'World', 'Hello World'),
            array('É', 'Nois', 'É Nois'),
            array('Deu', 'Errado', 'Deu Certo')
        );
    }
}

Resumindo

O assunto é bastante extenso e realmente fica difícil cobrir todas as possibilidades (que são quase infinitas), mas é possível criar testes para testar se Exceções são lançadas conforme esperado, para testar classes de acesso ao banco de dados e muito mais!

O ideal seria implementar isto em uma aplicação que esteja desenvolvendo, ou seja, crie uma pasta para os testes e vá criando testes para as suas classes nela.

Todo o código-fonte para os exemplos e outros exemplos mais complexos (todos bem documentados) estão disponíveis no link.

[]s


jun 18 2010

Executando Javascript Automaticamente

Muitas vezes precisamos executar algum javascript assim que a página terminar de carregar e fazer isto não é segredo:

<body onload="minhaFuncao();">

Este método funciona perfeitamente mas ele polui o DOM e é contra boas práticas escrever javascript inline, logo o ideal seria encontrar outro método…

Quem usa bastante jQuery sabe que dá pra fazer a mesma coisa assim:

jQuery(window).load(function($){
    // código
});

Mas e se precisar fazer isto sem o jQuery???

A solução é um truquezinho legal:

(function(){
    // código
})();

Se você colocar este código dentro de tags <script> normais ele será executado assim que o documento for carregado!

OBS: Também é possível fazer do modo tradicional (e bem menos estiloso), bindando o evento ao “onload” do window:

window.onload = function(){
   // código
};

jun 18 2010

Como instalar DBDesigner no Ubuntu

Quem já conhece, sabe o quanto o DBDesigner é útil para modelar bancos de dados e criar MERs (Modelo Entidade-Relacionamento), e quem não conhece, trate de conhecer!

O problema é que ele não tem instalador próprio para o Debian/Ubuntu e surgem alguns problemas de dependências ao tentar instalá-lo manualmente.  Pesquisei por aí e não achei nenhum guia 100% então resolvi compartilhar como consegui.

  1. Baixa o instalador RPM aqui
  2. Instale o Alien:
    sudo apt-get install alien
  3. Use o alien para converter o RPM em DEB:
    sudo alien DBDesigner4-0.5.4-0.i586.rpm
  4. Instale o DEB normalmente:
    sudo dpkg -i dbdesigner4_0.5.4-1_i386.deb
  5. O DBDesigner será instalado na pasta /opt/DBDesigner/ mas ao tentar executá-lo ele reclama de uma dependência que está faltando, então faça download dela aqui
  6. Copie a biblioteca para a pasta /lib/
    tar xzvf kylixlibs3-borqt-3.0-2.tar.gz && sudo cp kylixlibs3-borqt/libborqt-6.9.0-qt2.3.so /lib/libborqt-6.9-qt2.3.so
  7. Pronto! Agora é só criar um atalho para /opt/DBDesigner4/DBDesigner4 e mandar bala!

A fonte inicial do programa é grande demais então entre nas opções e mude para algum tamanho que fique legal.

Espero que tenha ajudado e boa sorte!


jun 14 2010

jQuery Scratchie

Litebox

EnglishPortuguês

jQuery Scratchie é um plugin completo para criar “raspadinhas”.

Defina uma imagem de fundo (o prêmio) e uma imagem ou cor para cobrir e clique ou arraste o mouse por cima para revelar a imagem debaixo!

Atualizado: 02/06/2010

Demo | Project @ GitHub | Download Link


mar 2 2010

MySQL Como exportar e importar backups pelo terminal

Ultimamente tenho trabalhando bastante com o MySQL em vários PCs diferentes e sempre tem aquele problema chato de ter que manter o banco de dados atual em todos eles, depois de cada mudança.

No início fazia tudo pelo phpMyAdmin mas depois aprendi alguns atalhos no terminal do linux que facilitam bastante a vida:

#Para os exemplos: usuário "alex" e senha "alex123"

#Exportar o banco normalmente
mysqldump -ualex -palex123 nomedobanco > nomedobanco.sql

#Exportar o banco com bzip2
mysqldump -ualex -palex123 nomedobanco | bzip2 > nomedobanco.sql.bz2

#Importar o banco normalmente (.sql)
mysql -ualex -palex123 nomedobanco < nomedobanco.sql

#Importar o banco com bzip2
bunzip2 < nomedobanco.sql.bz2 | mysql -ualex -palex123 nomedobanco

#Exportar apenas rotinas
mysqldump --routines -ualex -palex123 --no-create-info --no-data --no-create-db --skip-opt nomedobanco > nomedobanco-routines.sql

Demorei um pouco pra me acostumar mas é bem mais prático do que ter que fazer de qualquer outra forma!


mar 2 2010

Javascript Orientado a Objetos?

Como assim?  Você quer dizer usando jQuery não é?

Não!

Cada vez que aprofundo os meus conhecimentos de Javascript me vem à cabeça o artigo do lendário Douglas Crockford, aonde ele o qualifica qualifica como  “a linguagem de programação mais incompreendida do mundo”.

E convenhamos, não é a toa!  Como o pessoal do jQuery e outras bibliotecas já descobriu, o javascript pode fazer muito mais do que validar formulários e dar alerts e confirms… O surgimento destas bibliotecas foi uma faca de dois gumes pois apesar de ser enormemente responsável pelo ressurgimento da linguagem e por torná-la popular, também fez com que poucas pessoas de fato saibam usá-lo sem o auxílio de uma biblioteca… e eu me incluo neste grupo!

Recentemente decidi tentar criar algo em js puro e gostaria de compartilhar algumas coisas.

Objetos no Javascript

Quem já trabalhou com JSON com certeza já conhece o tal do “Object Literal”:

{
    nome : 'Alex',
    idade : 26
}

Pois aí está a forma mais simples de um objeto Javascript, o tal do literal! Veja outro exemplo: (e desculpem a falta de criatividade…)

function carro(params){
    this.velocidadeAtual = 0;
    var velocidadeMax = 100;

    this.acelerar = function(){
        if(this.velocidadeAtual < velocidadeMax){
            this.velocidadeAtual += 10;
            alert('vroom');
        }
    }
}

var car = new carro();
alert(car.velocidadeAtual);
car.acelerar();

O objeto pode ser instanciado e os seus métodos e propriedades podem ser acessados pela instância... legal não é? E aí, está se perguntando porque usei var para declarar uma variável e this pra declarar a outra?

Escopo de Métodos e Propriedades
obs - eu uso os termos métodos e funções intercaladamente, assim como propriedades e atributos... :)

Quando se está trabalhando com objetos no javascript, apesar de não existir palavras-chave delimitadoras de escopo como public ou private, é possível obter o mesmo resultado usando this e var, respectivamente.

Tal como o PHP e outras linguagens orientadas a objetos, o this se refere à instância do objeto, até aí sem novidades... Já o var tem a sua visibilidade delimitada ao escopo atual, ou seja, se for declarada dentro da função não será visível fora dela. Neste caso, o efeito resultante é o de uma variável privada.

E finalmente...

Herança

Antes de mais nada, não dá pra frisar o suficiente que o javascript não possui um sistema de "herança clássica". Na verdade nem possui classes e os seus objetos são "prototipados", ou seja: são definidos na hora para atender a uma necessidade. Existem várias formas de obter o efeito de herança entre objetos e isto é até hoje um tema para o qual não há uma só solução. Veja um exemplo simples:

function ClassePai() {
    this.teste = function(){
        alert('teste da classe pai');
    }
}

function ClasseFilho() {

}

// agora a parte legal, vamos herdar os métodos da classe pai
ClasseFilho.prototype = new ClassePai();

// testando
var filhote = new ClasseFilho();
filhote.teste();

Em conclusão: O javascript é uma linguagem bastante subestimada e poderosa, que pode ser usada para agregar bastante valor e transformar completamente a experiência do usuário no seu site. E claro, use o jQuery, YUI, MooTools, etc... só não se esqueça como programar em javascript! :)

Leia mais
http://ejohn.org/blog/simple-javascript-inheritance/
http://javascript.crockford.com/prototypal.html
http://www.sitepoint.com/blogs/2006/01/17/javascript-inheritance/
http://ajaxpatterns.org/Javascript_Inheritance
http://www.kevlindev.com/tutorials/javascript/inheritance/index.htm