Cannonball 0.4
A versão 0.4 do Cannonball está disponível para download. Além de várias refatorações de código, a nova versão conta com o retorno do painél administrativo e de um rascunho para o sistema de autenticação e autorização, ainda limitado.
Apesar das limitações do mecanismo de autenticação, o foco dos trabalhos para a pŕoxima versão é no mecanismo de configurações individuais de cada recurso, permitindo que cada aplicação rodando em cima do Cannonball altere livremente a maneira como cada recurso é exibido e processado.
Após isto as funcionalidades previstas para o Cannonball passar de alfa para beta estarão implementadas; ficará pendente a refatoração (e possível redefinição) do mecanismo de autenticação e do painél administrativo, que apesar de funcional, ainda se parece muito com um “quebra galho”.
O projeto está disponível no SourceForge em http://sourceforge.net/projects/getdown/.
Cannonball 0.3.5 – novos conceitos para CMS e aplicações web
A versão 0.3.5 do Cannonball foi lançada. As mudanças desde o último lançamento foram enormes – o projeto foi totalmente refatorado, e o framework central (que nós já estamos chamando de Kernel) está cada vez mais isolado do resto da aplicação. Estou chegando perto de começar de fato o desenvolvimento do CMS (até então o foco do trabalho tem sido o framework – o sistema de Wiki, padrão na instalação do Cannonball, é utilizado apenas como prova de conceito).
Cannonball é um sistema de gerenciamento de conteúdo e um framework para desenvolvimento de aplicações web. Na verdade, o sistema de gerenciamento de conteúdo é (ou está se tornando) apenas um conjunto de aplicações independentes rodando em cima do Kernel do Cannonball, que por sí só não tem noção de como apresentar conteúdos ou lidar com ações complexas – tudo o que ele faz é administrar recursos e as aplicações que lidam com estes recursos.
O Cannonball implementa uma visão razoavelmente diferente a respeito do gerenciamento de informação na web, tratando cada recurso (URL) isoladamente, funcionando de uma maneira que superficialmente (ou pelo menos filosoficamente) nos lembra um sistema de arquivos (e cada vez mais um sistema operacional). Estou desenvolvendo um artigo a respeito dos princípios aplicados ao Cannonball para explicar melhor esta visão a respeito do tratamento de informação.
Resumidamente, o Cannonball trata os recursos como uma árvore hierárquica, similar a pastas num sistema de arquivos. Cada pasta pode ter diversos conteúdos e tem associada a si uma aplicação independente do kernel, que é a responsável por lidar com requests para este recurso. Desta forma é possível criar e alterar facilmente a estrutura de qualquer website/sistema, (simples como mover pastas no seu computador) além de simplificar o desenvolvimento de novas funcionalidades. Esta “cara” de sistema operacional é o grande conceito do Cannonball.
Outro detalhe importante é a noção que o sistema tem de conteúdo. Conteúdos podem se relacionar livremente com outros conteúdos. Por exemplo: um post de blog e um comentário deste post são, para o kernel, dois conteúdos de igual valor. Ao invés de marcar o comentário como um conteúdo “diferente”, ele cria o comentário exatamente como qualquer outro conteúdo, e depois define que conteudo A se relaciona como comentário com o conteúdo B. Esta abstração é um dos pontos chaves do sistema, permitindo que sistemas razoavelmente complexos sejam definidos não com criação de novas tabelas ou políticas totalmente diferentes para tratamento de informação – ao invés disso, cada aplicação pode simplesmente relacionar os “conteúdos” da maneira como for necessário, e tratar estes relacionamentos internamente, aumentando em muito a concisão do sistema e das informações que ele administra.
A versão atual ainda é alfa. Alguns detalhes importantes ainda precisam ser definidos e estamos trabalhando nisto, prevendo que o software deve passar de alfa para beta na versão 0.4. No entanto, algumas mudanças já foram feitas para facilitar a instalação – agora é possível instalar o Cannonball em subdiretórios, entre outras coisas. Vale tentar!
Fica a URL do projeto no SourceForge: http://sourceforge.net/projects/getdown
Cannonball 0.3.1
A versão 0.3.1 do Cannonball está disponível para download. A nova versão conta com algumas pequenas correções e uma nova funcionalidade: criar a estrutura do web site a partir de um arquivo do FreeMind. O Cannonball, ainda em estado beta, está disponível no SourceForge e é desenvolvido em cima do Detox MVC Engine, um framework MVC minimalista desenvolvido em PHP.
Detox MVC Engine 0.99 disponível para download
A versão 0.99 do Detox, um framework MVC minimalista implementado em PHP, está disponível para download. Atualmente estou trabalhando na documentação do projeto (melhorando a existente e fazendo uma versão em português) e corrigindo alguns detalhes de implementação para o lançamento da versão 1.0. As funcionalidades, no entanto, devem continuar as mesmas disponíveis na 0.99.
O trabalho de documentação deve incluir também o desenvolvimento de alguns exemplos de utilização prática do Detox e soluções para problemas comuns no desenvolvimento de aplicações para Web, como mapeamento de URLs e desenvolvimento de camadas de persistência de dados.
Web Services com REST e PHP, parte 2
Agora que você já viu que pra implementar um web service RESTful você não precisa de nada além da sua boa vontade, podemos nos aprofundar no assunto sem grandes riscos. Fiz questão de iniciar este série com um texto focado na parte programática, deixando de lado boa parte da filosofia REST, uma abordagem meio reversa, propositalmente. REST é um conjunto grande de conceitos que engloba a adoção de todo um ponto de vista diferente em relação a Web (se você anda seguindo a cartilha do bom desenvolvedor direitinho, muita coisa nem vai ser tão nova assim), e começar por esta parte pode fazer parecer que as coisas são muito mais complicadas do que são realmente.
REST, como já mencionei, não é um protocolo ou uma especificação, e sim um conjunto de princípios. A idéia é a seguinte: tudo o que existe na rede é visto como um recurso, que possui estados, e pode ser acessado e manipulado por meio de um endereço único e universal. Isto soa abstrato demais, por isto quis colocar o código primeiro (no final deste artigo você vai entender por quê o exemplo do primeiro artigo não é uma aplicação RESTful em seu sentido mais “puro”, apesar de utilizar o mesmo mecanismo de acesso).
Se na primeira parte nos implementamos um código “estilo REST”, mas sem constituir uma aplicação RESTful no seu estado mais puro, agora nós vamos discutir um exemplo de aplicaçao seguindo uma arquitetura totalmente REST, porém contornando a aplicação de métodos PUT e DELETE, para sua (e minha) conveniência; no entanto, deixei comentários nas partes onde eu contornei o uso destes métodos, indicando uma possível implementação que os utilize.
O exemplo é o seguinte: uma loja virtual. Vamos nos concentrar exclusivamente na que diz respeito aos produtos. Todos os resultados das operações abaixo (o que é enviado para o navegador do usuário, ou aplicação que estiver acessando sua aplicação) é feito sob a forma de XML e Headers HTTP indicando o status do recurso acessado. Uma arquitetural RESTful iria resultar em uma aplicação web com uma interface mais ou menos assim:
dominio.com/produtos
- Ao receber um request do tipo POST, um produto é criado no banco de dados da loja;
- Ao receber um request do tipo GET, sem parametros, os produtos da loja são listados (a ordem ou quantidade depende da lógica de negócio do lojista);
dominio.com/produtos/mesa-de-centro
- Exemplo de um request do tipo GET com parametro: o nome do produto. Pressupoe-se que este os nomes são únicos. URLs como dominio.com/produtos/?p=mesa-de-centro devem ser evitadas; use mod_rewrite ou qualquer outra coisa para tratar os requests e permitir URLs inteligentes;
- Ao receber um request do tipo POST, o produto é atualizado com os dados enviados. Sinta-se livre para pensar num modelo de autenticação, não é tão difícil assim. Este é um dos contornos para ausência do método PUT; na verdade, o correto seria que um request do tipo PUT para esta URL realizasse a atualização do conteúdo ou a criação do mesmo no endereço especificado, caso não exista nada ali e o conteúdo possa ser criado.
dominio.com/produtos/mesa-de-centro/delete
- Ao receber um input do tipo POST com alguma informação de autenticação, caso a autenticação ocorra, exclui o produto do banco de dados da loja. O mais correto seria realizar esta operação através de um request do tipo DELETE para dominio.com/produtos/mesa-de-centro; esta é uma maneira de contornar isto, já que DELETE não é exatamente o método mais popular do HTTP.
Agora você tem uma interface RESTful para manipular os produtos da sua loja. Parece bobagem? Não vale a pena? E se você pensar que, através do acesso a dominio.com/produtos/mesa-de-centro, quem fez o request recebe um XML com as informações do produto e um link para sua loja, e nada mais, o que possibilita que qualquer um adicione links para seus produtos em seus sites, com a descrição dos produtos? E que tal se com uma aplicação simples no seu celular você pudesse manipular os produtos na sua loja, sem complicação nenhuma? Estes são apenas alguns exemplos do que pode ser facilmente alcançado com uma arquitetura REST.
As coisas ficam ainda melhores se você pensar que, identificando o cliente que fez o request (coisa trivial), você pode decidir se vai retornar simplesmente um XML com os dados necessários ou a interface completa da sua loja (em XHTML, por exemplo) com menus e tudo mais, pronta para ser exibida num navegador. As possibilidades são enormes.
“Mas e o PHP, Rafael? No título você falou que tinha PHP!”. Tudo bem. Não vou escrever aqui o código para o exemplo acima, nem sonhe com isto; no entanto, vão alguns toques de como fazer as coisas que eu mencionei:
Identificar o user agent
As informações sobre o autor do request (uma string) ficam guardadas aqui:
$_SERVER['HTTP_USER_AGENT']
Para testar:
echo $_SERVER['HTTP_USER_AGENT'];
Retornar um XML com Header 200/OK (operação foi um sucesso, dados retornados)
header('Content-Type: text/xml');
echo '<?xml version="1.0" encoding="UTF-8"?>'
echo '<produto>';
echo '<nome>Mesa de centro</nome>';
echo '<link>http://meudominio.com/mesa-de-centro</link>';
echo '</produto>';
Já é o suficiente. O content-type do header é alterado para text/xml, permitindo que o conteúdo seja corretamente interpretado; o header 200/OK não precisa ser gerado manualmente, já que é o header padrão quando tudo corre bem. Gerar os valores dinamicamente é com você e sua paciência para trabalhar com bancos de dados.
Nos outros casos, quando ocorrer algum erro ou alguma situação diferente, basta definir o status no header com o código correspondente; a W3C (é claro) tem todas as definições que você precisa:
http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
E definir um header é algo tão simples como:
header('HTTP/1.1 304 Not Modified');
Se quiser, pode usar echo para exibir alguma mensagem indicando o que aconteceu, mas não é recomendável. O header deve prover informação suficiente sobre o status (dê uma olhada na quantidade de headers no link mencionado acima), e deve ser interpretado por quem for acessar seu Web Service. Nada de repetir informação!
Agora é com você. Já deu pra perceber que implementar aplicações RESTful não é nada de outro mundo e não requer nada além do que você já tem; também ficou claro que a arquitetura da aplicação, o grande ponto do REST, resulta numa interface extremamente simples e funcional para acessar sua aplicação num abiente distribuído.
Web Services com REST e PHP
*Notei que a parte 1 deste artigo (esta que você está lendo) tem tido muito mais visualizações do que a parte 2, o que me deixou um pouco receoso; isto é uma introdução programática ao REST, uma abordagem apenas focada em código, ignorando boa parte dos conceitos. Isto é intencional, pois queria mostrar que do ponto de vista da escrita de código não é necessário nada absurdamente diferente do que você já faz; mas se você está lendo este artigo como um introdução ao REST eu recomendo que leia também a parte 2, na qual eu tentei abordar REST de forma mais conceitual, para não sair por aí falando e fazendo besteira!
REST (Transferência de Estado Representacional, ou Representational State Transfer) vem ganhando cada vez mais espaço entre os desenvolvedores, e motivos não faltam: simplicidade, objetividade e mais várias outras vantagens que você vai acabar descobrindo por si mesmo. Até aí, tudo bem; novas tecnologias geralmente aparecem visando exatamente estas coisas. A genialidade do REST é oferecer tudo isto ao preço de… nada. Tudo bem, quase nada.
REST é um paradigma arquitetural, não uma especificação de linguagem ou de protocolo. Pra desenvolver aplicações RESTful você não precisa ler nenhuma das muito organizadas, porém nada objetivas especificações da W3C, nem aprender outra linguagem ou qualquer coisa parecida. REST se baseia nos mesmos métodos GET e POST que você sempre usou, e a parte técnica da coisa para por aí*.
Se você estranhou quando eu falei que “a parte técnica da coisa para por aí”, é isso mesmo que você leu: o resto é conceito e filosofia e, como qualquer coisa envolvendo tecnologia, vai acabar esbarrando em outras tecnologias. No entanto, este artigo visa uma introdução programática ao REST, e não vamos discutir absolutamente nada disto aqui.
Já que a parte técnica é tão pequena, vamos logo pra ela. A parte que mais consumiu meu tempo neste artigo foi decidir sobre o quê usar como primeiro exemplo. Não queria nada que envolvesse banco de dados, nem nenhuma estrutura complexa de diretórios, nem arquivos de configuração de servidor, nem envolvesse mais do que dois arquivos: o cliente e o webservice em questão. Pensei na seguinte função:
function soma($numero1,$numero2) { return $numero1+$numero2; }
Mais claro impossível; esta função recebe dois valores e retorna a soma deles. Só isso. Esta vai ser o serviço oferecido: somar dois valores. Agora, vamos implementar isto de um jeito RESTful. O acesso vai ser feito por método GET, e os parâmetros vão se chamar n1 e n2 (que vão ser usados como os dois parametros da função soma). O conceito chave do REST é que tudo deve ser um recurso com um endereço único, e a manipulação deste recurso acontece pela troca de informações através de um protocolo.
No nosso caso o protocolo é o HTTP, o endereço único é a URI do webservice e as informações são os parametros enviados via GET. Resumidamente, isto significa que para utilizar o web service para saber o resultado da soma de 2 + 3, basta acessar a seguinte URL**: seudominio.com/soma.php?n1=2&n2=3 E o web service (o arquivo soma.php) seria assim:
function soma($numero1,$numero2) { return $numero1+$numero2; } echo soma($_GET['n1'],$_GET['n2']);
Ao acessar a URL, o resultado da operação (neste caso, 5) é exibida no navegador. CERTO. Se você está lendo este artigo como iniciação ao REST, existem grandes chances de você estar pensando algo como “ou este cara está tentando me enganar ou alguém está tentando enganar todo mundo”. Respire fundo e analise bem a situação. Pense sobre os web services que você já desenvolveu, caso tenha desenvolvido, e no que eles faziam. Eu avisei que REST não envolvia nada de novo, é só uma maneira diferente de abordar as coisas.
Vamos implementar o cliente de um jeito diferente; ao invés de web, vamos fazer uma aplicação para rodar na linha de comando. O código é simples:
$resultado = file_get_contents('http://sdc/soma.php?n1='.$argv[1].'&n2='.$argv[2]); echo $resultado;
Pronto! O método file_get_contents recebe um caminho de arquivo e retorna seu conteudo em uma string. No nosso caso, o “arquivo” é qualquer coisa que o nosso service retornar. Salve o trecho de código acima num arquivo chamado cliente.php e acesse agora via linha de comando:
php cliente.php 2 3
O resultado será:
5
Sendo que o processamento da soma aconteceu remotamente, no servidor, através do seu web service RESTful. Até aí, tudo bem. Mas não queremos viver num mundo onde os webservices se limitam a simplesmente retornar a soma de dois valores; se é pra ser assim, que pelo menos eles retornem isto num XML. Vamos alterar nosso código:
function soma($numero1,$numero2) { return $numero1+$numero2; } header('Content-Type: text/xml'); echo '<?xml version="1.0" encoding="iso-8859-1"?>'; echo '<resultado>'.soma($_GET['n1'],$_GET['n2']).'</resultado>';
Pronto. O resto agora fica a cargo da sua imaginação; não é difícil imaginar como extender isto para acessar bancos de dados e consequentemente realizar ações de entrada e persistência de dados (via POST) e recuperaçao de dados persistentes (via GET) ao invés de somente processamento de dados. Este artigo já ficou longo demais, e já cumpriu seu objetivo de dar uma visão geral sobre REST sob uma perspectiva prática.
Vale lembrar que o assunto é extenso, e merece ser estudado a fundo principalmente no que tange a arquitetura do seu sistema (afinal, REST é um estilo de arquitetura) e disponibilização de recursos.
* REST utiliza também os métodos PUT e DELETE, mas vamos ignorá-los aqui impiedosamente (se é que você já não os está ignorando a vida toda). Vários servidores não implementam esta parte do protocolo HTTP, e honestamente, não vejo porque se incomodar com isto, pelo menos por enquanto.
** Como eu disse, estou tentando simplificar as coisas; existem padrões de URL que vão de acordo com a filosofia de arquitetura de aplicações REST, e que merecem destaque em outros artigos. Neste caso, seria mais correto seria disponibilizar o serviço através de uma URL como “seudominio.com/soma/2+3″, mas falar sobre tratamento de URIs não faz parte do escopo deste artigo.