goncin@wordpress.com:~$ _

Linux, programação e toda sorte de nerdices

Arquivos de tags: programação

Ubuntu Mono: uma nova e ótima fonte para programar

Na última semana, os designers do Ubuntu atualizaram a família de fontes homônima, atualizando a variante monoespaçada. Essa variante, que já existia nas versões anteriores do pacote, foi bastante aperfeiçoada, tendo sido feito o trabalho de hinting, essencial para que a fonte seja legível em tamanhos menores e que ela não pareça “embaçada” na tela. Eis como ficou:

Ubuntu Mono, 24pt

Ubuntu Mono, 24pt

Ela tem caracterísiticas interessantes para os programadores, como o zero ponteado (para ser distinto do “O” maiúsculo), e é bastante compacta, de modo que a tela exibe mais linhas de código, comparada com outras fontes.

Ubuntu Mono no Netbeans

Ubuntu Mono no Netbeans

Ubuntu Mono no GEdit

Ubuntu Mono no GEdit

Certamente, a variante monoespaçada virá como padrão na próxima versão do Ubuntu, a Oneiric Ocelot (11.10), que sairá do forno ainda esse mês. Para quem não aguenta esperar e usa Ubuntu ou distros derivadas pode instalar a nova versão da Ubuntu Mono mediante um PPA:

sudo add-apt-repository ppa:webupd8team/ubuntu-font-family
sudo apt-get update
sudo apt-get install ttf-ubuntu-font-family

Já aqueles que usam outra distribuição (ou Windows 😦 , ou Mac 🙂 ) pode baixar as fontes num pacote ZIP aqui.

Aproveitem! 🙂

Anúncios

Integrando WordPress e Yii Framework: uma nova abordagem

Artigo publicado originalmente em inglês no wiki do Yii
Framework
, em 1º de julho de 2011.

Parece que muitas pessoas andam tentando fazer com que o WordPress e o Yii Framework trabalhem em conjunto. Eu me deparei com o mesmo problema, mas agora creio que o resolvi, após muito quebrar a cuca e gastar inúmeras horas de trabalho.

Meu ponto de partida foi a leitura dos artigos (em inglês) do imasia e do isekream. O princípio de ambas as pesquisas é chamar a aplicação Yii de dentro do WordPress. A solução que proponho coloca-se na mão contrária: utilizar o WordPress como modelo de página para a aplicação Yii, de modo que o usuário final nem perceberá que saiu do primeiro e foi parar na segunda.

Vamos em frente.

No WordPress

Minha instalação do WordPress usa um tema-filho do Twentyten (o padrão do WordPress 3.x). Para os efeitos deste tutorial, assumamos que nossa instalação do WordPress está em http://seuservidor.com.br/wp. Ao aplicá-lo, altere o caminho de acordo com sua situação.

O primeiro passo é criar um arquivo na pasta do seu tema do WP, e chamá-lo yii-template.php.

Arquivo: [raiz-wp]/wp-content/themes/[seutema]/yii-template.php

<?php
/**
 * Template Name: Yii Template
 *
 * Template for Yii-powered pages
 *
 * The "Template Name:" bit above allows this to be selectable
 * from a dropdown menu on the edit page screen.
 *
 * @package WordPress
 * @subpackage Twenty_Ten
 * @since Twenty Ten 1.0
 */
get_header();
?>
 
<div id="container">
  <div id="content" role="main">
 
    <?php
    /*
     * O marcador de lugar abaixo será substituído mais tarde pelo conteúdo gerado pelo Yii.
     */
    ?>
    <!-- ###yii-content-placeholder### -->
 
  </div><!-- #content -->
</div><!-- #container -->
 
<?php get_sidebar(); ?>
<?php get_footer(); ?>

Acabamos de criar um novo modelo para páginas do WordPress.

O passo seguinte é criar uma página no WordPress que use o modelo recém-criado. Acesse o painel administrativo do seu WP, crie uma página e selecione “Yii Template” (deve estar listado) como modelo da página. Informe yiipage no título e deixe o conteúdo da página em branco. Após salvar, você deverá ser capaz de ver a página usando o endereço http://seuservidor.com.br/wp/yiipage.

Isso é tudo o que tínhamos que fazer no WordPress.

No Yii

Crie uma aplicação Yii (usando yiic) sob a raiz da sua instalação do WP, numa pasta chamada yii. Você deverá ver a conhecida página inicial do Yii ao acessar http://seuservidor.com.br/wp/yii.

We’ll need a custom ClientScript class. Let’s create it under [yii-root]/protected/components.

Teremos que criar nossa própria classe ClientScript. Vamos fazê-lo sob  [raiz-yii]/protected/components.

Arquivo: [raiz-yii]/protected/components/ClientScript.php

<?php
 
class ClientScript extends CClientScript {
 
