sexta-feira, 17 de dezembro de 2010

Tutorial: MySQL no Autoit utilizando conector ODBC e UDF MySQL

Entre as UDF´s disponíveis para o Autoit, apenas uma nos permite conectar a um banco de dados, que é o SQLite. Felizmente ele disponibiliza meios de trabalharmos com COM Objects, o que torna possível o desenvolvimento de UDF´s para atender soluções específicas.

No Fórum oficial do Autoit temos um caso destes, no post MySQL UDFs o usuário cdkid disponibiliza uma UDF para trabalharmos com bancos de dados MySQL, apesar de ser antiga (última atualização em 2007) e um pouco limitada, ela funciona e entrega um resultado satisfatório.

No tópico é explicado como fazer a conexão e começar a trabalhar, porém, como é um pouco antigo, algumas coisas podem não funcionar (como aconteceu comigo) e pode ser preciso conferir alguns detalhes a mais, não explanados no fórum, por isso vamos a partir de agora, conferir como fazer para conectar o Autoit com o MySQL em detalhes.

Arquivos para conectar o Autoit e o MySQL

Antes de mais nada precisamos baixar a biblioteca (que você encontra no link logo abaixo) e também o driver ODBC, que fará o papel de intermediar a conexão entre as duas tecnologias:

Download 1: mysql.au3
Download 2: Driver ODBC

No link para baixar o driver ODBC, você deve escolher um dos arquivos em formato zip, apenas atente para optar pelo arquivo correto de acordo com a plataforma de seu computador ou servidor (32-bit ou 64-bit), para este exemplo nós baixamos o arquivo Windows (x86, 64-bit), ZIP Archive Connector-ODBC.

Instalando o Driver ODBC

Descompacte o arquivo na máquina em que você irá rodar sua aplicação, abra um prompt do DOS e digite o caminho completo até a pasta onde encontram-se os arquivos descompactados, seguido de /install.bat 0, conforme mostrado na figura abaixo:

Console ODBC Instalação

Após instalado o driver, clique em:

  1. Iniciar "Start"
  2. Ferramentas Administrativas "Administrative Tools"
  3. Fontes de dados(ODBC) "Data Sources(ODBC)"
  4. Clique em Adicionar "Add"
  5. Escolha MySQL ODBC Driver 3.51 e então clique em Finalizar "Finish"

Uma nova janela irá solicitar algumas informações sobre a nova conexão ODBC, preencha com os dados (alguns são opcionais) do banco que você deseja se conectar e por fim clique no botão Test. Se ele retornar uma mensagem positiva sua conexão já esta funcionando, caso contrário precisaremos trabalhar um pouco mais.

ODBC MySQL x Autoit configuração

Janela de configuração do ODBC

O teste deu ok! | O teste falhou, e agora?

Configurando o servidor MySQL para aceitar conexões externas

Se sua conexão ODBC não deu certo, pode ser que você precisa garantir o acesso da sua máquina de aplicação para o servidor do banco. Para fazer isso você vai ter que executar uma query no seu servidor MySQL atribuindo este acesso. Abaixo um exemplo:

GRANT ALL PRIVILEGIES ON database.table TO 'usuario'@'host' IDENTIFIED BY 'password'

Na query mostrada acima, nós temos algumas palavras destacadas em itálico, são elas que você deverá alterar, veja um exemplo de como deverá ficar no final:

GRANT ALL PRIVILEGIES ON *.* TO 'root'@'172.167.100.90' IDENTIFIED BY 'root@123'

Neste exemplo, foi definido acesso total para todos os bancos e todas as tabelas de nosso servidor MySQL, para o usuário root vindo do servidor 172.167.100.90 utilizando a senha root@123.

Você pode aplicar esta query via o prompt do mysql, no seu servidor de banco de dados ou por meio de um aplicativo terceiro, como o MySQL Administration ou PHPMyAdmin, caso tenha instalado. Fazendo isso, volte para a máquina onde você instalou o ODBC e teste novamente a conexão. Caso as falhas ainda persistam, tente recomeçar o tutorial desde o início novamente.

Criando uma aplicação Autoit/MySQL

Agora que você já garantiu a conexão basta você começar a desenvolver seu aplicativo, basta incluir a UDF do MySQL no início da seu script. Como um primeiro teste você pode apenas ler alguns registros de uma tabela qualquer e mostrar em tela, para fazer isso siga o exemplo abaixo, apenas adaptando para um banco e tabela existente no seu servidor de banco de dados:

;Conectar em uma base
$o_sql = _MySQLConnect('root', 'root@123', 'ambiente', '172.167.100.90')

;Realiza uma query
$o_query = _Query('SELECT hostname FROM servidores')

With $o_query

While NOT .EOF

;Mostra os resultados em tela
MsgBox(0, 'Hostnames', .Fields('hostname').value)

WEnd

EndWith

;Tenta encerrar a conexão com o banco
_MySQLEnd($o_sql)

Uma pequena contribuição

Durante o desenvolvimento de aplicações MySQL/Autoit eu tive uma grande necessidade que era conseguir descobrir se uma determinada query SELECT iria retornar algum resultado, pois se você tentar acessar os valores de um atributo retornado de uma query e esta não te retorne nada, você terá um erro de execução. Portanto criei essa pequena função que faz o trabalho de contar quantas linhas uma query retornará, tornando seu aplicativo menos suscetível a falhas.

;Conta quantas linhas uma query SELECT irá retornar
Func _CountRows($o_sql, $s_query)

;Customiza a query para retornar um COUNT, ao invés dos campos
$s_res = StringRegExpReplace ($s_query, '(SELECT [\w]{1,255})((, | )[\w]{1,255}(,|)){0,10} FROM', 'SELECT COUNT(*) as ct FROM')

;Se conseguir criar a nova query, testa o resultado
If $s_res <> $s_query Then

