Today, when starting a new project, one of the key decisions is to pick the right framework. It’s become hard to imagine building a complex web application from scratch nowadays without one.

Many popular languages for web development have their “default” framework, such as Ruby on Rails for Ruby, or Django for Python. However, PHP has no such single default and has multiple popular options to choose from.

According to Google trends and GitHub, the most popular PHP frameworks are Symfony with 13.7k stars and Laravel with 29k stars (at the time of writing this article).

In this article, I am going to compare these two frameworks and show you how to implement simple, everyday features with each. This way, you can compare the code of real-life examples side by side.

This article presumes strong PHP skills and an understanding of the MVC architectural paradigm, but no previous experience with Symfony or Laravel is required.

The Contenders

PHP Frameworks: Choosing Between Symfony and Laravel

Laravel

When speaking about Laravel, we are referring to Laravel version 4 and beyond. Laravel 4 was released in 2013 and represented a complete rewrite of the framework. The functionality of the framework was decoupled into separate components, which were managed with Composer, instead of everything being in one single huge code repository.

Laravel declares itself as a framework for rapid development with a simple and beautiful syntax which is easy to learn, read, and maintain. It is the most popular framework in 2016. According to Google trends, it is three times more popular than other frameworks, and on GitHub, it has two times more stars than competitors.

Symfony

Symfony 2 was released in 2011, but it must not be confused with Symfony 1, which was a totally different framework with different underlying principles. Fabien Potencier created Symfony 2, and the current version is 3.2, which is an incremental version of Symfony 2. Therefore, they are often called simply Symfony2/3.

Like Laravel 4, Symfony 2 is designed as a set of decoupled components. There are two benefits here: We can replace any component in a Symfony project, and we can take and use any Symfony component in a non-Symfony project. Symfony components can serve as great code examples and they are used in a lot of open source projects such as Drupal, phpBB, and Codeception. In fact, Laravel itself uses no less than 14 Symfony components. Understanding Symfony thus gives you many benefits when working with other projects.

Framework Installations

Both frameworks come with installers and wrappers available via the PHP built-in web server.

Symfony Installation

Symfony installation is as simple as the following:

# Downloading Symfony installer
sudo curl -LsS https://symfony.com/installer -o /usr/local/bin/symfony
# Granting permissions to execute installer
sudo chmod a+x /usr/local/bin/symfony
# Creating new Symfony project
symfony new symfony_project
# Launching built-in server
cd symfony_project/ && php bin/console server:start

That’s it! Your Symfony installation is available on URL http://localhost:8000.

Laravel Installation

The Laravel installation process is almost the same and as simple as that for Symfony; the only difference is that you install Laravel’s installer through Composer:

# Downloading Laravel installer using Composer
composer global require "laravel/installer"
# Creating new Laravel project
laravel new laravel_project
# Launching built-in server
cd laravel_project/ && php artisan serve

You can now visit http://localhost:8000 and check your Laravel installation.

Note: Both Laravel and Symfony run off the same localhost port (8000) by default, so you can’t have these default instances running concurrently. Don’t forget to stop the Symfony server by running php bin/console server:stop before launching the Laravel server.

About Framework Installation

These are examples of a basic installation. For more advanced usage examples, such as being able to configure projects with local domains or run multiple projects at once, both frameworks provide Vagrant boxes:

Basic Framework Configurations

Symfony Basic Configuration

Symfony uses YAML as the syntax for specifying its configuration. The default configuration is located in the app/config/config.yml file, and looks like the following example:

imports:
    - { resource: parameters.yml }
    - { resource: security.yml }
    - { resource: services.yml }

framework:
    secret:          '%secret%'
    router:          { resource: '%kernel.root_dir%/config/routing.yml' }
    # ...

# Twig Configuration
twig:
    debug:            '%kernel.debug%'
    strict_variables: '%kernel.debug%'
    
# ...

To create an environment specific configuration, create the file app/config/config_ENV.yml containing the basic config parameters. Here’s an example of a config_dev.yml file for the development environment:

imports:
    - { resource: config.yml }
# ...
web_profiler:
    toolbar: true
# ...

This example turns on the web_profiler Symfony tool only for the development environment. This tool helps you to debug and profile your application right in the browser window.

In the configuration files, you can also notice %secret% constructions. They allow us to put environment-specific variables in the separate parameters.yml file. This file could be unique on every machine and is not stored under version control. For version control, we have a special parameters.yml.dist file that is the template for the parameters.yml file.

Here is an example of the parameters.yml file:

parameters:
    database_host: 127.0.0.1
    database_port: null
    database_name: symfony
    database_user: root
    database_password: null
    secret: f6b16aea89dc8e4bec811dea7c22d9f0e55593af

Laravel Basic Configuration

Laravel configuration looks very different from that of Symfony. The only one thing they have in common is that they both use files that are not stored under version control (.env in the Laravel case) and a template for generating this file (.env.example). This file has a list of keys and values, like the following example:

APP_ENV=local
APP_KEY=base64:Qm8mIaur5AygPDoOrU+IKecMLWgmcfOjKJItb7Im3Jk=
APP_DEBUG=true
APP_LOG_LEVEL=debug
APP_URL=http://localhost

Like the Symfony YAML file, this one for Laravel is also human readable and looks clean. You can additionally create .env.testing file that will be used when running PHPUnit tests.

The application configuration is stored in .php files in the config directory. Basic configuration is stored in the app.php file and component-specific configuration is stored in <component>.php files (e.g., cache.php or mail.php). Here’s an example of a config/app.php file:

<?php

return [
    'name'     => 'Laravel',
    'env'      => env('APP_ENV', 'production'),
    'debug'    => env('APP_DEBUG', false),
    'url'      => env('APP_URL', 'http://localhost'),
    'timezone' => 'UTC',
    'locale'   => 'en',
    // ...
];

Framework Configuration: Symfony vs. Laravel

Symfony’s application configuration mechanisms allow you to create different files for different environments. Additionally, it prevents you from injecting complex PHP logic in the YAML configuration.

However, you may feel more comfortable with the default PHP configuration syntax Laravel is using and you don’t have to learn YAML syntax.

Routing and Controller

In general, a back-end web application has one primary responsibility: to read each request, and to create a response depending on the content of the request. The controller is a class responsible for transforming the request to the response by calling application methods, while the router is a mechanism that helps you to detect which controller class and method you should execute for a particular request.