  public function renderHead(&$output) {
    $html = '';
    foreach ($this->metaTags as $meta) $html.=CHtml::metaTag($meta['content'], null, null, $meta) . "\n";
    foreach ($this->linkTags as $link) $html.=CHtml::linkTag(null, null, null, null, $link) . "\n";    
    foreach ($this->cssFiles as $url => $media) $html.=CHtml::cssFile($url, $media) . "\n";
    foreach ($this->css as $css) $html.=CHtml::css($css[0], $css[1]) . "\n";
    if ($this->enableJavaScript) {
      if (isset($this->scriptFiles[self::POS_HEAD])) {
        foreach ($this->scriptFiles[self::POS_HEAD] as $scriptFile) $html.=CHtml::scriptFile($scriptFile) . "\n";
      }

      if (isset($this->scripts[self::POS_HEAD])) $html.=CHtml::script(implode("\n", $this->scripts[self::POS_HEAD])) . "\n";
    }

    if ($html !== '') {
      $count = 0;
      /*
       * A linha abaixo garante que tudo o que for registrado pelo Yii no POS_HEAD irá imediatamente
       * antes do final do cabeçalho (). Dessa forma, os estilos e scripts do Yii serão
       * renderizados *ABAIXO* e *DEPOIS* daqueles do WordPress.
       *
       * A linha original na classe ancestral era assim:
       * $output = preg_replace('/(]*>|)/is', '$1', $output, 1, $count);
       *
       */
      $output = preg_replace('/()/is', '$1', $output, 1, $count);
      if ($count) $output = str_replace('', $html, $output);
      else $output=$html . $output;
    }
  }
 }
?>

Será necessário também sobrepor o método CController.beforeRender(). Isso pode ser feito no arquivo Controller.php, que já existe em [raiz-yii]/protected/components.

Arquivo: [raiz-yii]/protected/components/Controller.php

<?php
/**
 * Controller is the customized base controller class.
 * All controller classes for this application should extend from this base class.
 */
class Controller extends CController
{
    /**
     * @var string the default layout for the controller view. Defaults to '//layouts/column1',
     * meaning using a single column layout. See 'protected/views/layouts/column1.php'.
     */
    public $layout='//layouts/column1';
    /**
     * @var array context menu items. This property will be assigned to {@link CMenu::items}.
     */
    public $menu=array();
    /**
     * @var array the breadcrumbs of the current page. The value of this property will
     * be assigned to {@link CBreadcrumbs::links}. Please refer to {@link CBreadcrumbs::links}
     * for more details on how to specify this property.
     */
    public $breadcrumbs=array();
 
  protected function beforeRender($view) {
 
    /* 
     * Let's prevent Yii from registering jQuery library. We'll stick with
     * the jQuery registered by WordPress.
    */
    Yii::app()->clientScript->scriptMap=array(
      'jquery.js'=>false,
      'jquery.min.js'=>false,
    );
    /*
     * O WordPress trabalha com a jQuery no modo "sem-conflito", i. e., ele não define o apelido $
     * para o objeto jQuery. No entanto, muitos scripts e plugin do Yii supõem que $ aponta para a
     * jQuery, de modo que precisamos fazer essa associação nós mesmos.
     */
    if(! Yii::app()->clientScript->isScriptRegistered('jquery-alias', CClientScript::POS_HEAD)) {
      Yii::app()->clientScript->registerScript('jquery-alias', 'var $ = jQuery', CClientScript::POS_HEAD);
    }

    /*
     * Para manter a coerência visual entre as páginas comuns do WordPress e aquelas turbinadas
     * pelo Yii, devemos utilizar o CSS fornecido pelo tema do WordPress. Contudo, o Yii usa
     * algumas classes CSS específicas para formulários, então é uma boa ideia registrar o
     * arquivo que as contém.
     */
    Yii::app()->clientScript->registerCssFile(Yii::app()->request->baseUrl . '/css/form.css');

    return parent::beforeRender($view);
  }

}
?>

Agora, a pedra fundamental da ideia toda. Vamos alterar o arquivo principal do layout do Yii, para buscar a página do WordPress que preparamos previamente, e substituir o marcador de lugar pelo conteúdo gerado pelo framework.

Arquivo: [raiz-yii]/protected/views/layouts/main.php

<?php
  /*
   * Aqui reside o cerne da mágica. Ao invés de usar o HTML do arquivo principal de
   * layout fornecido pelo Yii, buscamos a página especial do WordPress (como uma string)
   * e substituímos o marcador de lugar pelo conteúdo real.
   */

  echo str_replace('<!-- ###yii-content-placeholder### -->',
    $content, file_get_contents('http://seuservidor.com.br/wp/yiipage'));

  /* NÃO SE ESQUÇA DE APAGAR O CONTEÚDO DA PÁGINA ORIGINAL 😉 */

?>

Por fim, vamos dizer ao Yii para usar nossa classe ClientScript personalizada.

Arquivo: [raiz-yii]/protected/config/main.php