$o_query = _Query($o_sql, $s_res)

Return $o_query.Fields('ct').value

Else

Return 0

EndIf

EndFunc

Finalizando

Espero que tenham apreciado o post, dúvidas deixem um comentário que retornarei assim que possível. Para finalziar vou deixar um apelo: Se alguém tiver acesso aos atributos e métodos do MySQL COM Object, por favor compartilhe, seria muito interessante implementar mais algumas funções a esta biblioteca.

Antes de finalizar, não posso deixar de agradecer ao meu amigo Padilha, por insistir em descobrir como conectar o Autoit com MySQL, sem sua ajuda minha vida seria bem mais penosa. Obrigado!

Abraço!

quarta-feira, 15 de dezembro de 2010

Biblioteca de funções CMD (DOS) para Autoit

Em várias ocasiões, precisei criar ferramentas com o Autoit, que de alguma maneira precisavam executar comandos DOS e retornar o resultado para minha aplicação. Como na época não achei nada que fizesse algo semelhante, resolvi escrever minhas próprias funções, o que resultou na biblioteca CMD.au3, que estou disponibilizando logo abaixo para download.

Para os mais curiosos, estas funções não tem nenhum segredo, não utilizam nenhum COM Object ou DLL, são na verdade uma combinação de funções nativas do Autoit que executam um comando DOS e retornam em buffer o resultado do comando. Para finalizar utilizo várias regras de expressões regulares para conseguir a informação de que preciso.

Se alguém conhecer alguma DLL ou COM Object que trabalhe diretamente com linha de comando e que possa fazer um trabalho semelhante ao desta biblioteca, por favor me avise, pois eu gostaria muito de reescrever esta biblioteca com algum destes recursos, apesar de que a versão atual já ajuda e muito no atendimento de minhas necessidades do dia a dia e quem sabe ela possa te ajudar também.

O que vou precisar?

Para utilizar esta biblioteca, você vai precisar fazer o download dos dois arquivos abaixo, o primeiro é a biblioteca em si e o outro arquivo é um biblioteca com TRIM functions, para eliminar espaços em branco dentro de strings. Esta última não é de autoria minha, você pode conferir o tópico no fórum do Autoit que fala sobre ela: New String TRIM() functions

Download 1: Cmd.au3
Download 2: TRIM Functions

Além disso, a nossa biblioteca depende de algumas UDF´s para que possa ser executada, para estas basta dar um include no seu script, pois são nativas do Autoit:

  • Constants
  • Process
  • Array

Funções Cmd

Todo o código esta comentado e os nomes das funções, em sua maioria, são auto explicativos. De qualquer forma vou explicar um pouco sobre cada uma delas, assim fica mais fácil você entender o que poderá ser feito com cada uma e então decidir se elas atendem ou não suas necessidades.

_Cmd_GetBuffer($s_Command, [$b_GetDataFromClip = False])

O que faz?

Executa um comando DOS e retorna em um array, o buffer com o resultado. São retornados dois índices neste array, um deles com o buffer normal e o outro com o buffer de erros (caso houver)

Parâmetros

  • s_Command - O comando DOS que deseja executar
  • b_GetDataFromClip - [Opcional] Caso seja True, vai utilizar a Área de Transferência do Windows para ler o retorno do comando, ao invés do output Stdout que é o padrão. Você deve utilizar a Área de Transferência (ou Clipboard), caso seu aplicativo esteja travando quando utilizado o output padrão, isso pode acontecer por exemplo, em comandos que acabam solicitando algum input do usuário após o envio do comando, neste caso o Stdout fica na espera e não retorna nada para sua aplicação.

_Cmd_BufferTrim($s_Buffered, [$i_ReturnType = 0])

O que faz?

Remove os espaços em branco dentro de uma string e então retorna, ou uma nova string devidamente formatada ou um array com cada linha do buffer.

Parâmetros

  • s_Buffer - A string com o buffer do comando executado
  • i_ReturnType - [Opcional] Pode ser 0 "zero" para retornar a string inteira ou 1 "um" para retornar um array com as linhas da string.

_Cmd_GetSessionId($s_Usuario, [$s_Server = "localhost"])

O que faz?

Retorna um Integer com o ID de sessão de um usuário em um determinado servidor.

Parâmetros

  • s_Usuario - O nome do usuário do qual deseja descobrir o ID de sessão
  • s_Server - [Opcional] O servidor que se encontra o usuário.

_Cmd_GetUsers([$s_Server = "localhost"])

O que faz?

Retorna um array com uma lista de usuários de um servidor.

Parâmetros

  • s_Server - [Opcional] O servidor que deseja recuperar a lista de usuários.

_Cmd_ProcessExists($s_Process, [$i_Session = 0, [$s_User = "", [$s_RemServer = "", [$s_RemUser = "", [$s_RemPass = ""]]]]])

O que faz?

Retorna um boolean caso um processo informado exista em um determinado servidor. Este servidor pode ser um servidor remoto caso sejam passados os devidos parâmetros.

Parâmetros

  • s_Process - O nome do processo que deseja verificar.
  • i_Session - [Opcional] O número da sessão do usuário que deseja verificar, caso esse valor seja omitido, ele verificará a sessão 0, que costuma ser a sessão principal ou console.
  • s_User - [Opcional] Caso informado, a função irá verificar se determinado usuário esta executando o processo informado.
  • s_RemServer - [Opcional] Informa um servidor remoto para verificar a existência do processo.
  • s_RemUser - [Opcional] Caso seja informado um servidor remoto, você deve passar um usuário existente neste servidor para que o comando possa ser executado.
  • s_RemPass - [Opcional] A senha do usuário no servidor remoto.

_Cmd_ProcessClose($s_Process, [$i_Session = 0, [$b_Force = False, [$s_RemServer = "", [$s_RemUser = "", [$s_RemPass = ""]]]]])

O que faz?