Let’s create a controller that will show a blog post page requested from the /posts/{id} route.

Routing and Controller in Laravel

Controller

<?php

namespace App\Http\Controllers;

use App\Post;

class BlogController extends Controller
{
    /**
     * Show the blog post
     * @param int $id
     * @return \Illuminate\Http\Response
     */
    public function show($id)
    {
        return view('post', ['post' => Post::findOrFail($id)]);
    }
}

Router

Route::get('/posts/{id}', 'BlogController@show');

We’ve defined the route for GET requests. All requests with the URI matching the /posts/{id} will execute the BlogController controller’s show the method, and will pass the parameter id to that method. In the controller, we are trying to find the object of model POST with the passed id, and call Laravel helper view() to render the page.

Routing and Controller in Symfony

In Symfony, exampleController is a little bit bigger:

<?php

namespace BlogBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;

class PostController extends Controller
{
    /**
     * @Route("/posts/{id}")
     * @param int $id
     * @return \Symfony\Component\HttpFoundation\Response
     */
    public function indexAction($id)
    {
        $repository = $this->getDoctrine()->getRepository('BlogBundle:Post');
        $post = $repository->find($id);
        if ($post === null) {
            throw $this->createNotFoundException();
        }
        return $this->render('BlogBundle:Post:show.html.twig', ['post'=>$post]);
    }
}

You can see we’ve already included @Route("/posts/{id}”) in the annotation, so we just need to include the controller in the routing.yml configuration file:

blog:
    resource: "@BlogBundle/Controller/"
    type:     annotation
    prefix:   /

The step by step logic is the same as in the Laravel case.

Routing and Controller: Symfony vs. Laravel

At this stage, you might think Laravel is much nicer than Symfony. This is true, in the beginning. It looks way better and easier to start. However, in the real-life applications, you shouldn’t call Doctrine from the controller. Instead, you should call a service that will try to find the post or throw HTTP 404 Exception.

Templates

Laravel ships with a template engine called Blade and Symfony ships with Twig. Both template engines implement two main features:

  1. Template inheritance
  2. Blocks or sections

Both features allow you to define a basic template with overridable sections and child templates that fill values of those sections.

Let’s consider the example of a blog post page again.

Laravel Blade Template Engine

// base.blade.php
<html>
<head>
    <style></style>
    <title>@section('page-title')
            Welcome to blog!
        @show
    </title>
</head>
<body>
<div class="container">
    <h1>@yield('title')</h1>
    <div class="row">
        @yield('content')
    </div>
</div>
</body>
</html>

// post.blade.php
@extends('base')

@section('page-title')Post {{ $post->title }} - read this and more in our blog.@endsection

@section('title'){{ $post->title }}@endsection

@section('content')
    {{ $post->content }}
@endsection

Now you can tell Laravel in your Controller to render template post.blade.php. Do you remember our view(‘post’, …) call in the previous Controller example? You don’t need to know in your code that it is inherited from some other template. It is all defined only in your templates, on the view level.

Symfony Twig Template Engine

// base.html.twig
<html>
<head>
    <style></style>
    <title>{% block page_title %}
        Welcome to blog!
        {% endblock %}
    </title>
</head>
<body>
<div class="container">
    <h1>{% block title %}{% endblock %}</h1>
    <div class="row">
        {% block content %}{% endblock %}
    </div>
</div>
</body>
</html>

// show.html.twig
{% extends '@Blog/base.html.twig' %}

{% block page_title %}Post {{ post.title }} - read this and more in our blog.{% endblock %}

{% block title %}{{ post.title }}{% endblock %}

{% block content %}
    {{ post.content }}
{% endblock %}

Templates: Symfony vs. Laravel

Structurally, Blade and Twig templates are quite similar. Both generate templates into PHP code and work fast, and both implement control structures, such as if statements and loops. The most important feature both engines have is that they escape the output by default, which helps prevents XSS attacks.

Aside from syntax, the main difference is that Blade allows you to inject PHP code directly into your templates and Twig does not. Instead, Twig allows you to use filters.

For example, if you want to capitalize a string, in Blade you would specify the following:

{{ ucfirst('welcome friend') }}

In Twig, on the other hand, you would do the following:

{{ 'welcome friend'|capitalize }}

In Blade, it is easier to extend some functionality, but Twig does not allow any direct PHP code in templates.

Dependency Injection

Applications have a lot of different services and components, with various interdependencies. You need to store all the information about the created objects and their dependencies somehow.

Here comes our next component - Service Container. It is a PHP object that creates requested services and stores information about the created objects and their dependencies.

Let’s consider the following example: You are creating a class PostService to implement a method that is responsible for creating a new blog post. This class depends on two other services: PostRepository, which is responsible for storing information in the database, and SubscriberNotifier, which is responsible for notifying subscribed users about the new post. To get it to work, you need to pass these two services as the constructor arguments of PostService or, in other words, you need to inject these dependencies.

Symfony Dependency Injection Example

First, let’s define our sample services:

<?php
// src/BlogBundle/Repository/PostRepository.php
namespace BlogBundle\Repository;

use BlogBundle\Entity\Post;
use Doctrine\ORM\EntityRepository;

class PostRepository extends EntityRepository
{
    public function persist(Post $post)
    {
        // Perform save to db
    }
}
<?php
// src/BlogBundle/Service/SubscriberNotifier.php
namespace BlogBundle\Service;

use BlogBundle\Entity\Post;

class SubscriberNotifier
{
    public function notifyCreate(Post $post)
    {
        // Notify subscribers
    }
}
<?php
// src/BlogBundle/Service/PostService
namespace BlogBundle\Service;

use BlogBundle\Entity\Post;
use BlogBundle\Repository\PostRepository;

class PostService
{
    /** @var PostRepository */
    private $repository;
    /** @var SubscriberNotifier */
    private $notifier;

    function __construct(PostRepository $repository, SubscriberNotifier $notifier)
    {
        $this->repository = $repository;
        $this->notifier = $notifier;
    }

    public function create(Post $post)
    {
        $this->repository->persist($post);
        $this->notifier->notifyCreate($post);
    }
}

Next is the dependency injection configuration:

# src/BlogBundle/Resources/config/services.yml
services:
    # Our main service
    blog.post_service:
      class: BlogBundle\Service\PostService
      arguments: ['@blog.post_repository', '@blog.subscriber_notifier']

    # SubscriberNotifier service. It could also have it's own dependencies, for example, mailer class.
    blog.subscriber_notifier:
      class: BlogBundle\Service\SubscriberNotifier

    # Repository. Don't dive deep into it's configuration, it is not a subject now
    blog.post_repository:
      class: BlogBundle\Repository\PostRepository
      factory: 'doctrine.orm.default_entity_manager:getRepository'
      arguments:
        - BlogBundle\Entity\Post

Now you can request your post service anywhere in the code from your Service Container object. For example, in the controller it could be something like this:

// Controller file. $post variable defined below
$this->get('blog.post_service')->create($post);

Service Container is a great component, and it helps to build your application following SOLID design principles.

Laravel Dependency Injection Example

It is much easier to manage dependencies in Laravel. Let’s consider the same example:

<?php
// app/Repository/PostRepository.php
namespace App\Repository;

use App\Post;

class PostRepository
{
    public function persist(Post $post)
    {
        // Perform save to db
    }
}
<?php
// app/Service/SubscriberNotifier.php
namespace App\Service;

use App\Post;

class SubscriberNotifier
{
    public function notifyCreate(Post $post)
    {
        // Notify subscribers
    }
}
<?php
// app/Service/PostService.php
namespace App\Service;

use App\Post;
use App\Repository\PostRepository;

class PostService
{
    /** @var PostRepository */
    private $repository;
    /** @var SubscriberNotifier */
    private $notifier;

    public function __construct(PostRepository $repository, SubscriberNotifier $notifier)
    {
        $this->repository = $repository;
        $this->notifier = $notifier;
    }

    public function create(Post $post)
    {
        $this->repository->persist($post);
        $this->notifier->notifyCreate($post);
    }
}

Here comes the beauty of Laravel - you do not need to create dependency configurations. Laravel automatically scans the dependencies for PostService in its constructor arguments types and automatically resolves them.

You can also use injection in your controller method to use PostService by “type-hinting” it in method arguments:

<?php

namespace App\Http\Controllers;

use App\Post;
use App\Service\PostService;

class BlogController extends Controller
{
    public function create(PostService $service)
    {
        $post = new Post(['title' => 'Title', 'content' => 'Content']);

        $service->create($post);
        return redirect('/posts/'.$post->id);
    }
}

Dependency Injection: Symfony vs. Laravel

Laravel’s autodetection works great. Symfony has a similar capability called “autowire” that is turned off by default and could be turned on by adding autowire: true to your dependency configuration, but it requires some configuration. The Laravel way is simpler.

Object Relational Mapping (ORM)

To work with databases, both frameworks come with Object-Relational Mapping (ORM) features. ORM maps records from the database to objects in the code. To do this, you must create models for each record type (or each table) in your database.

Symfony uses a third-party project Doctrine to interact with the database, while Laravel uses its own library Eloquent.

The Eloquent ORM implements the ActiveRecord pattern to work with the database. In this pattern, each model is aware of the connection to the database and can interact with it. For example, it can save data to the database, update, or delete a record.

Doctrine implements the Data Mapper pattern, where models know nothing about the database; they are only aware of the data itself. A special separate layer, EntityManager, stores all the information about the interaction between models and databases, and it handles all the operations.

Let’s take an example to understand the difference. Let’s say your model has a primary id key, title, content, and author. The Posts table stores only the author id, so you need to create a relation to the Users table.

Doctrine

Let’s begin by defining the models:

<?php
// src/BlogBundle/Entity/User.php
namespace BlogBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * User
 *
 * @ORM\Table(name="user")
 * @ORM\Entity
 */
class User
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="name", type="string", length=255)
     */
    private $name;
}
<?php
// src/BlogBundle/Entity/Post.php
namespace BlogBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * Post
 *
 * @ORM\Table(name="post")
 * @ORM\Entity(repositoryClass="BlogBundle\Repository\PostRepository")
 */