<?php   
    (...)   'components'=-->array(
    /*
     * Vamos usar nosso próprio ClientScript (application.components.ClientScript).
     */
    'clientScript' => array(
      'class' => 'ClientScript'
    ),
  (...)
?>

E isso é tudo. Você deverá conseguir ver sua aplicação Yii com tema WordPress acessando http://seuservidor.com.br/wp/yii, e até mesmo fazer login mediante http://seuservidor.com.br/wp/yii/index.php?r=site/login. Adicionalmente, você pode ajustar sua configuração do Yii para usar URLs de caminho e ocultar o nome do script (assim, seus URLs se parecerão com http://seuservidor.com.br/wp/yii/controller/action). E sim, o AJAX funciona! *__*

De volta ao WordPress, a tarefa final é criar itens de menu (como links) apontando para as páginas turbinadas pelo Yii.

Espero que isto seja tão útil para você quanto foi para mim. Saudações!

Aprendendo a pensar com expressões regulares

Vivendo e aprendendo. Parece não haver máxima mais certeira quando se trata da vida de um #SouDev 😉 .

No meu último post, no qual tratei sobre normalização de nomes próprios, eu havia utilizado uma expressão regular para testar se determinada parte de um nome corresponde a um numeral romano. Antes de encontrar a expressão regular para fazer o teste, eu já estava quebrando a cabeça para escrever uma rotina para fazer a mesmíssima tarefa. Eis o que eu pensava em fazer:

  • Testar se a substring continha apenas caracteres válidos para números romanos – no caso, ‘I’, ‘V’, ‘X’, ‘C’, ‘D’ e ‘M’. Essa era a parte fácil.
  • Determinar se os ditos caracteres estavam na ordem e na quantidade corretas para representar um número romano válido – e era aí que a porca torcia o rabo.

Pelo meu método de raciocínio costumeiro, essa rotina teria alguns loops e outros tantos ifs, e, com certeza, não teria menos que dez linhas de código PHP. Ao pesquisar sobre a estrutura dos números romanos, deparei-me com a expressão regular que você pode observar na linha 18 da listagem daquele post (e que foi utilizada na linha 100). Com ela, resolvi meu problema em uma única linha.

Se eu havia sido esperto nessa parte do código, cometi uma sobrinhagem na parte em que eu precisava substituir todas os espaços duplos por espaços simples. Desde sempre, utilizei um laço para substituir todas as ocorrências de dois espaços por um único espaço, até que não houvesse mais nenhum daqueles. Desta forma:

<?php
while(mb_strpos($nome, self::NN_ESPACO_DUPLO) != false)
      $nome = mb_ereg_replace(self::NN_ESPACO_DUPLO, self::NN_ESPACO, $nome);

Isso funciona assim: se houver quatro espaços contíguos, na primeira passagem esses quatro tornar-se-ão dois. Somente na segunda passagem é que esses dois espaços serão reduzidos a apenas um, que é o resultado desejado. Quanto mais espaços contíguos, mais repetições serão necessárias.

E tudo isso se resolve, de forma muito mais elegante e eficiente, também com uma expressão regular, e em uma única instrução. E o melhor: independentemente da quantidade de espaços contíguos.

<?php
$nome = mb_ereg_replace('\s+', ' ', $nome);

A mágica reside na expressão regular \s+. O que ela significa? \s encontra espaços em branco, e o modificador + indica uma ou mais ocorrências. Era tudo o que eu precisava. E já corrigi o código do post anterior.

As expressões regulares, ao mesmo tempo que encantam com seu poder, também costumam assustar pela sua relativa complexidade. Antes de continuar, vale um definição do que são expressões regulares, provida pela Wikipédia:

Em ciência da computação, uma expressão regular (ou o estrangeirismo regex, abreviação do inglês regular expression) provê uma forma concisa e flexível de identificar cadeias de caracteres de interesse, como caracteres particulares, palavras ou padrões de caracteres. Expressões regulares são escritas numa linguagem formal que pode ser interpretada por um processador de expressão regular, um programa que ou serve um gerador de analisador sintático ou examina o texto e identifica partes que casam com a especificação dada.

Creio que isso esclarece (quase) tudo, mas vou colocar as coisas em termos mais práticos. A palavra regular provém do latim regula, -ae, que significa, ao mesmo tempo, regra e régua. Isso permite afirmar que as expressões regulares têm aplicação quando precisamos encontrar ou extrair ocorrências de caracteres de um texto, no qual ditos caracteres obedecem a determinados padrões (regra) e/ou se encontram em posições previsíveis (régua). E texto, nesse sentido, significa tanto um campo de número de telefone quanto uma cadeia com alguns milhares de caracteres.

Portanto, da próxima vez em que você precisar encontrar ou extrair determinadas substrings de um texto, e seu código começar a ficar mais complexo do que deveria, considere utilizar expressões regulares. Todas as linguagens importantes, hoje em dia, têm algum tipo de suporte a elas. É o tipo de conhecimento que vale o tempo em que se investe nele – uma hora gasta para aprendê-las pode poupar algumas de trabalho brabo 😛 .

Para aprender:

Normalizando nomes próprios com PHP

Salve, pessoal! Para compensar minha relativa inatividade nos últimos tempos, volto hoje com um post mais denso, que acredito e espero que seja útil a toda a comunidade #SouDev.

Vou tratar sobre normalização de nomes próprios. Norma… o quê? 😕

O problema

Algo que sempre achei horroroso em bancos de dados é a falta de padrão na capitalização (uso de letras maiúsculas e minúsculas) em nomes próprios – sejam de pessoas, logradouros ou localidades. Sobrinhos, geralmente, gravam no BD esses dados como foram coletados ou digitados, e programadores preguiçosos, no mais das vezes, limitam-se a aplicar um strtoupper() ou equivalente e entopem o cadastro com LETRAS MAIÚSCULAS. Na sinceridade, não sei qual das duas situações deixa o banco mais feio. O uso indiscriminado de letras maiúsculas, vale lembrar, cansa os olhos e dificulta a leitura após um certo tempo.

Já vi um caso em que a “saída” foi o uso de ucfirst() puro e simples. Menos mau, mas tão indolente quanto.

Fazer uma normalização, transformando “JOSÉ DA SILVA PEREIRA E SOUZA” em “José da Silva Pereira e Souza” não é uma tarefa difícil, desde que o desenvolvedor esteja atento a alguns detalhes.

A solução

Criei uma classe com um método estático em PHP (para não fugir ao paradigma da orientação a objetos) para propor minha solução. Expliquei, tanto quanto pude, todas as etapas nos comentários do código. Trata-se, em última instância, da implementação de um algoritmo relativamente simples, que não deve oferecer dificuldades para ser portado para outras linguagens. Se você utiliza PHP, de agora em diante aplique GUtils::normalizarNome($nome) e tenha um cadastro mais bonitinho e legível! 😛 Se não, implemente a ideia em sua linguagem favorita. 😉

<?php
/**
 * Classe contêiner para métodos estáticos de utilidades variadas
 *
 * @author goncin (goncin ARROBA gmail PONTO com)
 */
class GUtils {

  /**
   * Constantes definidas para melhor legibilidade do código. O prefixo NN_ indica que
   * seu uso está relacionado ao método público e estático normalizarNome().
   */
  const NN_PONTO = '\.';
  const NN_PONTO_ESPACO = '. ';
  const NN_ESPACO = ' ';
  const NN_REGEX_MULTIPLOS_ESPACOS = '\s+';
  const NN_REGEX_NUMERO_ROMANO =
    '^M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$';

   /**
   * Normaliza o nome próprio dado, aplicando a capitalização correta de acordo
   * com as regras e exceções definidas no código.
   * POR UMA DECISÃO DE PROJETO, FORAM UTILIZADAS FUNÇÕES MULTIBYTE (MB_) SEMPRE
   * QUE POSSÍVEL, PARA GARANTIR SUA USABILIDADE EM STRINGS UNICODE.
   * @param string $nome O nome a ser normalizado
   * @return string O nome devidamente normalizado
   */
  public static function normalizarNome($nome) {

    /*
     * A primeira tarefa da normalização é lidar com partes do nome que
     * porventura estejam abreviadas,considerando-se para tanto a existência de
     * pontos finais (p. ex. JOÃO A. DA SILVA, onde "A." é uma parte abreviada).
     * Dado que mais à frente dividiremos o nome em partes tomando em
     * consideração o caracter de espaço (" "), precisamos garantir que haja um
     * espaço após o ponto. Fazemos isso substituindo todas as ocorrências do
     * ponto por uma sequência de ponto e espaço.
     */
    $nome = mb_ereg_replace(self::NN_PONTO, self::NN_PONTO_ESPACO, $nome);

    /*
     * O procedimento anterior, ou mesmo a digitação errônea, podem ter
     * introduzido espaços múltiplos entre as partes do nome, o que é totalmente
     * indesejado. Para corrigir essa questão, utilizamos uma substituição
     * baseada em expressão regular, a qual trocará todas as ocorrências de
     * espaços múltiplos por espaços simples.
     */
    $nome = mb_ereg_replace(self::NN_REGEX_MULTIPLOS_ESPACOS, self::NN_ESPACO,
      $nome);

    /*
     * Isso feito, podemos fazer a capitalização "bruta", deixando cada parte do
     * nome com a primeira letra maiúscula e as demais minúsculas. Assim,
     * JOÃO DA SILVA => João Da Silva.
     */
    $nome = mb_convert_case($nome, MB_CASE_TITLE, mb_detect_encoding($nome));

    /*
     * Nesse ponto, dividimos o nome em partes, para trabalhar com cada uma
     * delas separadamente.
     */
    $partesNome = mb_split(self::NN_ESPACO, $nome);

    /*
     * A seguir, são definidas as exceções à regra de capitalização. Como
     * sabemos, alguns conectivos e preposições da língua portuguesa e de outras
     * línguas jamais são utilizadas com a primeira letra maiúscula.
     * Essa lista de exceções baseia-se na minha experiência pessoal, e pode ser
     * adaptada, expandida ou mesmo reduzida conforme as necessidades de cada
     * caso.
     */
    $excecoes = array(
      'de', 'di', 'do', 'da', 'dos', 'das', 'dello', 'della',
      'dalla', 'dal', 'del', 'e', 'em', 'na', 'no', 'nas', 'nos', 'van', 'von',
      'y'
    );

    for($i = 0; $i < count($partesNome); ++$i) {

      /*
       * Verificamos cada parte do nome contra a lista de exceções. Caso haja
       * correspondência, a parte do nome em questão é convertida para letras
       * minúsculas.
       */
      foreach($excecoes as $excecao)
        if(mb_strtolower($partesNome[$i]) == mb_strtolower($excecao))
          $partesNome[$i] = $excecao;

      /*
       * Uma situação rara em nomes de pessoas, mas bastante comum em nomes de
       * logradouros, é a presença de numerais romanos, os quais, como é sabido,
       * são utilizados em letras MAIÚSCULAS.
       * No site
       * http://htmlcoderhelper.com/how-do-you-match-only-valid-roman-numerals-with-a-regular-expression/,
       * encontrei uma expressão regular para a identificação dos ditos
       * numerais. Com isso, basta testar se há uma correspondência e, em caso
       * positivo, passar a parte do nome para MAIÚSCULAS. Assim, o que antes
       * era "Av. Papa João Xxiii" passa para "Av. Papa João XXIII".
       */
      if(mb_ereg_match(self::NN_REGEX_NUMERO_ROMANO,
        mb_strtoupper($partesNome[$i])))
        $partesNome[$i] = mb_strtoupper($partesNome[$i]);
    }

    /*
     * Finalmente, basta juntar novamente todas as partes do nome, colocando um
     * espaço entre elas.
     */
    return implode(self::NN_ESPACO, $partesNome);

  }

}
const NN_PONTO = ‘\.’;
const NN_PONTO_ESPACO = ‘. ‘;
const NN_ESPACO = ‘ ‘;
const NN_REGEX_MULTIPLOS_ESPACOS = ‘\s+’;
const NN_REGEX_NUMERO_ROMANO =
‘^M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$’;

Gerador da letra da musiquinha do elefante em PHP

Divirtam-se! 😛

<?php

echo "1 elefante incomoda muita gente\n";

for($i = 2; $i <= PHP_INT_MAX; ++$i) {

	echo "$i elefantes ";

	for($j = 0; $j < $i; ++$j)
		echo 'incomodam ';

	echo "muito mais\n";

	++$i;

	echo "$i elefantes incomodam muita gente\n";

}

Validando números de telefone com expressões regulares

A privatização do setor de telecomunicações, em meados da década de 90, universalizou o acesso dos brasileiros aos serviços de telefonia. De quebra, organizou a estrutura numérica dos terminais telefônicos: antes tínhamos códigos de área (códigos DDD) de três e quatro dígitos, e os números de telefone variavam entre de 5 a 7 dígitos. Atualmente, no país, todos os códigos de área têm dois dígitos e os números de telefone, oito. Essa estrutura uniforme torna possível validar números de telefone utilizando expressões regulares. Vejamos como.

Validando códigos de área (DDD)

Os código de área possíveis no Brasil vão de 10 a 99. Portanto, a expressão regular para validar códigos de área é

[1-9][0-9] (10)|([1-9][1-9])

UPDATE:  O Alexandre Taz, em seu comentário, alertou que o único DDD válido terminado em 0 é o 10, que será implementado em breve na Grande São Paulo, e observou também que prefixos iniciados com o número 6 também foram reservados para celulares. As expressões regulares foram alteradas para refletir essas alterações. Obrigado, Alexandre!

Trocando em miúdos: na primeira posição, aceitamos dígitos de 1 a 9 e, na segunda, dígitos de 0 a 9. Simples assim.

Se quisermos validar o código de área entre parênteses, como usualmente o código de área é representado, basta acrescentar:

\((10)|([1-9][1-9])\)

Uma vez que os sinais de abre e fecha parênteses porque esses sinais têm significado especial nas expressões regulares, é necessário antecedê-los com uma contrabarra para que sejam considerados literalmente.

Validando números de telefone (incluindo celulares)

Como dito anteriormente, os números de telefone (os de celular, inclusive) têm oito dígitos. O primeiro dígito do prefixo (os quatro primeiros números) pode variar de 2 a 9; números iniciados com 1 são reservados para telefônes de emergência, geralmente com 3 dígitos apenas (190 – polícia; 193 – bombeiros, etc.), e não serão validados. Os outro sete dígitos variam entre 0 e 9. Além disso, entre o quarto e o quinto dígito, vemos normalmente um hífen. De posse dessas informações, montamos seguinte expressão regular:

[2-9][0-9]{3}-[0-9]{4}

Explicando: o primeiro dígito (representado pelo primeiro grupo) pode variar de 2 a 9. A seguir, temos um grupo que pode variar entre 0 e 9 e se repete {3} vezes, seguido pelo hífen. O grupo final também pode variar entre 0 e 9 e se repete {4} vezes.

Validando números de celular

Pelas atuais normas da Anatel, os dígito inicial dos prefixos reservados para números de celular varia entre 7 6 e 9. Logo:

[6-9][0-9]{3}-[0-9]{4}

Foi necessário modificar apenas o primeiro grupo, relativamente à máscara anterior.

Colocando tudo junto

Para os casos em que o código de área será armazenado no mesmo campo que o número do telefone, a expressão regular é:

\((10)|([1-9][1-9])\) [2-9][0-9]{3}-[0-9]{4}

Trata-se simplesmente das máscaras já vistas, colocadas uma após a outra, e com um espaço entre elas para garantir a legibilidade.

Conclusão

Expressões regulares são ótimas para validar dados que obedecem a um padrão. Pesquise, busque, aprenda e melhore suas aplicações com elas. Praticamente todas as linguagens de programação oferecem suporte a elas. Consulte a documentação da sua linguagem para aprender como elas podem ser aplicadas 🙂 .

JetBrains PhpStorm: o novo garoto no quarteirão dos IDEs para PHP

Desde o ano passado (pelo menos), o pessoal da JetBrains vinha trabalhando num novo IDE para PHP. Cheguei a baixá-lo durante a fase de desenvolvimento, quando então o novo produto sequer tinha um nome definitivo ainda (era chamado simplesmente de “JetBrains Web IDE”), e se apresentava bastante promissor. A empresa parecia estar buscando o feedback dos desenvolvedores PHP para construir um produto específico para eles. Pois bem, o tempo se passou e finalmente foi lançada a primeira versão do IDE, agora batizado oficialmente como JetBrains PhpStorm.

Antes que me questionem: o JetBrains PhpStorm não é open source 😦 , mas tem um esquema de licenciamento bastante generoso, e sai na faixa para estudantes e desenvolvedores de projetos open source (!). E, mesmo que não se enquadre nas duas situações anteriores, adquirir uma licença dele sai mais barato que outras IDEs comerciais, como o Zend Studio, por exemplo. Seja como for, qualquer um tem 45 dias para testá-lo na condição de trial.

A pergunta, portanto, é outra: o que ele oferece em troca do preço da licença? É o que eu vou tentar desvendar de agora em diante.

Baixei a versão para Linux (uso o Ubuntu 10.04 LTS) e descompactei numa pasta sob a minha /home. Para iniciá-lo, há o script webide.sh sob  <pasta do JetBrains PhpStorm>/bin.

O JetBrains PhpStorm, assim como o Netbeans e o Eclipse, também roda sobre a plataforma Java, mas, ao contrário de seus “colegas”, pareceu-me muito mais leve para carregar. Afora o carregamento, confesso que primeira impressão não foi das melhores. O PhpStorm não assumiu o look and feel padrão do GNOME, e sua aparência padrão é horrível, para dizer o mínimo. Mas é bem fácil modificar isso: basta ir em File > Settings (aliás, um local um tanto quanto não-usual para as configurações; precisei consultar a Ajuda do produto para localizá-las), e, na guia IDE Settings > Appearance, alterar o Look and Feel para GTK+.

Resolvido o problema da aparência, criei um projeto, utilizando fontes já existentes. Eis o que obtive:

JetBrains PhpStorm com projeto carregado

JetBrains PhpStorm com projeto carregado

Isso feito, fui procurar como configurar o servidor remoto para o upload (deployment) da aplicação. Esperava eu encontrar essas configurações clicando com o botão secundário do mouse sobre o nome do projeto na árvore à esquerda, mas nada. Descobri que as configurações do projeto ficam também em File > Settings, e concluí em definitivo que, para se trabalhar com o PhpStorm, é necessário mudar o conceito de “onde ficam as coisas”. Deixando esses entraves conceituais à parte, pode-se configurar o deployment em File > Settings > Project Settings > Deployment > Options. E, aqui, uma ótima surpresa: além dos métodos FTP e SFTP, que são praxe, o PhpStorm permite também a criação de destinos em pastas montadas ou locais (!), para o caso de se ter acesso ao servidor Web pela rede local, o que é o meu caso. Esse tipo de configuração eu só havia visto antes no Adobe Dreamweaver.
Opções de destinos de "deployment" no PhpStorm

Opções de destinos de "deployment" no PhpStorm

Após o destino configurado, é possível enviar o arquivo para o servidor remoto clicando sobre o arquivo desejado na árvore do projeto e selecionando Upload to <nome do projeto>. Faltou, porém, uma opção de download a partir do servidor remoto, e a função Synchronize parece não ter sido ainda implementada: ao ser acionada, informa que o processo foi concluído com sucesso, mas nada acontece efetivamente.

A função de Code Completion é muito boa, retornando as sugestões quase que instantaneamente.

"Code completion": nem dá tempo de pensar

"Code completion": nem dá tempo de pensar

A impressão geral e inicial passada pelo JetBrains PhpStorm é a de um produto que está no caminho certo, mas que, apesar de estampar 1.0.2 como número de versão, demonstra ter ainda muito o que melhorar e evoluir. Nos próximos dias, continuarei explorando-o. Pelo que já vi de suas capacidades de depuração, a configuração parece ser a mais fácil dentre todos os IDEs que já analisei. Espero voltar em breve com um post específico sobre este tópico :).