Tenta fechar um processo em um determinado servidor e retorna um boolean com o resultado. Este servidor pode ser um servidor remoto caso sejam passados os devidos parâmetros.

Parâmetros

  • s_Process - O nome do processo que deseja fechar.
  • i_Session - [Opcional] O número da sessão do usuário que deseja verificar, caso esse valor seja omitido, ele verificará a sessão 0, que costuma ser a sessão principal ou console.
  • b_Force - [Opcional] Caso seja True, o processo será fechado a força. O padrão é False, onde ele irá aguardar o fechamento normal da aplicação.
  • s_RemServer - [Opcional] Informa um servidor remoto para fechar o processo.
  • s_RemUser - [Opcional] Caso seja informado um servidor remoto, você deve passar um usuário existente neste servidor para que o comando possa ser executado.
  • s_RemPass - [Opcional] A senha do usuário no servidor remoto.

_Cmd_Logoff($s_Session, [$s_Server = "localhost"])

O que faz?

Efetua o logoff de um usuário (da sessão informada) em um determinado servidor.

Parâmetros

  • s_Session - O nome ou ID da sessão que deseja fazer logoff
  • s_Server - [Opcional] O servidor que se encontra o usuário.

Finalizando

É isso, espero que tenham apreciado, dúvidas e sugestões é só comentar. Caso você sinta necessidade de ter exemplos, basta abrir o fonte da biblioteca e analisar as funções, acredito que é de fácil entendimento, senão é só gritar aí ;).

quinta-feira, 9 de dezembro de 2010

Ferramentas para o Autoit

No post anterior Automatizando tarefas com Autoit, eu fiz uma grande propaganda sobre a linguagem e sobre como você pode criar scripts para automatizar tarefas em ambientes Windows, também falei que existiam várias ferramentas para ajudar no desenvolvimento, mas acabei deixando de falar sobre elas ou ao menos citá-las, coisa que farei neste post. :)

SciTE4AutoIt3

Scite é um editor de texto baseado no componente Scintilla, para quem não conhece, este é o mesmo componente utilizado em projetos como o Notepad++, além de muitos outros.
Eu não sei como é escrever uma aplicação Autoit sem o SciTE4AutoIt3, pois eu sempre o utilizei e jamais trabalharia sem ele, considerando as inúmeras facilidades que ele proporciona:
  • Highlight de sintaxe
  • Função auto-completar
  • Função expandir ou recolher código
  • Função Intellisense, que mostra quais parâmetros você precisa passar para uma função.
Além disso, ele traz vários atalhos para outras ferramentas do Autoit: Compilador, Autoit Window Info, Koda Form Designer, Code Wizard entre outras.

Scite4Autoit3
Imagem da área de trabalho do Scite, detalhe na imagem para o menu Tools e os atalhos para acessos a outras ferramentas.

Koda Form Designer

Outra ferramenta interessante, principalmente para quem quiser trabalhar com GUI´s no Autoit, o Koda Form Designer permite a criação de interface gráficas como janelas e formulários de maneira simples e intuitiva: clique e arraste. Basicamente ele faz a mesma coisa que um Delphi faz, mas gerando código Autoit.

Koda Form Designer
O Koda Form Designer permite criar GUI´s inteiras apenas arrastando componentes, depois é só gerar o código, criar a lógica e compilar.


Autoit Window Info

É comum trabalhar-mos com a manipulação de janelas no Autoit, muitas vezes precisamos saber se elas existem, ou precisamos que um click do mouse seja enviado para algum ponto dela, ou que algum conteúdo precise ser digitado em algum campo, enfim precisamos ter as informações corretas para podermos manipulá-las da melhor maneira possível.
A proposta desta ferramenta é trazer essas informações de maneira simples e rápida, para isso basta você posicionar o cursor do mouse sobre uma janela e um pequeno console mostrará todos os dados que o Window Info Tool for capaz de obter. Veja abaixo, algumas informações que podemos encontrar:
  • Título da janela
  • Textos
  • Textos ocultos
  • Coordenadas X e Y de onde ela se encontra
  • Controls, Handlers e classes para manipulação com o Autoit

Autoit Window Info

Atente para as informações que conseguimos obter de uma janela utilizando a ferramenta.

Todas essas ferramentas contribuem em muito com o desenvolvimento de scripts e aplicações com o Autoit, se você desenvolve ou pretende começar a desenvolver com a linguagem, não deixe de aproveitar as facilidades que elas oferecem e otimize o tempo de desenvolvimento.

quinta-feira, 2 de dezembro de 2010

Automatizando tarefas com Autoit

Autoit V3

Conheci o Autoit a pouco mais de um ano, como sou fã de linguagens "direto ao ponto", de resultados rápidos, me identifiquei na mesma hora.

Se você não sabe do que se trata, sem problemas, eu explico: "Autoit é uma linguagem do tipo script, com uma sintaxe muito parecida com o BASIC e que permite automatizar tarefas em ambientes Windows. Você pode simular ações com o mouse e teclado, manipular janelas, arquivos, registro do Windows, conectar em um banco de dados, interagir com o Internet Explorer e com os elementos de uma página (utilizando conceitos de DOM)."

Isso é apenas uma pequena amostra do que a linguagem é capaz, pois ela ainda permite criar GUIs (Interfaces Gráficas) inteiras, ou seja, você pode criar um sistema desktop sem problemas.

Exemplo de interface GUI com Autoit
Exemplo de interface GUI com o Autoit extraído do site oficial

Além de ser uma linguagem completa, com uma vasta biblioteca de funções e inúmeras UDF´s (Bibliotecas homologadas criadas por usuários), o Autoit permite trabalhar com COM Objects e acessar DLL´s, ou seja, é difícil pensar em algo que ela não consiga fazer.