class Post
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @var string
     *
     * @ORM\Column(name="title", type="string", length=255)
     */
    protected $title;

    /**
     * @var string
     *
     * @ORM\Column(name="content", type="text")
     */
    protected $content;

    /**
     * @var User
     *
     * @ORM\ManyToOne(targetEntity="BlogBundle\Entity\User")
     * @ORM\JoinColumn(name="author_id", referencedColumnName="id")
     */
    protected $author;

Here, we created model mapping information and can now use a helper to generate the method stubs:

php bin/console doctrine:generate:entities BlogBundle

Next, we define post repository methods:

<?php
// src/BlobBundle/Repository/PostRepository.php
namespace BlogBundle\Repository;

use BlogBundle\Entity\Post;
use Doctrine\ORM\EntityRepository;

class PostRepository extends EntityRepository
{
    /**
     * Store post to database
     *
     * @param Post $post
     */
    public function persist(Post $post)
    {
        $this->getEntityManager()->persist($post);
        $this->getEntityManager()->flush();
    }

    /**
     * Search posts with given author's name
     *
     * @param string $name
     * @return array
     */
    public function findByAuthorName($name)
    {
        return $this->createQueryBuilder('posts')
            ->select('posts')
            ->join('posts.author', 'author')
            ->where('author.name = :name')
            ->setParameter('name', $name)
            ->getQuery()
            ->getResult();
    }
}

Now you can call these methods from the service or, for example, from PostController:

// To search for posts
$posts = $this->getDoctrine()->getRepository('BlogBundle:Post')->findByAuthorName('Karim');
// To save new post in database
$this->getDoctrine()->getRepository('BlogBundle:Post')->persist($post);

Eloquent

The User model ships with Laravel and it is defined by default, so you only need to define one model for the Post.

<?php
// app/Post.php
namespace App;

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    public function author()
    {
        return $this->belongsTo('App\User', 'author_id');
    }
}

That’s all for models. In Eloquent, you don’t have to define model properties, as it builds them dynamically based on the database table structure. To store a new post $post into the database, you need to make this call (from the controller, for example):

$post->save();

To find all posts by an author with a given name, the best approach would be to find a user with its name and request all users’ posts:

$posts = Post::whereHas('author', function ($q) {
    $q->where('name', 'Karim');
})->get();

ORM: Symfony vs. Laravel