Enquanto isso, se você desenvolve em PHP e puder fazê-lo, baixe também o JetBrains PhpStorm e dê um pouco de atenção a ele. Tudo leva a crer que valerá bastante a pena.

jQuery: evitando conflitos com outros “frameworks” Javascript

Post publicado originalmente em http://devfranca.ning.com/group/jquery/forum/topics/jquery-evitando-conflitos-com-1 em 7 de outubro de 2009

Que o jQuery é ótimo, todo mundo já sabe (ou pelo menos deveria saber). Um dos seus mais poderosos recursos é o atalho $, que, entre tantos outros usos, substitui com vantagem o famigerado document.getElementById().

Nada obstante, os problemas com o $ começam quando se usa o jQuery com outros frameworks, que também usam o cifrão para alguma coisa. Experimentei esse problema ao combinar jQuery com Scriptaculous.

Mas nem tudo está perdido. Há algumas saídas:

  1. Utilizar o método noConflict() do jQuery, atribuindo o resultado a uma variável, que então substituirá o cifrão. Isso deixa o cifrão livre para uso por outros frameworks. Esse método, pelo menos para mim, não deu certo (o jQuery continuou funcionando, mas o Scriptaculous não):
    jq = jQuery.noConflict();
    jq("#elemento").hide(); // Ao invés de $("#elemento").hide();
    
  2. Utilizar o próprio objeto jQuery no lugar do cifrão. Esse método “eu agarântio”, mas precisei fazer um “Encontrar/Substituir” todos os "$" por "jQuery" também no código fonte dos plugins (que, invariavelmente, usam o cifrão):
    jQuery("#elemento").hide(); // Ao invés de $("#elemento").hide();
    

