Como retirar o index.php das urls do Code Igniter

Acho que não comentei por aqui ainda, mas tenho usado bastante o Code Igniter ultimamemente junto com o Guilherme num projeto pessoal nosso. O Code Igniter é um framework PHP para implementação MVC do seu projeto.
Em breve pretendo fazer um post completo sobre ele e como tenho utilizado, por enquanto vou dar uma dica rápida de como resolver uma questão que envolve o CI: quando você cria URLs personalizadas nele, por adrão você precisa montá-las da seguinte forma:

http://[url base]/index.php/[nome do controller]/[método]

Para retirar esse index.php da url, se você estiver usando (o webserver) Apache, faça o seguinte: crie um arquivo .htaccess na raíz da instalação e insira:

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [L]

Abraços!

Lendo um RSS e exibindo-o na tela – por PHP

Estou voltando á programação em PHP depois de muitos meses sem fazer muitas coisas. Vou mostrar aqui como ler um RSS (2.0) e gerar um html a partir dele, usando orientação a objetos. Para ajudar na leitura, vale a pena comentar que eu usei o termo Feed para o arquivo XML lido e FeedEntry cada entrada (num RSS, abstraímos isso normalmente para uma notícia ou matéria).

Criei três arquivos:

  • uma classe que segue o conceito de JavaBean para armazenar os dados de cada FeedEntry
  • uma classe que funcionaria como um service: lê o XML e cria a partir dele uma lista de FeedEntries
  • um arquivo PHP que instancia a classe de serviço e gera adequadamente o código html

 O código da classe FeedEntry.php

 

<?php
class FeedEntry {
    private $title;
    private $description;
    private $pubDate;
    private $link;
   
    function __construct($title, $description, $pubDate, $link) {
        $this->title = $title;
        $this->description = $description;
        $this->pubDate = date("d-M-Y", strtotime($pubDate));
        $this->link = $link;
    }
   
    public function getTitle() {
        return $this->title;
    }
   
    public function getDescription() {
        return $this->description;
    }
   
    public function getPubDate() {
        return $this->pubDate;
    }
   
    public function getLink() {
        return $this->link;
    }
}
?>

 

Eis o código da classe de serviço (FeedService.php), devidamente comentado:

 

<?php
require("FeedEntry.php");
class FeedService {
    private $file;
    private $xml;
    private $doc;
    private $feedEntries = array();
   
    /* construtor: recebe a URL do feed e instancia objeto DOMDocument */
    function __construct($feedUrl) {
        $this->file = $feedUrl;
        $this->doc = new DOMDocument();
    }
   
    /**
    * carrega o arquivo XML do feed
    *
    */
    private function readXML() {       
        $this->doc->load($this->file);
    }
   
    /**
    * lê os nós
    */
    private function readNodes() {
       
        /**
        * percorre o objeto do tipo DOMDocument através do método getElementsByTagName()
        * cria um objeto do tipo FeedEntry e adiciona no array
        *
        * cada feed é declarado no RSS com uma tag <item> e tem:
        * uma tag <title> para o título do feed
        * uma tag <descritpion> para a descrição do feed
        * uma tag <pubDate> para a data de publicação do feed
        * uma tag <link> para o link do feed
        */
        $dataset = $this->doc->getElementsByTagName("item");
        foreach($dataset as $feed) {
            $feedEntry = new FeedEntry($feed->getElementsByTagName("title")->item(0)->nodeValue,
                                       $feed->getElementsByTagName("description")->item(0)->nodeValue,
                                       $feed->getElementsByTagName("pubDate")->item(0)->nodeValue,
                                       $feed->getElementsByTagName("link")->item(0)->nodeValue);
            array_push($this->feedEntries, $feedEntry);
        }
    }
   
    /**
    * chama métodos que lê o XML, percorre os nós transformando-os em objetos FeedEntry e retorna a lista
    * desses objetos
    */
    public function consume() {
        $this->readXML();
        $this->readNodes();
        return $this->feedEntries;
    }
}
?>

 

E, finalizando, o código da página PHP (chamei de consume.php) que vai consumir esse RSS:

 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Exemplo - consumo de um RSS</title>
</head>
<body>
<h1>Exemplo de uso da classe FeedService</h1>
<dl>
<?php
    //inclui Service que faz a manipulação de Feed
    require("FeedService.php");
    //instancia objeto do tipo
    $feedService = new FeedService("http://feeds.feedburner.com/AndAfter");
    $feedEntries = $feedService->consume(); //método do service retorna um array de objetos FeedEntry
    foreach($feedEntries as $feedEntry) { //percorre a lista de feeds, retornando a cada iteração objetos do tipo FeedEntry
?>
    <dt><a href="<?php echo $feedEntry->getLink(); ?>"><?php echo $feedEntry->getTitle() . " (" . $feedEntry->getPubDate() . " )"; ?></a></dt>
    <dd><?php echo $feedEntry->getDescription(); ?></dd>
<?php
    }
?>
</dl>
</body>
</html>
 

 