Não vou ser um daqueles fanáticos que nega até a morte a existência de problemas em seus objetos de adoração, ela possui algumas limitações e alguns bugs, por exemplo, eu não aconselharia criar um sistema de grande porte utilizando esta linguagem, até porque não é o foco e por exceção do SQLite, existem dificuldades em criar conexões com banco de dados conhecidos como: MySQL, SQL Server, Postgree, Oracle e etc. Apesar de existir uma UDF para se trabalhar com SQL e algumas outras não homologadas para trabalhar com alguns SGDBs conhecidos. Mas naquilo que o Autoit se propõe a fazer, o SQLite é mais do que suficiente para atender a maioria das necessidades.

Também já encontrei bugs em algumas funções mas nada que não possa ser contornado repensando um pouco seus scripts.

Se você se interessar e resolver mergulhar neste novo oceano de oportunidades que o Autoit lhe traz, descobrirá que ele também pode ser utilizado pelas forças do mal, você mesmo se sentirá inclinado pelo lado negro da força, quando descobrir que você pode perfeitamente criar keyloggers, vírus, worms entre outras pragas com algumas poucas linhas de código, nunca foi tão fácil destruir um PC.

Claro que apesar de algumas pessoas utilizarem para este fim, esta prática não é aconselhada e muito menos estimulada pelos desenvolvedores da linguagem e mesmo trabalhando a mais de um ano com ela, nunca parei para criar nada semelhante, eu teria apenas o trabalho de ter que consertar o estrago criado.

Para finalizar, se você esta querendo automatizar aquela tarefa repetitiva do dia a dia, ou quer deixar seus personagens de MMORPGS capinando ou matando monstros para aumentar de nível para depois vendê-los no ebay, ou quer criar uma ferramenta que monitore aplicações cruciais em um ambiente do qual você é administrador ou até mesmo deseja criar um pequeno aplicativo, sem ter que ficar se preocupando com inúmeros protocolos de linguagens burocráticas, então o Autoit é para você. Com uma comunidade ativa na internet, um fórum recheado de dicas, documentação eficiente, várias ferramentas para agilizar o desenvolvimento e compilador próprio, programar utilizando esta linguagem se torna algo extremamente divertido e eficiênte.

terça-feira, 30 de novembro de 2010

Vídeo: Todos nós queremos ser jovens (We all want to be young)

Mais um vídeo interessante, desta vez falando sobre aqueles que por décadas ditam tendências, mudam paradigmas e escrevem o futuro da civilização: Nós, os jovens.

O vídeo é resultado de um estudo realizado pela empresa BOX1824, que é especializada em tendências e comportamentos de consumo.

Obrigado a minha grande amiga Camila pela dica. Confira:

We All Want to Be Young (leg) from box1824 on Vimeo.

Vídeo: O que realmente nos motiva (The surprising truth about what motivates us)

Talvez este vídeo não seja novidade para você, mas caso você não tenha assistido e assim como eu trabalha em uma área que exige intelecto e criatividade, tenho certeza que irá gostar.

O vídeo traz uma palestra ministrada por Daniel Pink sobre seu livro "DRIVE - The surprising truth about what motivates us", que traz questões muito interessantes como: porque existem tantas pessoas trabalhando em projetos colaborativos sem receber um centavo em troca? Porque pagar um salário exorbitante para um funcionário não resulta em idéias mais criativas?

O vídeo dura cerca de 11 minutos e vale muito a pena mesmo de ser assistido. Não posso deixar de agradecer ao meu grande amigo Leonardo pela dica, confira:

quinta-feira, 25 de novembro de 2010

Criando VIEWS pelo phpMyAdmin em MySQL

Explicando a situação

Não quero introdução, mande-me direto ao ponto

Confesso que trabalhei um bom tempo sem saber da existência do conceito de uma VIEW (ou visões). Descobri isso poucos meses atrás, meus olhos brilharam quando eu entendi do que elas são capazes.

Até então sempre que eu precisava retornar informações de várias tabelas eu precisa criar as junções dentro da query no script php, ou pior, quando eu não estava com vontade nenhuma de colocar meu cérebro para trabalhar, eu esquecia totalmente do conceito de junções de tabelas e criava uma query para buscar cada informação de que eu precisava, era algo mais ou menos assim:


//Vamos buscar todas as compras
$sql = mysql_query('SELECT clientes_id, produtos_id, data_compra FROM compras');