Fica a dica! 🙂

Por que usar um “framework”

Todo desenvolvedor, não importa qual a linguagem em que trabalhe, certamente há de ter feito a si mesmo, pelo menos uma vez, a seguinte pergunta: devo ou não utilizar um framework? Ouso dizer que a resposta é SIM. E passo a detalhar as razões da minha assertiva.

Imagine, nos tempos pré-históricos, como nossos remotos ancestrais se viravam para sobreviver. Tinham que inventar suas próprias ferramentas, arranjar o que vestir. Até fazer fogo era algo extremamente trabalhoso. Felizmente, não vivemos mais naquela época. Mas alguns desenvolvedores ainda insistem em viver na Pré-História da programação, quando precisavam fazer quase tudo a partir do zero e “na unha”. Para defender sua postura em não adotar um framework, costumam lançar a questão “E se esse troço der pau, quem vai consertar?”.

Esse tipo de desenvolvedor é aquele que se apega de tal modo a seu “jeito de fazer as coisas”, ao ponto que todo código não escrito por ele mesmo lhe parece esotérico ou produto de seres alienígenas. Aqui vale um alerta: se você olha para o código-fonte de um framework e não entende nada do que está escrito ali, volte para casa zero e comece a estudar sua linguagem novamente!

O programador troglodita crê piamente que o valor do seu trabalho está no (mau) código que escreve, e não na solução que oferece para o problema do cliente. É aquele que foge o quanto pode das linguagens interpretadas, porque o aplicativo precisa do código-fonte para ser executado e “todo mundo pode ver e se apossar do que eu fiz”. É aquele cara que, nos idos do glorioso Clipper (uma linguagem semicompilada), morria de medo do Valkyrie, um utilitário capaz de traduzir o bytecode executável de volta a código-fonte.

