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.

Requests por segundo

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.

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?
  • User::find(array(“email”=>”mail@gmail.com”));
  • 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.

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:

Interface Gráficas

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