With regard to ORM, Eloquent looks much more friendly for PHP developers and easier to learn than Doctrine.

Event Dispatcher vs. Middleware

Symfony vs. Laravel Lifecycle

One of the most important things to understand about a framework is its lifecycle.

Symfony and Event Dispatcher

To convert a request into a response, Symfony uses EventDispatcher. It consequentially fires different lifecycle events and special event listeners to handle these events. In the beginning, it dispatches the kernel.request event that includes request information. The main default listener of this event is RouterListener, which invokes the router component to find a suitable route rule for the current request. After this, other events are executed step-by-step. Typical event listeners are a Security check, CSRF token verification, and a logging process. If you want to add some functionality in the request lifecycle, you need to create a custom EventListener and subscribe it to the necessary event.

Laravel and Middleware

Laravel uses a different solution: middleware. I like comparing middleware to an onion: Your application has certain layers and a request passes through these layers on the way to the controller and back. So, if you want to extend your application logic and add some functionality in the request lifecycle, you need to add an additional layer to your middleware list, and Laravel will execute it.

REST API

Let’s try to create a basic CRUD example to manage a blog post:

  • Create - POST /posts/
  • Read - GET /posts/{id}
  • Update - PATCH /posts/{id}
  • Delete - DELETE /posts/{id}

REST API in Symfony

Symfony doesn’t have an easy out-of-the-box solution for fast REST API creation, but it has great third-party bundles FOSRestBundle and JMSSerializerBundle.

Let’s consider the minimal working example with FOSRestBundle and JMSSerializerBundle. After you installed them and turned them on in AppKernel, you can set in the bundle configuration that you will use JSON format and that this doesn’t have to be included in the URL requests:

#app/config/config.yml
fos_rest:
    routing_loader:
        default_format: json
        include_format: false

In the routing configuration, you should specify that this controller will implement a REST resource:

#app/config/routing.yml
blog:
    resource: BlogBundle\Controller\PostController
    type:     rest

You implemented a persist method in the repository in the previous example; now you need to add a delete method:

// src/BlogBundle/Repository/PostRepository.php
public function delete(Post $post)
{
    $this->getEntityManager()->remove($post);
    $this->getEntityManager()->flush();
}

Next, you need to create a form class to accept input requests and map them to the model. You can do it by using a CLI helper:

php bin/console doctrine:generate:form BlogBundle:Post

You will receive a generated form type with the following code:

<?php
// src/BlogBundle/Form/PostType.php
namespace BlogBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class PostType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('title')->add('content');
    }

    /**
     * {@inheritdoc}
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => 'BlogBundle\Entity\Post',
            'csrf_protection' => false
        ]);
    }

    /**
     * {@inheritdoc}
     */
    public function getBlockPrefix()
    {
        return 'post';
    }
}

Now let’s implement our controller.

Note: the code I am going to show you is not perfect. It violates some design principles, but could be easily refactored. The main purpose is to show you how to implement each method, step by step.

<?php
// src/BlogBundle/Controller/PostController.php
namespace BlogBundle\Controller;

use BlogBundle\Entity\Post;
use BlogBundle\Form\PostType;
use FOS\RestBundle\Controller\FOSRestController;
use FOS\RestBundle\View\View;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;

class PostController extends FOSRestController
{
    /**
     * @param $id
     * @return Response
     */
    public function getPostAction($id)
    {
        $view = new View();
        $post = $this->getDoctrine()->getRepository('BlogBundle:Post')->find($id);
        if ($post === null) {
            $view->setStatusCode(Response::HTTP_NOT_FOUND);
        } else {
            $view->setData(['post' => $post]);
        }

        return $this->handleView($view);
    }

    /**
     * @param Request $request
     * @return Response
     */
    public function postPostAction(Request $request)
    {
        $view = new View(null, Response::HTTP_BAD_REQUEST);
        $post = new Post;
        $form = $this->createForm(PostType::class, $post, ['method' => $request->getMethod()]);
        $form->handleRequest($request);
        if ($form->isValid()) {
            $this->getDoctrine()->getRepository('BlogBundle:Post')->persist($post);
            $view->setStatusCode(Response::HTTP_CREATED);
            $postUrl = $this->generateUrl('get_post', ['id' => $post->getId()], UrlGeneratorInterface::ABSOLUTE_URL);
            $view->setHeader('Location', $postUrl);
        } else {
            $view->setData($form->getErrors());
        }

        return $this->handleView($view);
    }

    /**
     * @param $id
     * @param Request $request
     * @return Response
     */
    public function patchPostAction($id, Request $request)
    {
        $view = new View(null, Response::HTTP_BAD_REQUEST);
        $post = $this->getDoctrine()->getRepository('BlogBundle:Post')->find($id);
        if ($post === null) {
            $view->setStatusCode(Response::HTTP_NOT_FOUND);
        } else {
            $form = $this->createForm(PostType::class, $post, ['method' => $request->getMethod()]);
            $form->handleRequest($request);
            if ($form->isValid()) {
                $this->getDoctrine()->getRepository('BlogBundle:Post')->persist($post);
                $view->setStatusCode(Response::HTTP_NO_CONTENT);
                $postUrl = $this->generateUrl('get_post', ['id' => $post->getId()], UrlGeneratorInterface::ABSOLUTE_URL);
                $view->setHeader('Location', $postUrl);
            } else {
                $view->setData($form->getErrors());
            }
        }

        return $this->handleView($view);
    }

    /**
     * @param $id
     * @return Response
     */
    public function deletePostAction($id)
    {
        $view = new View(null, Response::HTTP_NOT_FOUND);
        $post = $this->getDoctrine()->getRepository('BlogBundle:Post')->find($id);
        if ($post !== null) {
            $this->getDoctrine()->getRepository('BlogBundle:Post')->delete($post);
            $view->setStatusCode(Response::HTTP_NO_CONTENT);
        }

        return $this->handleView($view);
    }
}

With FOSRestBundle, you don’t need to declare a route for each method; just follow the convention with controller method names, and JMSSerializerBundle will automatically convert your models to JSON.

REST API in Laravel

First, you need to define routes. You can do this in the api section of the route rules to turn off some default middleware components and turn on others. The api section is located in the routes/api.php file.

<?php
// routes/api.php
Route::resource('/posts', 'BlogController');

In the model, you should define the $fillable property to pass variables in the model’s create and update methods:

<?php
// app/Post.php
namespace App;

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    protected $fillable = ['title', 'content'];
    // …

Now let’s define the controller:

<?php
// app/Http/Controllers/BlogController.php
namespace App\Http\Controllers;

use App\Post;
use Illuminate\Http\Request;
use Illuminate\Http\Response;

class BlogController extends Controller
{
    public function show(Post $post)
    {
        return $post;
    }

    public function store(Request $request)
    {
        $post = Post::create($request->get('post'));

        return response(null, Response::HTTP_CREATED, ['Location'=>'/posts/'.$post->id]);
    }

    public function update(Post $post, Request $request)
    {
        $post->update($request->get('post'));

        return response(null, Response::HTTP_NO_CONTENT, ['Location'=>'/posts/'.$post->id]);
    }

    public function destroy(Post $post)
    {
        $post->delete();

        return response(null, Response::HTTP_NO_CONTENT);
    }
}

In Symfony, you are using FosRestBundle, which wrapped errors in JSON. In Laravel, you need to do it yourself. You need to update render method in the Exception handler to return JSON errors for expecting JSON requests:

<?php
// app/Exceptions/Handler.php
namespace App\Exceptions;

use Exception;
use Illuminate\Auth\AuthenticationException;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;

class Handler extends ExceptionHandler
{

    /**
     * Render an exception into an HTTP response.
     *
     * @param  \Illuminate\Http\Request $request
     * @param  \Exception $exception
     * @return \Illuminate\Http\Response
     */
    public function render($request, Exception $exception)
    {
        if ($request->expectsJson()) {
            $status = 400;
            if ($this->isHttpException($exception)) {
                $status = $exception->getStatusCode();
            } elseif ($exception instanceof ModelNotFoundException) {
                $status = 404;
            }

            $response = ['message' => $exception->getMessage(), 'code' => $exception->getCode()];

            return response()->json($response, $status);
        }

        return parent::render($request, $exception);
    }
    // ...
}

REST API: Symfony vs. Laravel

As you can see, for a typical REST API, Laravel is much simpler than Symfony.

Picking the Winner: Symfony or Laravel?

There’s no clear winner between Laravel and Symfony, as everything depends on your final goal.

Laravel is a better choice if:

  • This is your first experience with the framework, as it’s easy to learn and has a simpler syntax and better learning materials.
  • You’re building a startup product and checking your hypothesis, as it’s good for rapid application development and Laravel developers are easy to find.

Symfony is the best option if:

  • You’re building a complex enterprise application, as it is very scalable, maintainable, and well structured.
  • You’re building a migration of a big long-term project, as Symfony has predictable release plans for the next six years, so it’s less likely that there will be any surprises.

About the author

Karim Sakhibgareev, Russia
member since July 27, 2016
Karim is a PHP developer with over ten years of experience creating web applications from scratch, developing projects from architecture to launch, making high-load optimizations, and refactoring legacy code. He combines expert knowledge with a keen problem-solving skill. [click to continue...]
Hiring? Meet the Top 10 Freelance PHP Developers for Hire in August 2017

Comments