Os melhores frameworks disponíveis na atualidade baseiam-se em padrões de desenvolvimento, giram em torno de uma grande e ativa comunidade e suas versões são testadas com rigor antes de serem disponibilizadas ao grande público. Tudo isso se traduz em qualidade de software, o que, certamente, as soluções do nosso companheiro troglodita não tem.

Adotar um framework significa, num primeiro momento, renúncia. Você abrirá mão do seu jeito de fazer as coisas para endossar o dele. Na maior parte das vezes, isso significa parar de contemplar o próprio umbigo e olhar ao redor, onde mais gente faz mais coisas de forma semelhante, e, portanto, tem problemas similares. Todos começam a falar a mesma língua, e fica mais fácil pedir ajuda e ajudar.

Muitos tomam o tempo que se gasta no aprendizado de um framework como perdido. Eu não veria desta forma. Antes, eu consideraria essas longas horas como auto-instrução e aperfeiçoamento profissional. O resultado, por certo, não aparecerá logo de início (para desespero dos apressados), mas terá reflexos num futuro melhor.

Obviamente, de nada adianta tentar aprender a trabalhar com um framework a toque de caixa para aplicá-lo naquele projeto que era para ontem. Aconselho que essa atividade de aprendizado se dê em paralelo ao desenvolvimento rotineiro, e, a menos que se tenha tempo disponível para erros e tentativas, não utilizar o framework em um projeto sério enquanto não entender seu funcionamento e se sentir minimamente confortável com ele.

