O que é?
PhalconPHP é um framework full stack php escrito em C puro e compilado na forma de uma extensão do php. Isso significa que todos os arquivos do framework foram convertidos em código nativo de cada sistema operacional, traduzindo: Performance!
Performance
O framework phalcon ganha disparado dos frameworks convencionais. Um exemplo dos mais conhecidos por sua velocidade é o CodeIgniter que é superado pelo Phalcon em 8x. Aos detalhes!
Benchmark Phalcon PHP vs. Frameworks convencionais?
O teste é feito com uma instalação limpa dos frameworks, com o modo debug desligado e apenas respondendo a um request que gera uma página com os dizeres: “Hello World”.
Presentes deste teste:
- Yii(YII_DEBUG=false) (yii-1.1.13)
- Symphony(2.0.11)
- Zend Framework(1.11.11)
- Kohana(3.2.0)
- FuelPHP(1.2.1)
- CakePHP(2.1.3)
- Laravel(3.2.5)
- CodeIgniter(2.1.0)
Comparação 1 - Requests por segundo.
O gráfico abaixo mostra a comparação de requests por segundo que cada framework atende.
Figura 1: Requests por segundo
Em primeiro lugar, Phalcon com 2535,82 requests por segundo, o segundo colocado é o CodeIgniter com 1059,05 requests por segundo.
Comparação 2 - Tempo de resposta.
Figura 2: Tempo de resposta
Novamente o Phalcon supera todos os frameworks testados, com o tempo de resposta de 394 ms enquanto o segundo lugar novamente com CodeIgniter com 944 ms.
Para mais detalhes sobre o Benchmark, visite: http://docs.phalconphp.com/en/latest/reference/benchmark/hello-world.html
E outros Frameworks compilados?
Existem outros frameworks compilados como extensão, porque escolher o Phalcon? Essa é uma pergunta sutil. Ao pesquisar pelo framework mais rápido, você irá encontrar o YAF. Então porque o Phalcon?
Simples, o YAF apesar de vencer o phalcon no benchmark de hello world, não é um fullstack. Explicando melhor, se você precisar de algum recurso mais sofisticado você precisará incluí-lo, fazendo a vantagem de ter um framework compilado desaparecer.
Componentes
Foi comentado que o Phalcon é um framework full stack mas nada foi dito sobre arquitetura MVC. Você pode trabalhar com ele tanto no modo application que te oferece um MVC completo e no modo micro que não carrega nada do framework e te permite ir carregando as classes na medida que você for utilizando.
Principais componentes
FrontEnd
- RazorTemplate Engine: Uma engine de templates com sistema de Layouts Master, Views, Partials e Herança.
- Cache: Autoexplicativo, os layouts, views e partials são compilados em cache.
- Tags: O nome também entrega, as Tags são funções para gerar html. Dois exemplos para mostrar o poder:
{{ javascript_include("javascript/jquery.js") }}
Esta tag gera a tag com base na url da sua aplicação.
{{ form("posts/save") }}
Esta tag abre um form não para a URL posts/save mas sim para a URL que corresponde ao controller post, action save.
BackEnd
- DependencyInjection: Como havia sido comentado, o Phalcon só carrega aquilo que usa. E esse é o responsável por isso.
- ObjectRelational Mapping: Nada de escrever linhas de conexão e sql. Quer achar um usuário?
- EventManager: Esse serviço permite que você execute ações antes e/ou depois de cada request. Ou somente para uma classe, totalmente personalizável.
User::find(array(“email”=>”mail@gmail.com”));
Linha de comando
Nada como não ter que dar ctrl+c e ctrl+v em um monte de pastas e arquivos. Este recurso permite que vc crie projetos, controllers, models, views. Todos com comandos simples.
Um novo projeto:
phalcon project devmedia
Um novo controller:
phalcon controller Posts
Um novo model:
phalcon model --table-name Users
O ORM procura por uma table no banco com as configurações do projeto, mapeia os atributos e gera o model.
Interface Gráfica
Além da linha de comando, o phalcon conta com uma interface gráfica para gerar as controllers, as models e etc. Uma imagem diz mais que mil palavras:
Figura 3: Interface Gráficas
Conclusão
Até aqui só foi exaltada as qualidades deste framework. Existem desvantagens? Sempre. Assim como todo framework, ele possui uma curva de aprendizagem e como não é muito popular, as vídeo aulas e cursos online são escassos. Em contrapartida o phalcon conta com uma comunidade muito ativa no github e uma documentação muito rica.
O melhor framework é aquele com o qual mais se produz e mais se adapta. Se o phalcon for muito confuso para você, acontece. Mas se o seu objetivo é performance vale a pena dar uma conferida!
API Rest de Robôs
Uma api simples para um CRUD de Robôs.
Listagem 1: API Rest de Robôs
<?php
//Cria uma instância de Dependency Injection
$di = new \Phalcon\DI\FactoryDefault();
//Cria o serviço de banco de dados
$di->set('db', function(){
return new \Phalcon\Db\Adapter\Pdo\Mysql(array(
"host" => "localhost",
"username" => "asimov",
"password" => "zeroth",
"dbname" => "robotics"
));
});
//Retorna todos os robôs
$app->get('/api/robots', function() {
$robots = Robots::find(array("order" => "name"));
$data = array();
foreach ($robots as $robot) {
$data[] = array(
'id' => $robot->id,
'name' => $robot->name,
);
}
echo json_encode($data);
});
//Retorna o robô com a chave primária $id
$app->get('/api/robots/{id:[0-9]+}', function($id) {
$robot = Robots::find($id);
if ($robot == false) {
$response->setJsonContent(array('status' => 'NOT-FOUND'));
} else {
$response->setJsonContent(array(
'status' => 'FOUND',
'data' => array(
'id' => $robot->id,
'name' => $robot->name
)
));
}
return $response;
});
//Insere um novo robô
$app->post('/api/robots', function() {
$status = Robots::save(
$this->request->getPost(),
array(“name”,”type”,”year”)
);
//Resposta HTTP
$response = new Phalcon\Http\Response();
//Verifica o resultado da inserção
if ($status->success() == true) {
$robot->id = $status->getModel()->id;
$response->setJsonContent(array(
'status' => 'OK',
'data' => $robot
));
} else {
//Altera o status da resposta
$response->setStatusCode(500, "Internal Error");
//Envia os erros
$errors = array();
foreach ($status->getMessages() as $message) {
$errors[] = $message->getMessage();
}
$response->setJsonContent(array('status' => 'ERROR', 'messages' => $errors));
}
return $response;
});
//Atualiza o robô com a chave primária $id
$app->put('/api/robots/{id:[0-9]+}', function($id) {
$robot = Robots::findFirst($id);
$post = $robot = $app->request->getJsonRawBody();
$robot->name = $post->name;
$robot->type = $post->type;
$robot->year = $post->year;
$status = $robot->save();
//Resposta HTTP
$response = new Phalcon\Http\Response();
////Verifica o resultado da atualização
if ($status->success() == true) {
$response->setJsonContent(array('status' => 'OK'));
} else {
//Altera o status da resposta
$response->setStatusCode(500, "Internal Error");
$errors = array();
foreach ($status->getMessages() as $message) {
$errors[] = $message->getMessage();
$response->setJsonContent(array('status' => 'ERROR', 'messages' => $errors));
return $response;
});
//Deleta o robô com a chave primária $id
$app->delete('/api/robots/{id:[0-9]+}', function($id) {
$status = Robots::delete($id);
//Resposta HTTP
$response = new Phalcon\Http\Response();
if ($status->success() == true) {
$response->setJsonContent(array('status' => 'OK'));
} else {
// Altera o status da resposta
$response->setStatusCode(500, "Internal Error");
$errors = array();
foreach ($status->getMessages() as $message) {
$errors[] = $message->getMessage();
}
$response->setJsonContent(array('status' => 'ERROR', 'messages' => $errors));
}
return $response;
});
//Instancia a aplicação com as dependências criadas ($di)
$app = new \Phalcon\Mvc\Micro($di);
$app->handle($di);
Links
- Alguns tutoriais sobre o Phalcon pela própria equipe que o mantém.
- Documentação