Grynn
A small note: Laravel has valet (https://laravel.com/docs/5.4/valet) which make debugging and testing locally much, much easier than Homestand/Vagrant etc. It's incredible!
Nick
In Symfony you can use ParamConverter from SensioExtraBundle and instead this: public function indexAction($id) { $repository = $this->getDoctrine()->getRepository('BlogBundle:Post'); $post = $repository->find($id); if ($post === null) { throw $this->createNotFoundException(); } return $this->render('BlogBundle:Post:show.html.twig', ['post'=>$post]); } Do just this: public function indexAction(Post $post) { return $this->render('BlogBundle:Post:show.html.twig', ['post'=>$post]); } With this simple way you get a post or a 404.
Karim Sakhibgareev
I agree, Valet is nice tool, but Valet requires macOS. What's why I decided not to talk about it in this article.
Jakub
If the first thing you do, after starting a new project is choosing framework, then I feel sad for you.
Sorin
Hello. You should include Yii (http://www.yiiframework.com) in the Contenders list and maybe change the "duel" with a "truel" :)
Karim Sakhibgareev
Hi Nick, I also like the way Symfony forces you to do better design.
Karim Sakhibgareev
Actually I should include CodeIgniter too and we'd have quartet here, but no chance to put it all in one article :)
Luis Galaz
FYI ... "Today, when starting a new project, one of the key decisions is to pick the right framework. It’s become hard to imagine building a complex web application from scratch nowadays without one."
Emir Karşıyakalı
You need to careful when say "very scalable, maintainable, and well structured". These arguments belongs to developer. Not a framework thing. So Laravel also very scalable, maintable and well structered If you know what you do. Both of them are MVC framework so If you don't enable services, or don't use "services.yml" Symfony being also not maintainable, well structered. I don't want to say anything about scalable argument. You have to remove it, really.
Pramod
CakePHP is best, Personally I used many frameworks.
Nazareno Lorenzo
Although it is created and maintained by Laravel, Valet also supports symfony! :)
Luis Galaz
@karimsakhibgareev:disqus I think that around the time Laravel 5.4 was released, there was also some announcement in Laravel News on Valet being available on linux.
Michael Houghton
I would have thought choosing a framework is a logical step when starting a new project. Pick a framework based on the best choice for each project - which may not be your own personal preference.
Théo FIDRY
If you want to compare APIs, I think a more fair duel for out of the box solutions is Lumen & ApiPlatform :)
Roman Kuznetsov
oh... This article is sucks.. And I gonna explain why.. Karim, you have to learn Framework BEFORE you compare it )))) 1. yaml format is a common way to configure many things. Symfony allow XML, PHP, YML configuration and XML is used frequently. So you see that Laravel sucks in this case. 2. Routing: Symfony routes could (and it's preferable way) be configured in route files and not directly at a controller. You said yml is shit? you can include one controller routes into another building trees... I do not see why you choose Laravel in this case. 3. Template systems.. I do not see why you choose Blade over Twig. Direct PHP in templates could lead you to output problems easier. e.g. you have a temptation to write more PHP in templates then you need. So basically TWIG is better in this case 4. DependencyInjection comparison makes me laugh again.. Karim, you really lack of knowledge ))) autowire is not good thing. but yes it could help sometimes. Also.. Did you hear about Compilation process in Symfony? It allows override services its definition and Symfony has such thing as Extension. where you configure your bundle and prepare parameters for your services.. I can't say many about Laravel.. And you has shown to us that you do not know Symfony at all 5. About FOSrestBundle.. hm.. you didn't show that Laravel has some kind of REST feature at all.. man.. If you need to fetch only POST or GET requests for an controller's action then you can accomplish that WITHOUT FOSRestBundle.. you could configure route to fetch POSTs only. FOSRest DO NOT WRAPS exceptions to JSON.. it wraps exceptions to that format that you use. This is very bad comparison.. I've just explained that you need to learn Symfone deeper that first 2 how-to on their site ))) I'm very sad, Karim. Do not write such articles anymore or people will think that you are not clever person
Roman Kuznetsov
I'd suggest Phalcon if you need speed.. that's good framework. you will see as soon as try it
Matteo Galli
This article lacks a lot of details. First and foremost the fact that Symfony is the go-to choice for enterprise grade applications because of its robust and rigorous approach to software engineering, in fact many components created by Symfony team are also at the base of other projects, including Laravel itself (this is a huge details that was not mentioned). More often than not Laravel looks like a nice tool to play around with a side project or webagency-style project, something you just need to release quickly and you don't care much about architecture. This is something you can see for example in Twig vs Blade where Twig doesn't allow php code to be executed and instead forces you to create an app extensions that can be used again and leave your template code clean.
Karim Sakhibgareev
@disqus_QyjNpN80x3:disqus great news, I missed it. In Laravel 5.4 docs macOS is still a requirement.
Karim Sakhibgareev
Hi Roman, your comment makes me feel like in a holy war that is expected in comparison topics. Let's discuss your points: 1. Symfony allows several formats and YAML is used by default that's why it was used for the article. For people who didn't work with YAML native PHP might be more comfortable, but since you are good with YAML it is a better choice. For me YAML is better because as I said in the article: "it prevents you from injecting complex PHP logic in the YAML configuration." 2. I didn't say that yaml is a shit, where did you get it? Annotation routes is a nice feature to show it in the article though you can use YAML. 3. I like Twig more, I didn't choose any in this article. I said: "Twig does not allow any direct PHP code in templates" and for me, this is a winning point, but somebody might think another way. 4. Happily, I heard about it. You can configure your Symfony bundle in Extension class and Laravel app in Service Provider. But how does it refer to the topic? 5. I covered GET, POST, PATCH and DELETE requests. I think this is enough for the starting point of understanding in case you didn't work with these frameworks before. In the case of building JSON API FOSRestBundle wraps exceptions to JSON. I agree that FOSRestBundle is a much more powerful package, but this article is not about FOSRestBundle. FOSRestBundle with it's edge cases is worth separate article. 6. Again as with FOSRestBundle: JMSSerializerBundle is a very powerful package and that's why it is so popular. Topic example doesn't show the edge cases of using it but points developers attention to its existence as in real life API you should use it for sure. I see that every point can be covered more detailed and this is nice that you know it, but this article is focused on developers who might not be experienced with these framework and choosing one to learn.
Karim Sakhibgareev
Hi Matteo, I respect your opinion, that sounds similar to my own. Please take a look at "The Contenders" section of the article where I am saying: "Symfony components can serve as great code examples and they are used in a lot of open source projects such as Drupal, phpBB, and Codeception. In fact, Laravel itself uses no less than 14 Symfony components." I also pointed as an example that Twig doesn't allow you to inject php code and forces you to create reusable filters that is benefit for me. Your conclusions are similar to ones in "Picking the Winner" section but said in other words.
Karim Sakhibgareev
Hi Emir, speaking about maintainable I think that the term "if you know what you do" is not an argument. With the same words you can say that building your app on raw PHP without any framework is as maintainable as with good framework, but it doesn't work in a real word working in a team. When we are speaking about maintainability, we also assume how we can maintain app that was built by other developers, how easy we can update the app, refactor, etc. Such a small things as the abilities to inject PHP code in configuration files and in templates in Laravel reduces the maintainability, for example. You can say that you shouldn't do it, but Laravel allows you to do it while Symfony forces you not to do it.
Roman Kuznetsov
This article shows that Laravel is better but it's fake. It's fake comparison. If I do not know Symfony I 'd choose Laravel. I wanted to say that you hadn't written any argument but just had said that Laravel was better. With due respect to you, I'd delete this article or spend on it more time if you really need to post that
Karim Sakhibgareev
Roman, why did you decide that I had said that? Please read the last section once again, where I am saying that in my opinion Laravel is better if you don't have any previous framework experience or for rapid application development, but Symfony is better for enterprise and long-term projects, i.e. for serious real life projects.
J7mbo
Why, precisely, is autowiring a "bad thing"?
Roman Kuznetsov
It's not bad but there could be such case: if you have a service which depends on Interface and not on specific class autowire wont help. It means that you will write service configuration as you'd done without autowire. That's why I've said that autowire is not a key for every door
Karim Sakhibgareev
In Laravel you can bind Interface to Implementation in Service Provider and use your service with interface dependency without any extra configuration: https://laravel.com/docs/5.4/container#binding-interfaces-to-implementations .
Koray Küpe
Good article. Thank you. Additional note: Yes, Eloquent looks much more friendly for developers and easier to learn than Doctrine BUT it is suitable for applications that doesn't have lots of complex business logic. Eloquent models have their own tests but if we want to test some particular requests we need add it some abstraction like repositories. Doctrine is more suitable for applications, more natural and flexible because it cares more about object oriented. Easier to refactor. Entities can work without the ORM or DB. We design entities first. We model our domain and than define the database. It doesn't allow collection access from outside the entity.
miholeus
It's nice to use Laravel for rapid development. But I'd prefer Symfony for long-termed projects, that's for sure :) And I'd not use Eloquent at all. I advise to use Analogue ORM instead. But Doctrine remains the best. Thanks to author for his thoughts.
Roman Kuznetsov
Exactly! what I've said: it's additional configuration. Is it able to bind more then 1 class for the same interface? If no.. then it's a crutch...
Karim Sakhibgareev
Yes it is possible - it is named Contextual Binding. Returning to your first argument: imagine you have 5 services that have dependency from 1 interface. Without autowire you'd define service configurations for all 5 services, using autowire you'd define only one configuration for interface, but you wouldn't need to define configurations for 5 services. So it is not the same as you'd done without autowire, it's a big difference.
J7mbo
In the example you provided, autowire *will* help, depending on the auto-wiring you are using. Some auto-wiring injectors still automatically inject a default implementation if only one concrete is available at runtime when you typehint for an interface. Just because you have interfaces for some things and still require configuration doesn't mean that auto wiring is not the next logical step for dependency injection. There are a *load* of concretes you will still inject unless your business case demands otherwise - your http client for example. Unless you're building an application that calls for multiple different http clients, most 'just work'. Just pull in guzzle and be done with it. If you still write service configuration as you have done before, yet *also* have the additional capabilities auto wiring provides should you want to use them, then you might as well just use auto wiring. It's not one of those things where "it's useful for this instance and not useful here" - you might as well have the ability to use it if you want to, it's the next step up.
Roman Kuznetsov
Symfony allows to use service templates, abstract services. so that won't take more time then Laravel configuration. ))
dojovader
Coming from ZF2 Symfony looks carefully structured and clear and also one important part very flexible. However am still looking for more articles on the Internals of Symfony, I'd like to know different phases such as the Event Listeners and where/how to track listeners.
Jorge S.
Hi, after reading the article I have some doubts. How do you avoid injecting EntityManager everywhere where you put "perform save to DB here", and why you chosen to use a PostSubscriberNotifier service instead of making it an Event and EventListener? Thanks!
Karim Sakhibgareev
Hi Jorge, thanks for good questions. 1. I put "perform save to DB here" in PostRepository that inherits EntityRepository so you can use `$this->getEntityManager()` in methods of a class. I omitted it in "DI" section to focus on the subject and described it in "Object Relational Mapping (ORM)" section - please check the implementation of `PostRepository` there. 2. Using Event for this certain purpose is better, I wanted to show DI principle and chose it as an example. 3. Actually, in that example I can not access the list of subscribers, class was simplified to focus on DI principle and omit some implementation details. In real life to get the list of subscribers I'd implement Subscriber service and inject this service into SubscriberNotifier class. Then SubscriberNotifier would call some subscriber service method to request the list of subscribers to the topic of published post.
Semen Shashkin
Comparing Symfony and Laravel is pretty much like comparing Linux and Debian. Laravel is running on Symfony kernel. And what is called "Symfony" here is in fact Symfony Standard Edition (currently they call it full-stack framework). ORM? Symfony allows you to use any. Just like Linux allows you to use yum, apt-get, etc.
Semen Shashkin
What's the first thing to do? Have "We'll soon be the bosses" party? As a tech guys, yes, first we're defining initial requirements and then figuring out infrastructure, including framework (which is, yes, one of the key points).
Ehsaan Ehsaan
Hi Karim, I would like to dicuss about a web application project with you. I can't seem to find any method of contacting you other than this page. My Email is ehsaansvp@gmail.com.
Gayan Pathirage
Wonderful article with clear concise information
Karim Sakhibgareev
Thanks for feedback.
TheIrritainer
Yes please also consider phalcon in a comparison. Apart from the installation process (which is a breeze) its just as clean and easy as the big two.
Shahroze Nawaz
I Personally don't like these "VS" topics as Laravel is using many components of Symfony framework and there is no competition between the Two. It's truly your choice and Project nature for which you will select the framework. You can also create a symfony Project by running this simple command <b>composer create-project symfony/framework-standard-edition your_project_name "3.1"</b>
Paul Hendry
i would ignore him - he clearly likes symfony and is disappointed at some criticism he thinks you have said against symfony.. at the end of the day, use whatever you prefer/comfortable with and thats it..
Geordy James
good comparison. Can you make a blog about PHP Frameworks: Choosing Between Laravel and CodeIgniter as codeigniter is the most easiest and most one in india.
Karim Sakhibgareev
At this moment I am not experienced enough with CodeIgniter to write a blog post regarding this subject. Maybe in a year, I would do it or somebody else earlier.
Attila Fulop
I'm fed up a bit with Symfony. Even right now I'm working with Symfony, and it can be incredibly cumbersome to achieve simple things. And it's not because I don't get it, I've been using Symfony since 2006 (with Propel ORM back then) and used to be a kinda big fan of it. I still am to a certain extent, but Laravel's new ways blew me away from it. We've built last year a complex system with Laravel and my experience is that it's actually easier to work with it. It doesn't throw stupid dogmas on you. Yes you can go wrong with it. So can you with Symfony, neither those restrictions can prevent one from writing shitty code. Symfony's forced <em>inject everything</em> paradigm for example often makes things even worse. We have to accept that our team consists of devz with various knowledge levels, and we have to make sure they get along as well. But apart from that, it's often OK to write <code>$object = new ClassNameHere();</code>. I personally find Laravel's service container better for it's straightforward dependency injection / service resolution tactics. It encourages a cleaner practice for coupling via interfaces to service instances. Also it's TDD facilities are much more contemporary out of the box. Just take a look a this video: https://vimeo.com/151390908 A year ago I was deeply sarcastic with Laravel. Even last summer, <a href="https://artkonekt.com/blog/high-traffic-sites-and-the-php-framework-dilemma/">I wrote a blogpost</a>, where I came to the same conclusion as the author of this article: For complex systems and for seasoned developers, Symfony is the right choice. Laravel wasn't my choice, but I'm happy that I was kinda forced into it. I also have to mention that without Symfony we wouldn't have PHP as we have it today. It was one of the most important things to PHP. Symfony has been playing a huge role in converting PHP folks to mature developers. Not to mention Laravel's foundations are Symfony as well. Without Symfony we wouldn't have Laravel. Both frameworks are great, but I think Laravel is not the small dumb brother any more.
Attila Fulop
I used to think that too. And I changed my mind :) I remember like two years ago, we had a discussion with Pawel Jedrzejewski (the author of <a href="https://sylius.org">Sylius</a>) and he told he has never seen someone deviating from Symfony once he got used to it. I understand why he said it. But the ultimate truth is going to get deprecated one day, who knows.
Attila Fulop
True, Eloquent lacks repositories as core concept, and we always use our handmade repositories in Laravel projects as well. Also Doctrine's caching facilities are much more enhanced out of the box. It's also important to mention that they're built on a basically different approach: Data Mapper vs. Active Record pattern. I also lean towards Doctrine and Data Mapper, but I also have to mention I don't always like it and that Eloquent can be used pretty well for complex modeling. Active Record implements some very bad ideas, but it's actually possible to not use the the stupid parts. What I don't like about doctrine for example is that in real-world scenarios the entities often hold a reference to an EntityManager which contradicts the promise of the DataMapper pattern. Still, DataMapper rulez ;)
Attila Fulop
Yeah, Analogue ORM is a great one. They've mixed pretty well Laravel's db/query builder layer and the pretty concept of the DataMapper pattern.
Attila Fulop
Well, for point 4. if you <em>can't say many about Laravel</em>, see https://laravel.com/docs/5.4/packages
Alex
I don't like the whole concept of annotations - particularly in Symfony. It's one thing using them in Unit tests, it's quite another using them as logic for your application. Comments should not be able to break your code. A compiler / Interpreter should be free IMO to ignore commented code without it having an adverse affect on the application.
Mrunal Khatri
It is really a very difficult task to choose between symfony and laravel frameworks. Both of them have their pros and cons so you cant neglect anyone of them at all.
Luis Galaz
Exactly, I think that is important to know the tools at your disposal, how and when to use them.
Joe
You are comparing the wrong things. Who cares about code syntax. I choose Symfony because Laravel breaks backwards compatibility with every minor release, and I have to rewrite big parts of my code while Symfony does not. A Symfony 2.3 project done in 2013 can be transferred to Symfony 2.8 that is maintained until 2019 with not a single code change, can't rely on a Laravel code to upgrade 6 month later... When you get an error in Symfony development mode, you actually know what the error is, in Laravel, it's just some generic error, it can't even pinpoint the file or the line half the time, especially if it is an error in the template...
Joe
The only original things about Laravel are a poorly implemented template engine and a poorly implemented ORM
Paul Aan
I'm a with you! we had same story. I have worked with Symfony when it was beta 2.0. As of now, I'm happy with Laravel as well. Laravel can be Enterprise as well.
Paul Aan
Hello buddy, can you archive this among your project: Time: 1.45 minutes, Memory: 76.00MB OK (841 tests, 2608 assertions) Generating code coverage report in Clover XML format ... done Generating code coverage report in HTML format ... done Generating code coverage report in PHP format ... done > Checking code coverage... Code coverage is 100% - OK! > Checking swagger.json... Regenerating docs /tmp/swagger.json is valid Can you run more than 800 files test(both Functional-20% and Unit Test-80%) less than 2minutes? Go back to your project and look at your Test! 100% coverage or not?
squinter
I had one look at Laravel and all those statics were hurting my eyes (yeah yeah it's all OOP underneath), but another impression I have is that quite a few things that people love about Laravel are things Symfony has moved away from for good reasons. Laravel reminds me a lot of Symfony 1.x. Symfony is your choice if you care about best practice of software engineering.
Leonard Lepadatu
and/or Zephir compiler obviously. The other server compiled framework can be Yii framework
Dad Bot 3000
Symfony has changed a lot since 2006, for the better (much better). It is hard to learn because it is almost completely different than Symfony 1.x back then. Laravel is really just like an improved version of Symfony 1.x. to me.
Attila Fulop
I don't agree with that. I've been working with all versions of Symfony, including the upcoming 4.0 which is currently being cooked. The only thing may resemble Laravel to Symfony v1 is the ActiveRecord ORM. Just look at how Symfony v4 is replacing the parameters.yml with the .env library what Laravel has been using for a while. Symfony v4 is a very good direction btw, look up Fabien's posts.
Dad Bot 3000
.env is a tiny dot in the bigger scheme of things. I think the often forgotten word here is portability. From architecture point of view, Symfony's less magic more decoupling mantra wins is a clear winner. Framework dependency is the big issue in Laravel as it was with Symfony 1.x.
Dad Bot 3000
"Who cares about code syntax" You, a year or two from now? :)
Attila Fulop
.env is a tiny dot, you're completly right. How often do you switch frameworks on existing apps? https://medium.com/@attilafulop/framework-agnostic-php-applications-6d0d622be02c
Dad Bot 3000
If I say that technology is ever changing, everyone would be nodding their head. Yet if I say that framework dependency is to be avoided, everyone loses their minds. Here's my experience: whatever framework you are using today will be obsolete in 3-5 years. A project that has taken off and in production for 5+ years will need to be rebuilt at least once (well, hopefully the developer learned the lesson about portability on that rebuild, otherwise another rebuild will be needed). That's true for all my projects.
Attila Fulop
If I look back to my 5 years old code, I see an amateurish work that needs instant trashing :D
Anthony Benkhebbab
This article so far : "Laravel is way simpler in everything than Symfony but indeed i'm not pushing you to choose Laravel". People reading this kind of article are usually people that never experienced neither and are looking to test a framework for the first time. Pushing people to Laravel, how great, it enforces no good behavior, where as Symfony main focus is consistency and architecture. Writing PHP code in a template is a code smell. First it's hard to use : beside relying on global functions or some computation, why ? MVP has been proven a great model, you should compute your data before rendering your template. There are conditionnal in templating systems because you have to loop in iterables data structure, OR you want to display something only if this condition is met. Twig enforcing filters and functions is a great thing. What if the front-end team isn't really on PHP ? Well with blade good luck with that, with Twig you only have to know that a function is disposed that allows to compute something. Well i'm not saying your article is bad, but you are hiding your preference for Laravel by putting a "Contenders" in the end of the article. You should rename this "why choosing laravel of symfony". The only things you are exposing is "how fast it is to do stuff". Choosing one framework over another on a boilerplate basis is missing the whole point of frameworks in the first place. I, personnaly, still don't know what are the pros of Laravel over Symfony so far.
comments powered by Disqus
Subscribe
The #1 Blog for Engineers
Get the latest content first.
No spam. Just great engineering posts.
The #1 Blog for Engineers
Get the latest content first.
Thank you for subscribing!
You can edit your subscription preferences here.
Trending articles
Relevant Technologies
About the author
Karim Sakhibgareev
PHP Developer
Karim is a PHP developer with over ten years of experience creating web applications from scratch, developing projects from architecture to launch, making high-load optimizations, and refactoring legacy code. He combines expert knowledge with a keen problem-solving skill.