Em suma, creio que a grande diferença entre utilizar ou não um framework é a mesma entre ter uma caixa de ferramentas de alta qualidade prontas para o uso, e já partir para o trabalho, ou perder tempo (re) inventando a roda, frequentemente de modo improvisado.

E você? Já escolheu seu framework preferido?

O Yii Framework e os “models” (modelos)

Dando seguimento à série de artigos sobre o Yii Framework, desejo compartilhar algumas reflexões acerca dos modelos (models) do padrão de desenvolvimento MVC e de como o Yii Framework implementa o conceito.

Para deixar as coisas mais claras, tomei a liberdade de traduzir a definição de modelo constante deste artigo da Wikipédia de língua inglesa (quase sempre mais completa que a versão lusófona):

O modelo é utilizado para gerenciar informações e notificar os observadores quando a informação é alterada. O modelo é a representação dos dados específica de um negócio, sobre os quais a aplicação trabalha. A lógica de negócio dá significado aos dados brutos (como, por exemplo, determinar se hoje é o dia do aniversário do usuário, ou os totais, impostos e valores de frete para itens de um carrinho de compras). Quando o estado do modelo se altera, este notifica suas visões [views] associadas, de forma que elas possam ser atualizadas.

Várias aplicações usam um mecanismo de armazenamento persistente, como um banco de dados, para guardar os dados. O padrão MVC não menciona especificamente a camada de acesso aos dados, porque se supõe que ela esteja sob o modelo ou encapsulada por este. Modelos não são objetos de acesso a dados; contudo, em aplicações muito simples, com pouca lógica de negócio, não há nenhuma distinção efetiva a se fazer. O Active Record é um padrão de desenvolvimento bem aceito e que une o código da lógica de negócios e o de acesso aos dados – um modelo que sabe como persistir a si mesmo.

Do que foi abordado acima, aprofundemos dois tópicos.

1. O modelo nem sempre está relacionado a um objeto de banco de dados

Isso pode soar estranho, mas basta pensar um pouco para dar razão à assertiva. O ciclo de vida de uma aplicação MVC é, basicamente, coletar dados por intermédio de um formulário (visão, view), filtrá-los segundo as regras de negócio (o que é feito no controlador – controller) e armazená-los para posterior consulta, usando os modelos (models) para tanto.

