Chega uma hora na vida que nossos programas Perl têm que sair da mera linha de comando. Não que haja problemas com a linha de comando. Mas algumas pessoas acabam não gostando muito dela. Seja por que a considerem feia, pouco amigável, entediante ou seja lá o que for.

Um dia seu chefe virá para você e dirá: "Eu queria que estas aplicações que você fez para obter informações dos servidores fiquem disponíveis para o pessoal do atendimento nível 1". E você retruca: "Elas estão!".

O chefe termina: "O pessoal do nível 1 não está familiarizado com linha de comando! Quero uma coisa gráfica, fácil de usar e acessível de qualquer computador da empresa!".

Você poderia responder: "Coisa gráfica? Pede para equipe do Windows. Eles adoram gráficos, janelinhas, campainhas e coisas inúteis...". Mas você não quer dar esse gostinho para eles... o gostinho de pegarem seus programas em linha de comando, colocarem em uma caixinha colorida e levar toda a fama...

Então pensamos: "Vamos criar algo do tipo cliente/servidor? Banco de dados? Aplicativo local? Web?". O pessoal do Linux convoca um Brain Storm (no barzinho do Zé) para discutir o assunto. E surgem as ideias: Qt, PHP, MySQL, Postgree, Apache, shell script, Java, C...

Parece que teremos um programa monstro, daqueles que usam diversas linguagens de programação diferentes. PHP para a interface Web, shell script e C para realizar as tarefas de administração dos servidores... Sugeriram até um pouco de Java. Não haverá escapatória? Iríamos criar um monstrengo???

Aí alguém da sua equipe bate na mesa. As cervejas balançam. Caem algumas gotas sobre a mesa. E a salvação aparece: "Por que a gente não faz tudo em Perl? Podemos criar os módulos de gerência dos servidores, a interface Web e de quebra ainda podemos fazer os módulos do Apache. Não vamos gastar um dólar com licença de software e não precisamos instalar nada novo nos servidores Linux."

Do que eu vou falar aqui?

Entre as funcionalidades do Perl está a capacidade de criar e gerenciar aplicativos Web. Para isto temos o CGI, DBI, o Catalyst entre outros que facilitam a vida do programador. Além de dezenas de milhares de módulos no CPAN.org que estão lá para nos ajudar.

Este artigo vai apresentar uma introdução aos aplicativos CGI com Apache, Perl e MySQL. Independentemente de sua implementação em servidores Linux ou Windows. O Perl é isto: Liberdade de escolha. Inclusive pode-se usar Perl no IIS*. Mas isso é humilhar demais os programadores ASP.

Nota: se quiser saber como fazer o IIS executar Perl acesse a página do ActivePerl

Bom, obviamente você vai precisar de um sistema com Perl, MySQL e Apache instalados. Por enquanto estou usando as configurações padrão da instalação. Na minha instalação do Debian GNU/Linux, novinha aliás, não foi necessário fazer nenhuma modificação nas configurações padrão do Apache, Perl ou MySQL.

Mas como o Apache é um pouco diferente e o Apache do meu Debian é diferente do Apache onde eu trabalho que está num Red Hat, fica a dica para verificar as opções de configuração abaixo que devem estar habilitadas:


LoadModule cgi_module modules/mod_cgi.so
ScriptAlias /cgi-bin/ "<PATH da sua pasta CGI>"

Quanto ao MySQL você pode usar a linha de comando o MyAdmin, o QueryBrowser. Fique à vontade sobre como gerenciar e criar seus bancos. A versão que usaremos é a: 5.0.51a:

comandos SQL

O Perl pode ser o ActiveState, Strawberry* ou aquele original da sua instalação. Apenas verifique se ele está atualizado. Qualquer versão acima da 5.6 está ótimo. É só digitar:

$ perl -v

E verificar a versão:

comandos SQL
Nota: O Strawberry é uma distribuição do Perl para Windows. Assim como o MySQL e o Apache funcionam no Windows. Tudo que fizermos aqui funcionará corretamente no Windows desde que devidamente configurados. Se tiver necessidade de usar no Windows - shame on you - você deve alterar o she-bang dos scripts para:
#!c:\<PATH DA SUA INSTALAÇÃO DO PERL>\perl

Agora que está tudo verificado, VAMOS PARA A AÇÃO!

Criando a primeira página Web com Perl

Abra o seu editor de textos e digite o código abaixo. Salve como "ambiente.pl" no diretório que está definido no item ScriptAlias do arquivo de configuração do seu Apache. Normalmente é uma pasta com o nome cgi-bin. No meu caso fica em /usr/lib/cgi-bin.

#!/usr/bin/perl
use warnings;
use strict;
use CGI; #Carrega o módulo CGI, que permite criarmos scripts cgi - claro!
my $cgi = CGI->new; #Criamos uma instância da classe CGI
print $cgi->header, # Primeiro criamos o Cabeçalho
  $cgi->start_html('Minha Primeira Página Perl'), # Iniciamos o Arquivo HTML
  $cgi->h1('BEM VINDO AO PERL'), # Cria a Tag <h1>TEXTO</h1>
  $cgi->p(scalar localtime), # Cria <p>Texto</p>
  $cgi->h3("Minhas Variáveis Locais:\n");
foreach my $chave (keys(%ENV)) {
  print $cgi->p($chave . " => $ENV{$chave}");
}
print $cgi->end_html; # Finalizamos o HTM

E veja o resultado no seu browser:

comandos SQL

O nosso script primeiro cumprimenta o usuário, mostra a hora atual e apresenta as variáveis de ambiente. Bacana mas, antes de continuar vamos falar um pouco sobre o módulo CGI do Perl.

O módulo CGI é uma solução Perl completa e bem madura que pode receber e criar requisições HTTP. É uma solução com mais de dez anos de desenvolvimento e burilamento. Comecei está série de artigos com ela por que já está entre os principais e mais consagrados módulos do Perl.

Com ele podemos criar tags HTML em um estilo de programação orientado a objetos.

$meuObjetoCGI = CGI->new;
$meuObjetoCGI->tagHTML([parâmetros]);

A primeira vantagem desta forma de escrever códigos é a organização. O código é mais enxuto e legível que o HTML/XHTML tradicional. A outra vantagem é a possibilidade de criar páginas com estrutura dinâmica com pouco esforço. Mas a maior vantagem é poder levar o poder do Perl para suas aplicações Web.

Para ver uma característica prática, execute o script na linha de comando e veja a saída:

comandos SQL

Perceba que na primeira linha invocamos strict e warning. Sempre use 'strict' e 'warning' em seus scripts Perl. Irá salvar muito tempo de trabalho com depuração. Depois nós carregamos o módulo CGI e criamos uma instância do mesmo:

$my $cgi = CGI->new

Utilizar o modo de orientação a objetos é uma boa prática, pois aplicações Web complexas exigem diversos módulos, e ficar usando alguns como objetos e outros como funções carregadas tornará seu código uma bagunça.

No trecho:

print $cgi->header,                      
      $cgi->start_html('Minha Primeira Página Perl'), 
      $cgi->h1('BEM VINDO AO PERL'),  
      $cgi->p(scalar localtime),   
      $cgi->h3("Minhas Variáveis Locais:\n");

Estamos criando o cabeçalho HTML e criamos o corpo da página. A função 'localtime' retorna um array com o horário local, ou um string quando o contexto é escalar. A função scalar obriga a função localtime a retornar um escalar.

No penúltimo bloco de código:

foreach my $chave (keys(%ENV)) {
    print $cgi->p($chave . " => $ENV{$chave}");
}

Um hash é um tipo de variável do Perl que armazena valores relacionados a uma chave.