Tentei separar um pouco as canadas, mas isso nem de perto chega no conceito de MVC. Mas é um começo, já criando um bean e uma classe específica para acessar dados – note que não há mistura no FeedService de marcação html, ou seja, essa classe pode ser utilizada normalmente em qualquer outro projeto.

Para facilitar, coloquei os 3 arquivos para baixar: http://www.chrisb.com.br/files/consumeFeed.zip
É só descompactar no mesmo diretório e acessar, que funcionará.

Velocity – linguagem de templates

Quando comecei a trabalhar na empresa em que estou até hoje, 4 anos atrás, fui "jogado" no mundo de aplicações java para web. Antes, só tinha mexido de verdade com PHP. E de cara comecei a mexer com o que, hoje em dia, é muito comum: templates.

Existem inúmeras opções de frameworks que usam templates, para as mais variadas linguagens (inclusive foi lançado um, em PHP, que parece ser bem bacana, o Spaghetti).
Em java, muito se usa JSP. Mas nem de longe são os mais bacanas: se você quer implementar uma aplicação MVC mesmo, deve usar o JSTL ou Velocity.

E Velocity é com o que eu trabalho atualmente. Ela é ótima para uma aplicação de grande porte, que usa MVC: você escreve seu XHTML normalmente e, depois, utiliza os objetos que a camada de negócios te dá. Ou seja, você coloca apenas lógica de interface na interface. E a lógica de negócios fica na camada de negócios. E não tem como misturar uma coisa com a outra (ok, até tem, mas vai dar tanto trabalho e é tão mais difícil de fazer isso quando comparado com JSP, que desestimula qualquer POG…).

Vamos falar um pouco, então, dele:




Velocity

Conceito

É um engine baseado em java para a construção de templates. Um template velocity é um documento que permite a escrita de html com a inserção de lógica usando objetos do Java na sua inteligência, aplicando o conceito de MVC para separar a camada de negócios da camada de apresentação.

Tipos

Sendo baseado em Java, o código Velocity tem os mesmos tipos de objetos do Java, e podem ser usados todos os métodos dos objetos Java. Objetos são sempre chamados através do identificador $
Por exemplo:
$nome ou $quantidade
Para definir um valor a um objeto, é usada a diretiva #set(
objeto = valor)
Não é necessário definir o tipo do objeto. O engine do Velocity se encarrega de definir a qual tipo ele pertence.
Por exemplo: #set($nome = "Eduardo") ou #set($quantidade = 5)

Arrays

Para criar um array – um objeto que contêm uma lista de outros objetos, há duas formas:
#set($meu_array = ["a", "b", "c", "d", "e"]) ##instancia-se o objeto e já passa o valor a ele
ou

#set($meu_array = []) ##instancia um objeto e cria uma lista vazia
##adiciona item a item os objetos da lista, usando o método add() da classe Array
#set($foo = $meu_array.add("a"))
#set($foo = $meu_array.add("b"))
#set($foo = $meu_array.add("c"))
#set($foo = $meu_array.add("d"))
#set($foo = $meu_array.add("e"))
##como o método add() tem um valor de retorno, jogamos o valor do método em uma variável qualquer, $foo, para que esse valor não seja printado na tela

Tomada de decisão

Há um tipo de estrutura de decisão no Velocity, que é definida pela seguinte sintaxe:
#if(condição)

#elseif(condição)

#else

#end

Nesse caso, apenas a diretiva #if(condição) e #end são obrigatórios; as demais ficam por conta da necessidade da implementação. A lógica é a mesma de qualquer estrutura de outras linguagens. Segue um exemplo completo:
#if($c<5)
##só entra quando $c for menor do que cinco
#elseif($c==5)
##só entra quando $c for igual a c
#else
##entre nos demais casos
#end

Laço de repetição

Há um tipo de estrutura para laço de peteição no Velocity – ou seja, como percorrer um Array (lista), que é definida pela seguinte sintaxe:
#foreach($iter in $lista)

#end

Usando aquele Array criado no item Arrays, segue um exemplo completo da utilização:
#set($meu_array = ["a", "b", "c", "d", "e"])
#foreach($letra in $meu_array)
$letra ##printa na tela a letra
#end

É possível também criar uma repetição de n vezes. Por exemplo, no código abaixo serão feitas 3 iterações (de 1 até 3):
#foreach($c in [1..3])
$c
#end

Macro
Uma macro pode ter seu conceito simplificado para
função carregada em memória. Deve ser utilizada quando um trecho de código é repetido várias vezes em diversos locais do seu código. Por ser carregada em memória e não interpretada em tempo de execução, a performance é maior.
A sintaxe para criação e posterior acesso a ela segue o seguinte padrão:
#macro(meu_nome $param1 $param2 .. $paramn)
##lógica da macro
#end
##chama a macro
#meu_nome($p1 $p2 .. $pn)

Vale ressaltar que n é a quantidade de parâmetros que a macro recebe. Se ela não receber nenhum, é chamada a macro com os parênteses em branco.

Referência: User Guide