Há ocasiões, no entanto, em que os dados coletados não precisam ou não devem ser armazenados – eles são necessários apenas em uma etapa intermediária do processamento. Talvez o exemplo mais típico dessa situação sejam os formulários de login, nos quais coletamos um nome de usuário e uma senha, que servem à autenticação/autorização. Depois disso, o nome do usuário (ou seu código, dependendo da lógica implementada) é, no máximo, armazenado num cookie ou num objeto de sessão. Armazenar a senha seria um total contrassenso, por questões de segurança.

O que nos impede, então, de representar os dados de um formulário de login como um modelo? É exatamente isso que o Yii Framework faz. Em todo projeto iniciado com o auxílio da ferramenta de linha de comando yiic, é gerado um modelo chamado LoginForm (na pasta protected/models), cujo conteúdo é o seguinte:

class LoginForm extends CFormModel
{
	public $username;
	public $password;
	public $rememberMe;

	private $_identity;

	/**
	 * Declares the validation rules.
	 * The rules state that username and password are required,
	 * and password needs to be authenticated.
	 */
	public function rules()
	{
		return array(
			// username and password are required
			array('username, password', 'required'),
			// rememberMe needs to be a boolean
			array('rememberMe', 'boolean'),
			// password needs to be authenticated
			array('password', 'authenticate', 'skipOnError'=>true),
		);
	}

	/**
	 * Declares attribute labels.
	 */
	public function attributeLabels()
	{
		return array(
			'rememberMe'=>'Remember me next time',
		);
	}

	/**
	 * Authenticates the password.
	 * This is the 'authenticate' validator as declared in rules().
	 */
	public function authenticate($attribute,$params)
	{
		$this->_identity=new UserIdentity($this->username,$this->password);
		if(!$this->_identity->authenticate())
			$this->addError('password','Incorrect username or password.');
	}

	/**
	 * Logs in the user using the given username and password in the model.
	 * @return boolean whether login is successful
	 */
	public function login()
	{
		if($this->_identity===null)
		{
			$this->_identity=new UserIdentity($this->username,$this->password);
			$this->_identity->authenticate();
		}
		if($this->_identity->errorCode===UserIdentity::ERROR_NONE)
		{
			$duration=$this->rememberMe ? 3600*24*30 : 0; // 30 days
			Yii::app()->user->login($this->_identity,$duration);
			return true;
		}
		else
			return false;
	}
}

A classe CFormModel, na hierarquia do Yii Framework, descende de CModel. Estão ali alguns métodos que costumamos ver nos posts anteriores, como o rules(), que estabelece as regras de validação para os dados, e o attributeLabels(), no qual podemos definir os nomes dos campos na linguagem natural do usuário.

Os dados de login são colhidos e processados, mas nunca armazenados em banco de dados – mesmo porque nem a classe CFormModel, nem sua ancestral, CModel, implementam um método save(). Pelo “jeitão de ser” do Yii Framework, CFormModel deve ser usado toda vez que os dados do formulário não serão armazenados (ao menos diretamente) num banco de dados. Para o trabalho com banco de dados, utilizamos o CActiveRecord.

2. O Active Record reúne em si regras de negócio e código de acesso a dados

O quão chocante lhe parece esta afirmação? Trata-se, é verdade, de uma quebra do paradigma MVC, que preconiza que as regras de negócio devem residir unicamente no controlador (controller). Ponderemos, porém: validação de dados é, em última análise, regra de negócio NOTA MENTAL: escrever um post sobre validação de dados no Yii Framework. E, se esses dados foram ou serão armazenados em banco de dados, a validação precisa obedecer, necessariamente, a definição da estrutura do BD, bem como as características e limitações do SGBD correspondente.

Logo, faz todo o sentido deixar que o próprio modelo verifique se a informação a ser armazenada num campo definido como VARCHAR(100) não ultrapassa esse comprimento. Podemos chamar isso, grosso modo, de forma. O controlador poderia ter-se encarregado de checar essa mesma informação quanto ao aspecto do conteúdo: é um endereço existente? É um nome de pessoa válido? É um município dentro da área de representação da empresa?

Por isso, e para poupar o precioso tempo do desenvolvedor, é que o Yii Framework mantém as regras de validação de dados, quanto à sua forma, no modelo (clique aqui para ver o exemplo de um código de modelo gerado a partir de um objeto de banco de dados), refletindo, sempre que possível, as regras já definidas no BD (tais quais campos requeridos, comprimento máximo, tipo de valor – numérico, alfanumérico, etc.). Tudo isso é implementado estendendo-se a classe CActiveRecord que, por seu turno, também estende CModel.

Concluindo…

O Yii Framework nos leva a repensar o conceito de modelo, desprendendo-o da correlação, julgada muitas vezes  necessária, com um objeto de banco de dados. Com isso, as possibilidades de uso dos modelos ampliam-se, como é o caso do formulário de login anteriormente citado.

O framework também implementa de forma elegante o padrão de desenvolvimento Active Record, encarregando os modelos gerados a partir de estruturas de bancos de dados da validação formal das informações, poupando o desenvolvedor de escrever código para isso 8) .

Para saber mais

  • The Definitive Guide to Yii (em português)
%d blogueiros gostam disto: