Symfony Vs Phalcon: Which framework to use for building REST APIS?

5.00 avg. rating (97% score) - 1 vote

There are a number of frameworks and micro-frameworks available in PHP for building REST APIS each with its pros and cons. While some provide more performance benefits some are rich in community interaction and 3rd party bundles. We had quite an expertize in symfony and its related components, so we decided to go for a comparison of symfony with the fastest PHP framework available i.e, phalcon. No doubt phalcon is faster but we wanted to know how much performance gain is achieved via phalcon so that we can let go of  symfony which provides many bundles easing our development and reducing our time to market the application.

Let’s see why we decided to go with phalcon for building REST APIS!

Introduction

Behind every great mobile and web application there is a number of REST APIS that are responsible for delivering data and serve as the backend. So choosing a right framework for building these REST APIS plays a crucial role in the performance of our application.

Symfony – Symfony is a web application framework for PHP consisting of a set of decoupled components (features) written in PHP.

Phalcon – Phalcon is a web application framework for PHP consisting of a set of of loosely coupled components written as a C extension. Its innovative architecture makes it the fastest PHP framework ever built!

Similarities

Before we start discussing about performance let us first see what they have in common. The below mentioned features are crucial in building any application and are present in both of them.

Source Code

As an example let’s consider a simple REST API for fetching an employee list for a company. For performing benchmark we used a GET api that fetches 10000 records from a mysql database.

For creating REST APIS in symfony we don’t need full stack symfony framework. Symfony introduced MicroKernel in Symfony 2.8 that contains minimal requirements to boot an application implying less code and therefore less memory and faster execution as compared to its full stack framework. We can build our APIS using MicroKernel and required symfony components.

Sample code (Symfony):

index.php

<?php
use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Kernel;
use Symfony\Component\Routing\RouteCollectionBuilder;
use MyAppSymfony\Model\Employees;
use MyAppSymfony\Manager\ApiManager;

require __DIR__.'/vendor/autoload.php';

class AppKernel extends Kernel
{
    use MicroKernelTrait;

    public function registerBundles()
    {
        return array(
            new Symfony\Bundle\FrameworkBundle\FrameworkBundle()
        );
    }

    protected function configureContainer(ContainerBuilder $c)
    {
        $c->loadFromExtension('framework', array(
            'secret' => 'S0ME_SECRET'
        ));
    }

    protected function configureRoutes(RouteCollectionBuilder $routes)
    {
        $routes->add('/employees', 'kernel:getEmployees');
    }

    public function getEmployees()
    {
        $apiManagerObj = new ApiManager();
        $employeeList = $apiManagerObj->getEmployees();
        return new JsonResponse($employeeList);
    }
}

$kernel = new AppKernel('dev', true);
$request = Request::createFromGlobals();
$response = $kernel->handle($request);
$response->send();
$kernel->terminate($request, $response);

*This is a sample code not meant to copy and run. Logic for fetching from mysql database is abstracted away for simplicity. Also no out the box optimization is done.

For building REST APIS in phalcon we use micro component of phalcon. It provides a set of methods to define the routes and its corresponding HTTP method.
Just like symfony you can use its full stack framework for building complex mvc applications and its related components.

Sample code (Phalcon):

index.php

<?php
use Phalcon\Mvc\Micro;

try {
    $loader = new \Phalcon\Loader();
    $loader->registerNamespaces(
        [
            'MyAppPhalcon\Manager' => __DIR__ . "/manager/"
        ]
    );   
    $app = new Micro();
    $app->get('/employees', function () {
        $apiManagerObj = new \MyAppPhalcon\Manager\ApiManager();
        $employeeList = $apiManagerObj->getEmployees();
        $response = new \Phalcon\Http\Response();
        $response->setJsonContent($employeeList);
        $response->send();
    });
    $app->handle();
} catch (\Exception $e) {
      echo $e->getMessage() . '<br>';
      echo '<pre>' . $e->getTraceAsString() . '</pre>';
}

*This is a sample code not meant to copy and run. Logic for fetching from mysql database is abstracted away for simplicity. Also no out the box optimization is done.

More about phalcon:

While building REST APIS we often encounter situations in which one component is dependent on other which in turn is dependent on another. For eg, in our case api manager is dependent on api dao which in turn has a dependency connection and logger.

Dependency injection is a widely accepted design pattern to solve this kind of situation. It keeps our code more maintainable and decoupled. In phalcon it is achieved via container which acts as a global registry (where all services are registered). The component can access the service it requires by simply requesting the global registry. There are many ways to register and access a service. Most widely used are:

Constructor Injection
Sample code (Registering a service):

services.php

<?php
$di = new Di();
$di->setShared(
    "api.manager",
    [
        "className" => "MyAppPhalcon\\Manager\\ApiManager",
        "arguments" => [
            [
                "type" => "service",
                "name" => "api.dao",
            ]
        ]
    ]
);
$di->setShared(
    "api.dao",
    [
        "className" => "MyAppPhalcon\\Dao\\ApiDao"
    ]
);

*This is a sample code not meant to copy and run. We can write the above mentioned code in services.php and include it in index.php making our code more maintainable.

index.php

<?php
include __DIR__ . '/config/services.php';
 Sample code (Accessing a service):
<?php

namespace MyAppPhalcon\Manager;

use MyAppPhalcon\Dao\ApiDao;

class ApiManager
{

    protected $apiDao;
    public function __construct(ApiDao $apiDao)
    {
        $this->apiDao = $apiDao;
    }
}

*This is a sample code not meant to copy and run.

Setter Injection
Sample code (Registering a service):
<?php

$di = new Di();
$di->setShared(
    "api.manager",
    [
        "className" => "MyAppPhalcon\\Manager\\ApiManager",
        "calls"     => [
            [
                "method"    => "setApiDao",
                "arguments" => [
                    [
                        "type" => "service",
                        "name" => "api.dao",
                    ]
                ]
            ]
        ]        
    ]
);

*This is a sample code not meant to copy and run.

Sample code (Accessing a service):
<?php

namespace MyAppPhalcon\Manager;

use MyAppPhalcon\Dao\ApiDao;

class ApiManager
{
    protected $apiDao;

    public function setApiDao(ApiDao $apiDao)
    {
        $this->apiDao = $apiDao;
    }
}

*This is a sample code not meant to copy and run.

Properties Injection
<?php
$di = new Di();
$di->setShared(
    "api.manager",
    [
        "className" => "MyAppPhalcon\\Manager\\ApiManager",
        "properties"     => [
            [
                "name"    => "apiDao",
                "values" => [
                    [
                        "type" => "service",
                        "name" => "api.dao",
                    ]
                ]
            ]
        ]        
    ]
);

*This is a sample code not meant to copy and run.

Sample code (Accessing a service):
<?php
namespace MyAppPhalcon\Manager;

use MyAppPhalcon\Dao\ApiDao;

class ApiManager
{
    public $apiDao;
}

*This is a sample code not meant to copy and run.

Performance Benchmark

We performed benchmarking using ab (apache workbench) benchmark tool with varying number of total and concurrent requests.

Results

With 100 requests using 10 concurrent connections following observation was recorded

 

With 1000 request using 100 concurrent connections following observation was recorded

Conclusion

Phalcon can handle around 50% more request per second as compared to symfony. Phalcon outperformed significantly as compared to symfony in terms of number of request per second and time per request due to its innovative architecture but that should not be the only criteria for selecting/rejecting a framework.
Debugging in phalcon is a headache. Of course we can debug our application code which is written in PHP but what if there is a bug in the framework itself or the framework is not maintained anymore. In that case we need to hire a C programmer or wait for a bugfix. Debugging in symfony is just like debugging our application as it is also written in PHP. There is another factor that plays a significant role in selecting/rejecting a framework, that is community support. There are more number of third party bundles available in symfony and more programmers who resolve the queries.

So, for building small applications that do not require many components/ 3rd party bundles we should choose phalcon, which is significantly better than symfony in terms of performance saving our resources and improving response time and thus boosting our business and money.

3 thoughts on “Symfony Vs Phalcon: Which framework to use for building REST APIS?

  1. Thanks , I’ve just been looking for info approximately this topic for a long time and yours is the best I’ve found out till now. But, what about the bottom line? Are you sure in regards to the source?

Comments are closed.