O hash %ENV é uma variável interna do Perl e carrega as variáveis de ambiente no formato: %ENV = {Variável => valor_da_variável}. A função keys retorna um array com todas as chaves do hash. Então, no nosso caso, retornará o nome de todas as variáveis de ambiente. E para cada uma delas - foreach - ele mostrará no documento HTML o nome_da_variável => valor_va_variável.

E encerramos com:

print $cgi->end_html; 

Moral da história

Fizemos aqui uma pequena apresentação dos scripts CGI com Perl. O módulo CGI permite que você crie documentos com qualquer tag HTML, processe formulários e crie páginas dinâmicas.

Apresentamos, para os que não são familiarizados com esta linguagem, o loop foreach, que executa uma repetição para cada item de um dado array. O conceito de hash - que pode ser entendido como um array associativo por nome ao invés de ordenado por número de posição. Pode ser comparado com o tipo dicionário de outras linguagens. Porém o intuito aqui não é apresentar ao Perl mas suas funcionalidades de programação Web.

Agora vamos falar um pouco sobre o MySQL com o Perl e o DBI. O MySQL é um dos Bancos de Dados Relacionais mais utilizados no mundo. Mas, para alguém que acessa este site isto é uma informação redundante. Apesar de ser impossível não elogiar o MySQL vamos passar direto para a comunicação do MySQL com o Perl. Caso tenha interesse em mais detalhes sobre o MySQL acesse http://dev.mysql.com/. Para acessar o MySQL com Perl é necessário que você instale alguns módulos do CPAN. Estes módulos vão administrar a conversa entre o seu programa e o banco de dados. No nosso caso, eu recomendo o Perl DBI. Para isso digite na sua console os comandos a seguir:

$cpan intall DBI 

E deixe a instalação rolar. Caso o cpan solicite alguma informação responda conforme a instalação no seu sistema. Em dúvida, deixe um poste aqui e eu responderei. No meu caso o DBI já estava instalado:

$ cpan install DBI 
CPAN: CPAN::SQLite loaded ok (v0.199) 
Database was generated on Sun, 16 May 2010 20:31:26 GMT 
CPAN: Module::CoreList loaded ok (v2.31) DBI is up to date (1.611). 

Uma vez que o módulo DBI está instalado temos que nos certificar que temos os drivers necessários. No CPAN temos drivers para diversos bancos de dados, sendo possível utilizar bancos MySQL, MS-SQL, Oracle entre outros. Para verificarmos os drivers possíveis digite:

$perl -MDBI -e '@drivers = DBI->available_drivers; print qw/@drivers/;' 
$ perl -MDBI -e '@drivers = DBI->available_drivers; print qq/@driv ers/;' 
ADO DBM ExampleP File Gofer ODBC Pg Proxy SQLite Sponge mysql 

No nosso caso o driver do MySQL aparece como último da nossa lista, então ele está instalado. Porém, caso não apareça o driver do MySQL na sua instalação, utilize o comando $cpan install DBD::mysql.

$ cpan install DBD::mysql
CPAN: CPAN::SQLite loaded ok (v0.199)
Database was generated on Sun, 16 May 2010 20:31:26 GMT
CPAN: Module::CoreList loaded ok (v2.31)
DBD::mysql is up to date (4.014).

Rode novamente o comando para verificar os drivers de banco de dados do DBI e certifique-se de que você tem o driver correto. Para instalar o driver de outro banco de dados, verifique o driver em http://search.cpan.org/.

Conectando-se com o banco de dados

Vamos criar um banco qualquer. No caso eu criei o banco vivaoLinux no console do MySQL.

CREATE DATABASE `vivaoLinux` ; 

$dbh será nossa variável de manuseio do banco, ou seja, o database handle. Para criar um database handle a sintaxe é a seguinte:

my $dbh = DBI->connect(“DBI:<nome_do_driver>:<nome_do_banco>:<servidor>”, ”<usuário>”, ”<senha>”).

O módulo DBI também fornece a variável DBI::errstr que armazena possíveis mensagens de erros. Muito útil para debugar erros. Então, vamos criar um programa para acessar o banco 'vivaoLinux' com o Perl. Para acessar um banco temos que criar o database handle. Para isso crie um arquivo, no meu caso artigo.pl e digite o código abaixo:

use strict;use warnings;
use DBI;
my $dbh = DBI->connect("DBI:mysql:vivaolinux:localhost", 'root','root')
  or die ("Não foi possível fazer conexão: " . $DBI::errstr);
$dbh->disconnect();

A primeira observação clara é: você nunca irá usar o usuário root num programa que acessa um banco em produção. Pois é uma falha séria de segurança. O usuário declarado na string de conexão do programa deve ter as configurações se acesso no sistema do banco de dados restritas às operações necessárias. Então, o root não é necessário. Isso é importante, pois caso o banco esteja inacessível a strig de erro pode mostrar ao usuário do programa as informações da conta de acesso ao banco. Veja abaixo o erro que aparece se eu executar o programa acima com o serviço do MySQL parado:

$perl artigo.plDBI connect('vivaolinux:localhost','root',...)
 failed: Can't connect to MySQL server on 'localhost' (10061) 
 at artigo.pl line 8
Não foi possível fazer conexão: 
Can't connect to MySQL server on 'localhost' (10061) at artigo.pl line 8.

Criando Tabelas no Banco

Para criar tabelas no banco com o Perl DBI, criamos uma string com o valor do código SQL que queremos adicionar, então, usamos o método 'do' pertencente ao nosso objeto $dbh, como o código abaixo:

#!/usr/bin/perluse strict;
use warnings;
use DBI;
my $dbh = DBI->connect("DBI:mysql:vivaolinux:localhost", 'root','')
  or die ("Não foi possível fazer conexão: " . $DBI::errstr);
my $sql = qq{CREATE TABLE itens (id INT NOT NULL,Item VARCHAR(255),
  Descr VARCHAR(255),Preco REAL,Vid INT NOT NULL)};
my $return = $dbh->do($sql);
if($return) {print "Table addition successful!\n";}else {
  print "\n\nERROR! $DBI::errstr\n";}
$dbh->disconnect();
saída:
Table addition successful!

Veja que o procedimento foi extremamente simples. E a vantagem que temos definindo a query SQL em uma string $sql é a versatilidade do Perl. A string pode ser gerada dinamicamente no código conforme nossa necessidade e algoritmo. Para alterarmos o valor uma tabela basta modificar a variável $sql:

my $sql = "ALTER TABLE itens ADD Qta VARCHAR(20)";

e para remover uma tabela completa:

my $sql = "DROP TABLE itens";

Enviando dados para uma tabela

Para enviar dados para uma tabela, temos que executar o método 'prepare' do DBI antes do 'execute', como você vê abaixo:

#!/usr/bin/perl
use strict;
use warnings;
use DBI;
my $dbh = DBI->connect("DBI:mysql:vivaolinux:localhost", 'root','')
 or die ("Não foi possível fazer conexão: " . $DBI::errstr);
my $sql = "INSERT INTO itens (id,Item,Descr,Preco,Vid,Qta) " .
"VALUES ('01','Curso Perl','Curso Perl do Basico ao Profissional',".
"'90.00','10','20')";
my $query = $dbh->prepare($sql);$query->execute 
or die("\nErro executando query! $DBI::errstr");
print "Query $sql executada com sucesso.";
$dbh->disconnect();
saída:
Query INSERT INTO itens (id,Item,Descr,Preco,Vid,Qta) 
VALUES ('01','Curso Perl','Curso Perl do Basico ao Profissional',
'90.00','10','20') executada com sucesso.

O Perl, como uma das mais poderosas linguagens de programação da atualidade unido com o módulo DBI apresenta uma interface de programação muitíssimo poderosa e prática para o uso com MySQL, permitindo a criação de aplicações sólidas com pouco esforço.