while($dados = mysql_fetch_array($sql)){

 //Aqui eu pego o nome do cliente
 $sql_clientes = mysql_query('SELECT nome_cliente FROM clientes WHERE clientes_id ='.$dados['clientes_id']);
 $dados_clientes = mysql_fetch_array($sql_clientes);
 $nome_cliente = $dados_clientes['nome_cliente'];

 //Aqui eu pego o nome do produto
 $sql_clientes = mysql_query('SELECT nome_produto FROM produtos WHERE produtos_id ='.$dados['produtos_id']);
 $dados_produtos = mysql_fetch_array($sql_produtos);
 $nome_produto = $dados_produtos['nome_produto'];

 //Mostrando os resultados
 echo("Cliente: $dados_clientes[nome_cliente] - Produto: $dados_produtos[nome_produto] - Data da compra: $dados[data_compra]
");

}

Inegável que ela é totalmente ineficiente, mais lenta do que uma query com JOINs, além de mais trabalhosa, mas quando você tem recursos como o CTRL+C e CTRL+V disponíveis e tem que entregar tudo "pra ontem" é simplesmente mais simples e menos arriscado fazer isso, do que fazer JOINs que podem embolar o cérebro.

Abaixo a alternativa eficiênte, utilizando JOINs:


$sql = mysql_query('
 SELECT
  clientes.nome_cliente,
  produtos.nome_produto,
  compras.data_compra
 FROM `compras`
 LEFT JOIN clientes ON compras.clientes_id = clientes.clientes_id
 LEFT JOIN produtos ON compras.produtos_id = produtos.produtos_id

');

while($dados = mysql_fetch_array($sql)){

 echo("Cliente: $dados[nome_cliente] - Produto: $dados[nome_produto] - Data da compra: $dados[data_compra]
");

}

Com VIEWs podemos simplificar a história ainda mais e reduzir nosso bloco de código para algo assim:


$sql = mysql_query('SELECT cliente, produto, data FROM v_compras');
while($dados = mysql_fetch_array($sql)){

 echo("Cliente: $dados[cliente] - Produto: $produtos[nome] - Data da compra: $dados[data]
");

}

Bem mais simples certo? Mais ou menos, pois para que isso seja possível, teremos que criar a VIEW no nosso banco de dados, digamos que ela vai fazer o trabalho sujo e facilitar nosso trabalho durante o desenvolvimento.
Em uma situação ideal, quem faria isso seria um DBA, o que tornaria ainda mais simples a vida do programador, mas como esta não é a realidade de muitos, inclusive da minha, teremos que criar a VIEW nós mesmos.

Utilizando o phpMyAdmin para criar nossas VIEWS

Antes de mais nada espero que você já esteja com seu phpMyAdmin aberto, se não tiver por gentileza abra-o.

  1. Clique em uma tabela qualquer;
  2. No canto inferior da página, procure por "Operações resultantes da consulta" ou "Query results operations" para quem utiliza o phpMyAdmin em inglês, clique onde diz CREATE VIEW;
  3. Você será apresentando a um formulário pedindo para inserir algumas informações para criar a VIEW, neste caso o que nós apenas teremos que informar será:
    • Nome da VIEW
    • Campos da VIEW
    • Query da VIEW
  4. Escolha um nome para ela, convencionalmente eu utilizo v_nome_da_tabela_original, para distingui-las melhor em relação as tabelas originais;
  5. Defina os nomes das colunas da view, utilize vírgulas para separá-las;
  6. Por último, crie a query que fará a seleção dos valores que queremos que a VIEW nos retorne.

Seguindo nosso exemplo, ficaria algo assim:

Nome: v_compras
Colunas: id,cliente,produto,data
Query:
 SELECT
  clientes.nome_cliente,
  produtos.nome_produto,
  compras.data_compra
 FROM `compras`
 LEFT JOIN clientes ON compras.clientes_id = clientes.clientes_id
 LEFT JOIN produtos ON compras.produtos_id = produtos.produtos_id

Como você pode notar, a query que a gente utilizou aqui, foi a mesma do nosso segundo exemplo.
Feito isso, é só confirmar e começar a usufruir de sua criação.

Utilizar este recurso de banco de dados pode trazer diversas vantagens bem como desvantagens, não vou entrar em muitos detalhes, mas vamos dar uma olhadinha rápida nessas questões:

Algumas vantagens das VIEWs

  • Restringir acesso aos dados de uma tabela a apenas alguns usuários;
  • Combinar dados de várias tabelas em uma única VIEW (conforme nosso exemplo)
  • Menos retrabalho
  • Melhorar a performance de acesso aos dados
  • Mais segurança

Desvantagens das VIEWs

  • VIEWs muito complexas podem acabar exigindo muito processamento, tornando-se lentas;
  • Para atualizar uma VIEW, na maioria dos casos é necessários efetuar um DROP, atualizar a query e recriar a VIEW.

Se você tiver mais interesse em aprender sobre este assunto, achei um link bem interessante e completo que pode agregar em muito seu conhecimento: TWiKi - Lição Visões.

É isso aí, até mais!

terça-feira, 23 de novembro de 2010

Framework? Não sei nenhuma e agora?

Em desenvolvimento web, utilizar uma framework geralmente é o melhor caminho para entregar um projeto em menos tempo e com mais qualidade, isso é fato.

Sempre tive curiosidade e vontade de aprender a utilizar uma, mas a única que eu me
aventurei por um tempo foi a framework Django, utilizando a linguagem Python.

Confesso que estava gostando, mas tive que voltar a trabalhar e interrompi o aprendizado, aliás, este sempre foi o motivo de eu não aprender uma framework: ter que trabalhar em projetos pequenos e com prazos "pra ontem", não sobrando muito tempo para se dedicar à algo desse porte. Então como o tempo é curto, procuro aprender várias coisas que exigem menos tempo de dedicação e que agreguem ao meu trabalho.

Graças a esse modelo aprendi muita coisa sozinho: Ajax, Jquery, Json, PDO, SEO, além de diversas técnicas de CSS. Ter esses conhecimentos ajuda muito, posso dizer com segurança que tenho plena capacidade de escrever meus próprios plugins e "fuçar" nos dos outros, não ficando dependente de soluções de terceiros.

Claro que tenho plena consciência dos problemas de não utilizar uma framework, bem como um sistema de templates e não utilizar MVC. Acredite, o que eu mais peguei na vida foi código estilo macarrão, confesso que em alguns eu até aprendi algumas coisas novas, mas na maioria dos casos eles apenas fizeram eu querer sair correndo e devolver o dinheiro que me pagaram.

Seguindo a filosofia Rambo, de se virar como puder (MacGyver deve compartilhar esta mesma filosofia), resolvi criar meu próprio método de desenvolver, do qual me sinto confortável e satisfeito. O melhor dele, é que a única coisa mais próxima de uma framework que vou precisar, é o Jquery. Falo isso porque ele é considerado mais como uma biblioteca JavaScript, do que uma framework.

Outro fato que me traz satisfação neste método, é que eu não vou utilizar um sistema de templates para criar o visual, o próprio arquivo html será meu template, então não vou ter que aprender mais uma sintaxe especial de um sistema de templates informando para meu php o que ele precisa fazer lá.

A estrutura ficaria a seguinte:

MODELVIEWCONTROLS
MySQL / PDOHTML / CSSPHP / JavaScript (Json/Jquery)

  • Primeiramente eu trabalho o layout da aplicação, utilizando o HTML e CSS, resultado é todo o front-end do sistema.
  • Segundo lugar eu modelo e escrevo minhas classes, com as regras do negócio, persistência de dados e etc.
  • Por último, utilizo JSON e JQuery para interligar os pontos.

Oficialmente, não sei se esta é uma boa maneira de se trabalhar, mas foi a melhor que eu consegui, considerando que muitas vezes eu tenho que acumular os trabalhos de: designer, analista, programador front-end e back-end.

Quem sabe PHP tem que entender de HTML, quem entende de HTML tem de entender de CSS e JavaScript, Jquery é extremamente fácil de aprender e muito bem documentado e com um pouco de esforço extra, você também aprende JSON. Aprender orientação ao objeto e PDO é questão de gosto, mas eu recomendo, pois facilita muito o desenvolvimento e manutenção.

Enfim, para aqueles que não se empolgam tanto com uma framework ou não tem tempo para investiver no aprendizado de uma, acredito que esta seria uma boa forma de trabalhar, ao menos para mim, ela funciona.

Grande abraço e até uma próxima.

sexta-feira, 19 de novembro de 2010

Não esqueça do HTML

Quando eu fiz o curso técnico na área de informática tive uma ou duas aulas sobre HTML, na verdade, no currículo do curso esta matéria nem existia e o que estávamos aprendendo era PHP Básico, claro que é raro encontrar um curso em que uma tecnologia é abordada a fundo, na maioria das vezes é algo inviável. O ponto é, essas duas aulas de HTML me mostraram muito pouco sobre o assunto e eu sai de lá achando que HTML era uma linguagem de programação, apenas meses mais tarde eu descobri que ela na verdade era uma linguagem de marcação, só fui entender mesmo um pouco mais e o quanto um HTML bem estruturado é importante a pouco mais de um ano, sendo que trabalho com desenvolvimento a três anos.

Resumindo, passei dois anos da minha vida profissional de desenvolvedor considerando o HTML algo secundário, aprendi outras tecnologias, me aprofundei em algumas que já conhecia, e o HTML nada. Agora vamos pensar um pouco, navegadores entendem HTML, eles não processam linguagens lado servidor (PHP, ASP, Python, etc), eles processam HTML, processam folhas de estilos e scripts porque também rodam no lado do cliente, mas se você olhar a fundo, verá que tudo em uma aplicação web parte de alguma tag HTML, então quem é secundário nesta história toda? Certo que não é o nosso querido HTML.

Não conheço o mundo todo, mas conheço alguns outros programadores, alguns deles já me deram dicas preciosas sobre PHP, CSS ou banco de dados MySQL, mas nenhum deles me falou algo do tipo:

“Cara, porque você ta usando <h2> (título nível 2) no meio de um texto dentro de uma tag <p> (parágrafo)? Ah! Entendi, é porque ela deixa em negrito, mas seguinte, que tu acha da minha sugestão? Utiliza a tag <strong>, você quer informar ao navegador que esta palavra tem um contexto maior dentro do texto, então usa ela. O <h2>, representa um sub-título de uma página, use-o somente para este fim, os robôs de indexação de conteúdo agradecem.”

Óbvio que eu ficaria confuso e ficaria me perguntando o porque não posso utilizar um <h2> ao invés de um <strong>, se ambos deixam minhas palavras em negrito.
Para os mais entendidos do assunto isso tem uma explicação bem simples, não vou me aprofundar nela agora, pois não quero perder o foco deste artigo, mas se tiver curiosidade, começa a estudar um pouco de SEO (Search Engine Optimization) que você irá descobrir o porque HTML não pode ser considerado algo secundário.

Interoperabilidade é uma palavra que deve se tornar cada vez mais ouvida no mundo web, ser capaz de criar conteúdo que possa ser apresentado em diferentes dispositivos de maneira eficiente, se torna algo cada vez mais mandatório em nossa área e conhecer um pouco mais a fundo sobre essa tal linguagem de marcação chamada HTML, é um dos grandes pontos chaves para atender estas expectativas do mercado.

Para finalizar, caso você ainda não tenha muita experiência com HTML, resolvi criar uma lista com itens interessantes a serem estudados sobre o assunto. Divirta-se:

  1. Procure conhecer a diferença entre HTML e XHTML;
  2. Entenda o que é DHTML, DOM e os elementos de um documento HTML
  3. Estude sobre SEO, conheça algumas técnicas e se for desenvolvedor procure conhecer bem a importância do correto uso das tags
  4. Aprofunde seu conhecimento em CSS, saiba do que ele é capaz e como ele pode ser utilizado para diminuir significativamente as linhas de código de um documento HTML
  5. Comece a criar curiosidade sobre o HTML 5, apesar dele estar meio longe de se tornar padrão (HTML 4 demorou quase 10 para chegar em seu ápice), vale a pena conhecer o que a W3C esta preparando e como isso vai mudar nossas vidas.

terça-feira, 16 de novembro de 2010

Tutorial: Utilizando a classe Paging para criar uma paginação simples e rápida

No post "Paginação simples e rápida em PHP utilizando a classe Paging" foi apresentado a classe Paging, para criar paginação de dados tabelados.

Neste post, vamos ver passo a passo como fazer para utilizar os recursos desta classe e vamos construir um pequeno sistema de visualização de registros com as funções mais comuns esperadas de um recurso como este.

Arquivos necessários

Utilize o link abaixo para fazer o download dos arquivo necessários, esta tudo compactado em um arquivo zip, no total são cinco arquivos, iremos ver cada um deles a partir de agora.

produtos.sql

Execute o conteúdo deste arquivo no seu servidor mysql. Todo este exemplo é trabalhado baseando-se nos registros deste banco. Fique livre para usar qualquer outra tabela caso não queira poluir seu banco de dados com este sql. :)

paging.css

Utilizado para dar uma "floreada" em nossa tabela, aplicando alguns estilos.

connection.class.php

Utilizaremos este arquivo para fazer a conexão com o banco de dados.


  1. Abra o arquivo e altere os valores destacados em negrito, utilizando os dados de acesso ao seu banco de dados:

    private $dsn = 'mysql:dbname=paging;host=localhost';
    private $user = 'root';
    private $pass = '';
  2. Depois de alterado, pode salvar e fechar o arquivo, não iremos mais mexer nele.

paging.class.php

Este é o arquivo que faz toda a mágica. Você não precisa mexer em basicamente nada nele, a não ser que queira personalizar, fique a vontade para realizar as mudanças que julgar necessário.

exemplo_simples.php

É neste arquivo que iremos utilizar a classe Paging.

  1. Abra o arquivo e procure pelas linhas:
    1. require_once('paging.class.php');
    2. $paging = new Paging();
    3. $paging->table('produtos');
    4. $paging->labels('ID,Nome,Tipo, Descrição');
    5. $paging->fields('id,nome,tipo,descricao');
    6. $paging->rowsperpage(10);
    7. $paging->page(isset($_GET['p']) ? $_GET['p'] : 1);
  2. Nas primeiras duas linhas nos apenas incluímos a classe Paging e criamos uma instância do objeto Paging. Até aqui nada demais.
  3. Na linha "$paging->table('produtos');", nós informamos ao objeto, qual a tabela dentro do banco de dados, que queremos que os registros sejam retornados.
  4. Na linha "$paging->labels('ID,Nome,Tipo, Descrição');", utilizamos o método labels( ) para definir quais serão os valores do cabeçalho da tabela. Os valores que forem colocados ali, ficarão dentro das tags <th> da tabela. Utilize vírgulas para separar os valores.
  5. Na linha "$paging->fields('id,nome,tipo,descricao');", temos um método bem semelhante: fields( ), aqui você precisa informar quais são as colunas que terão o conteúdo retornado da tabela. Assim como no método labels( ), utilize vírgula para separar os valores.
  6. Na linha "$paging->rowsperpage(10);", temos o método rowsperpage( ), aqui você definirá o número máximo de registros que serão mostrados em cada página.
  7. Na linha "$paging->page(isset($_GET['p']) ? $_GET['p'] : 1);", temos o método page( ). Vamos passar como parâmetro o valor da página atual, informando ao objeto, de qual página queremos que ela retorne os registros. A classe Paging, utiliza a variável $_GET['p'] como padrão, portanto deixe ela reservada para a classe, caso precise mudá-la, você terá que fazer isso manualmente no arquivo paging.class.php. Como geralmente na primeira visualização da página, a variável $_GET['p'] não esta definida, nós utilizamos um "if inline" para validá-la.

Até aqui, o que nós apenas fizemos, foi configurar nosso objeto com alguns parâmetros, nada é mostrado em tela até então. Vamos ver como isso é feito:

  1. Procure pelas linhas:
    1. <div id="All">
    2. <div id="Table"><?php $paging->show_table(); ?></div>
    3. <div id="Paging"><?php $paging->show_controls(); ?></div>
    4. <div id="Pagecount">Página: <?php echo($paging->i_page) ?> de <?php echo($paging->pages_count())?></div>
    5. </div>
  2. Vamos ignorar a explicação das divs neste exemplo, elas são praticamente auto-explicativas e servem basicamente apenas para organizar o conteúdo.
  3. Na segunda linha, utilizamos mais um método de nossa classe: show_table( ), como o nome da a entender, é ele quem imprime na tela os registros recuperados.
  4. Logo abaixo, utilizamos mais um importante método, o show_controls( ), é ele quem mostrará os controles de navegação das páginas. Por padrão este método irá sempre mostrar até 5 links com páginas para o usuário navegar, mas caso você queira alterar este valor, utilize o método link_limit( ), e informe um novo valor para o objeto.
  5. Por último, temos na penúltima linha, o uso de mais um método pages_count( ), ele nos permite retornar o número de páginas encontradas pela classe, e com isso nós conseguimos mostrar ao usuário um status da navegação dele pelas páginas.

Se você conseguiu rodar localmente este exemplo, você deve estar vendo algo parecido com a imagem abaixo:

Bom, por hoje é só, espero que tenham apreciado o exemplo. Fiquem livre para comentar, tirar dúvidas ou dar sugestões. Até breve!

Paginação simples e rápida em PHP utilizando a classe Paging

Apesar de ser um assunto muito abordado em outros sites e blogs, resolvi postar aqui a minha abordagem de paginação em PHP. Se trata de uma classe, que com algumas poucas linhas de código, pode ser configurada para mostrar dados tabelados, com um painel de navegação entre páginas, semelhante ao utilizado no site da google.com.

Imagem demonstrativa


Exemplo de utilização

  1. Crie uma instância da classe
    require_once('paging.class.php');
    $paging = new Paging();
  2. Defina os parâmetros (atributos) principais
    $paging->table('produtos');
    $paging->labels('ID,Nome,Tipo, Descrição');
    $paging->fields('id,nome,tipo,descricao');
    $paging->page(isset($_GET['p']) ? $_GET['p'] : 1);
  3. Mostre os resultados: a tabela com os registros e controles de navegação
    $paging->show_table();
    $paging->show_controls();

Confira mais exemplos


Arquivos

Utilize o link abaixo para fazer o download dos arquivo necessários, esta tudo compactado em um arquivo zip, no total são dois arquivos, um é a classe connection.class.php, que você deve configurar com os dados de acesso para um banco de dados e o outro arquivo é o paging.class.php, responsável por criar a paginação. Caso tenha dúvidas de como proceder, confira os tutoriais disponíveis nos links acima.

Documentação

Abaixo você pode conferir a documentação da classe paging, com a lista de atributos e métodos disponíveis.

Atributos


NomeTipoModificadorDescrição
s_tableStringPublicNome da tabela do banco em que o objeto irá operar.
s_fieldsStringPublicLista de campos(colunas) da tabela que deverão ser retornadas (separados por vírgulas).
s_labelsStringPublicLista com os valores que serão apresentados nas colunas do cabeçalho da tabela (separados por vírgulas).
s_whereStringPublicClausúla 'Where', caso ouver, senão poderá ser deixada em branco e assumirá '1' (tudo) na hora de realizar a query.
s_orderbyStringPublicNome da coluna que irá ser utilizada para ordenar os registros. Assume 'id' como padrão, caso não seja informada.
s_orientationStringPublicOrientação dos registros Ascendente 'ASC' ou Descendente 'DESC'.
i_rowsperpageIntegerPublicNúmero de registros mostrados por página. Se não for informado, assumirá 50 por padrão.
i_pageIntegerPublicPágina atual utilizada para a leitura dos registro. O padrão é 1, ou seja, primeria página.
i_link_limitIntegerPublicLimite de número de links de páginas mostrados no painel de navegação da paginação. Assume 5 caso não seja informado.
a_columnsArrayPublicArray responsável por armazenar as colunas inseridas manualmente.
a_cols_widthArrayPublicArray com os tamanhos das colunas do grid.

Métodos

NomeRetornaModificadorDescrição
table(String)NullPublicMétodo set, utilizado para definir a propriedade 's_table'
fields(String)NullPublicMétodo set, utilizado para definir a propriedade 's_fields'
labels(String)NullPublicMétodo set, utilizado para definir a propriedade 's_labels'
where(String)NullPublicMétodo set, utilizado para definir a propriedade 's_where'
orderby(String)NullPublicMétodo set, utilizado para definir a propriedade 's_orderby'
orientation(String)NullPublicMétodo set, utilizado para definir a propriedade 's_orientation'
rowsperpage(Int)NullPublicMétodo set, utilizado para definir a propriedade 'i_rowsperpage'
page(Int)NullPublicMétodo set, utilizado para definir a propriedade 'i_page'
link_limit(Int)NullPublicMétodo set, utilizado para definir a propriedade 'i_link_limit'
total_rows()IntegerPublicRetorna o número total de registros encontrados, baseando-se nos atributos(s_fields,s_where) passados para o objeto.
pages_count()IntegerPublicRetorna o número total de páginas.
thead()ArrayPrivateRetorna um array com as células utilizados no cabeçalho da tabela. Usada apenas internamente pela classe.
cells()ArrayPrivateRetorna um array com os campos que deverão ser retornados do banco de dados. Usada apenas internamente pela classe.
page_scale(Int, Int, Int)ArrayPrivateCria uma escala numerada de páginas, avança na escala conforme o número da página atual informado, mantendo sempre números iguais de páginas anteriores e próximas a atual. Usada apenas internamente pela classe.
show_table()NullPublicEscreve na tela a tabela com os registros recuperados.
show_controls()NullPublicMostra o painel de controle da paginação, com os links: ('Primeira','Anterior','Escala numerada','Próxima','Última'). Aqui existe um pequeno porém, caso o número de registros por página seja insuficiente para criar mais do que uma página, então os controles não serão mostrados, resumindo: 1 página = nenhum controle, 2 páginas ou mais = mostra controles.
add_column()NullPublicPermite adicionar manualmente colunas no grid.
cols_width()NullPublicPermite ajustar o tamanho das colunas do grid.
É isso aí, espero que tenham apreciado, qualquer dúvida, critica ou sugestão por favor deixe um comentário, irei responder assim que possível.

segunda-feira, 15 de novembro de 2010

Programação Orientada a Resultados

Na área de desenvolvimento é comum se falar de paradigmas: procedural, orientado a objeto, orientada a aspecto e por aí vai.
Independente do paradigma utilizado, existe uma constante que rege não apenas nossa área de trabalho, como qualquer outra: "Precisamos entregar resultados".

Muita gente, a medida que este blog for crescendo, vai discordar de muita coisa que eu postar aqui, porque não defenderei padrões de desenvolvimento, frameworks ou qualquer outro conceito comumente utilizado na área, minha visão será sempre focada em resultado.

Se utilizar tal framework vai entregar o resultado de que precisa, então beleza, use-a. Se utilizar um sistema de templates será bom para o projeto, perfeito, mas se você preferir fazer tudo na munheca e demorar alguns dias a mais para fazer um trabalho, não se martirize por isso.

A visão é simples, existe muita tecnologia no mercado, muitos padrões, tendências e exigências, para ser um desenvolvedor, exigem um currículo extenso, com inúmeros conhecimentos, porém, esse é uma realidade muito volátil, conhecer uma Zend Framework em um lugar pode não significar mais do que criar um script todo procedural que resolveu um problema de anos dentro de uma empresa.

Lógica é importante, conhecer a linguagem e não apenas sua sintaxe é importante, com esses dois itens somado a força de vontade de aprender e uma dose de oportunidade você é capaz de utilizar qualquer tecnologia encontrada no mercado, mas mais importante do que saber um punhado de tecnologias que os outros querem que você saiba, é ter satisfação naquilo que você faz, com isso você entrega resultado, que é o que toda empresa quer e a tecnologia será meramente secundária.

Para finalizar, muitos mas muitos desenvolvedores não irão compartilhar de minha visão, irão dizer que eu não sei nada de programação, que provavelmente sou um amador, não discordarei, realmente, se for analisar em todo um contexto, tenho muito a aprender, mas acredito que também tenho com o que contribuir, se algo que eu postar aqui estiver errado, ou pudesse ter sido escrito melhor, por favor contribua positivamente com sua crítica e sugestão de melhoria, afinal quem toma a liberdade de criticar é porque tem a plena capacidade de fazer melhor.

Seja bem-vindo!