0.00

PHP Frameworks 2023: Symfony, Laravel, Smart.Framework

Image
An overview of 3 popular PHP frameworks for web development to consider:
Symfony vs. Laravel vs. Smart.Framework

An overview of PHP and web frameworks

PHP server-side language is considered to be the most popular programming language that is used for web development. There are many frameworks available for the PHP language that can make it easier to develop web applications by providing a structure for organizing code and various tools and libraries for common tasks.
Some popular PHP frameworks include, in this order:
  • Symfony: a comprehensive PHP framework that provides a set of reusable components and a structured process for building complex web applications, often used as the foundation for many large-scale heavyweight web projects. Download Symfony
  • Laravel: a full-featured, mediumweight, open-source PHP framework that provides a clean and elegant syntax for tasks such as routing, middleware, and dependency injection, mostly used in medium and some large scale projects. Download Laravel
  • Smart.Framework: a lightweight but powerful PHP framework that is known for its speed, flexibility and minimalism (as a general concept) ; it has a small footprint and requires minimal setup, making it a good choice for developers who want to get up and running quickly and run large projects at amazing loads with a much higher execution speed than most of the other frameworks ; this particular framework was considered for this article because is something quite different than Laravel and Symfony as concept, architecture, usage and developer experience. Download Smart.Framework
There are many PHP frameworks available, and the right choice will depend on your specific needs and preferences, but for this article only these 3 frameworks were considered.


Symfony 6.2 - overview

Symfony Logo
  • Components: provides a set of more than 50 standalone PHP components that can be used to build web applications. These components cover a wide range of functionality, including HTTP handling, routing, form creation, and more.
  • Dependency injection: implements a PSR-11 compatible service container that allows you to standardize and centralize the way objects are constructed in your application.
  • Modularity (supported): Symfony 6.2 as previous versions supports Bundles. "A bundle is similar to a plugin in other software. ... The core features of Symfony framework are implemented with bundles."
  • Templating engine: includes a powerful templating engine called Twig that provides a simple and flexible way to define and render views for your application.
  • Database support: it supports a variety of database systems via Doctrine, including MySQL/MariaDB, PostgreSQL, and SQLite. It provides both: a DBAL component and also an easy-to-use ORM (object-relational mapper) which makes the process of interacting with databases being very easy and affordable even by junior developers.
  • Routing: provides a flexible routing system that allows you to define routes for your application and map them to specific controller actions. In the last versions it include also an alternative way of creating routes using a native way to import routes from a PSR-4 namespace with annotations.
  • Security: includes a range of security features, such as input validation and sanitization and support for secure cookies. It may include also a cross-site request forgery (CSRF) protection which can be provided by an extra vendor library. It does not provide by default any user authentication system (but it may be included one by external components).
  • Console: includes a console component Symfony-CLI that allows you to create command-line tools and scripts for tasks such as database migrations and seeding.
  • Code Deploy: N/A.
  • Sample Code: a HTML "HelloWorld" Page and a "Sample (JSON) Api"
    • Route definitions:
      As of Symfony 6.2 with Annotations, the route can be defined as comment directly in the PHP Controller.
      See below this definition: #[Route('/some-route', name: 'someRouteMethod')] just above the method.
      In the HelloWorld Controller will have one route: /hello-world.
      In the SampleApi Controller will have a different route: /api/sample.

    • Controller: src/Controller/SampleApi.php
      <?php
      
      // Symfony 6.2: Sample Controller: SampleApi.php
      // outputs: application/json
      
      namespace App\Controller;
      
      use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
      use Symfony\Component\Routing\Annotation\Route;
      use Symfony\Component\HttpFoundation\Response;
      use Symfony\Component\HttpFoundation\Request;
      
      final class SampleApi extends AbstractController {
      
          #[Route('/api/sample', name: 'sampleApiService')]
          public function sampleApiService(Request $request): Response {
      
              $getVars = (array) $request->query->all(); // vars from $_GET
              $postVars = (array) $request->request->all(); // vars from $_POST
              // Symfony does not provide a native way to get all request variables at once as $_REQUEST = [ $_GET + $_POST ], inflexible
      
              $response = new Response((string)\json_encode(
                  [
                      'code'      => 200,
                      'status'    => 'OK',
                      'message'   => 'This is a sample API.',
                      'data'      => [ 'generator' => 'Symfony 6.2' ],
                  ]
              ));
              $response->headers->set('Content-Type', 'application/json');
              //$response->headers->set('Content-Type', 'text/json');
      
              return $response;
      
          }
      
      }
      
      // #end
      
      
    • Controller: src/Controller/HelloWorld.php
      <?php
      
      // Symfony 6.2: Sample Controller: HelloWorld.php
      // outputs: text/html
      
      namespace App\Controller;
      
      use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
      use Symfony\Component\Routing\Annotation\Route;
      use Symfony\Component\HttpFoundation\Response;
      use Symfony\Component\HttpFoundation\Request;
      
      final class HelloWorld extends AbstractController {
      
          #[Route('/hello-world', name: 'helloWorldPage')]
          public function helloWorldPage(Request $request): Response {
      
              return $this->render('views/hello-world.twig.htm',
                  [
                      'title'     => 'Hello World',
                      'random'    => (int) rand(100, 999),
                  ]
              );
      
          }
      
      }
      
      // #end
      
      
    • View: templates/views/hello-world.twig.htm
      {% extends "template.twig.html" %}
      
      {% block title %}{{ title }}{% endblock %}
      
      {% block main %}
      <!-- Symfony 6.2: Sample View: hello-world.twig.htm -->
      <h1>{{ title }}</h1>
      This is a sample random number: <q>{{ random }}</q>.
      {% endblock %}
      
    • Template: templates/template.twig.html
      <!DOCTYPE html>
      <!-- Symfony 6.2: Sample Template: template.twig.html -->
      <html>
      <head>
      <meta charset="utf-8">
      <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta name="generator" content="Symfony 6.2">
      <link rel="icon" href="data:,">
      <title>{{ title }}</title>
      </head>
      <body>
      {% block main %}{% endblock %}
      </body>
      </html>
      


Laravel 9 - overview

Laravel Logo
  • Components: provides a set of more than 80 standalone PHP components that can be used to build web applications. It even includes a subset of some Symfony components.
  • Dependency injection: uses an advanced dependency injection container that allows you to manage the dependencies of your application and inject them into your classes as needed.
  • Modularity (unsupported since some versions ago): the latest versions of Laravel just dropped any support for modularity which makes the entire Laravel ecosystem being hard to keep reusable code that can be shared among projects. This somehow forces each developer / team to publish the code using the vendor components system with composer. But there are drawbacks using this way of approach as a module can contain more than just portable code libraries such as: templates, views, javascript, css, default settings.
  • Templating engine: The built-in Blade templating engine provides a simple and efficient way to define and render views for your application.
  • Database support: supports a variety of database systems via Eloquent such as MySQL, PostgreSQL, and SQLite. It also includes an ORM (object-relational mapper) that simplifies the process of interacting with databases.
  • Routing: provides a simple and expressive routing system that allows you to define routes for your application and map them to specific controller actions. The routes are split in several parts: web, api, channel, console.
  • Security: it includes an almost complete range of built-in security features as: input validation / sanitization, support for secure cookies, a default enabled cross-site request forgery (CSRF) protection, a generic user authentication system: sanctum.
  • Console: Artisan CLI is a command-line interface that provides a range of tools and commands for tasks such as database migrations and seeding, queue management, and more.
  • Code Deploy: N/A.
  • Sample Code: a HTML "HelloWorld" Page and a "Sample (JSON) Api"
    • Route definitions:
      The routes in Laravel have different places to setup depending of the area.
      For the HelloWorld Controller the route: /hello-world have to be setup in routes/web.php.
      For the SampleApi Controller the route: /api/sample have to be setup in routes/api.php.
      Setting up routes/api.php
      <?php
      
      use Illuminate\Support\Facades\Route;
      use Illuminate\Http\Request;
      
      // Laravel 9: Sample Route Definition ; area: api ; file: routes/api.php (existing, edited, adding content below)
      
      use App\Http\Controllers\SampleApi;
      
      // route: /api/sample ; all routes here will be prefixed with: /api/
      Route::match(['GET', 'POST'], '/sample', [SampleApi::class, 'handleSampleApi']);
      
      // #end
      
      
      Setting up routes/web.php
      <?php
      
      use Illuminate\Support\Facades\Route;
      use Illuminate\Http\Request;
      
      // Laravel 9: Sample Route Definition ; area: web ; file: routes/web.php (existing, edited, adding content below)
      
      use App\Http\Controllers\HelloWorld;
      
      // route: /hello-world
      Route::match(['GET', 'POST'], '/hello-world', [HelloWorld::class, 'handleSampleHelloWorld']);
      
      // #end
      
      

    • Controller: app/Http/Controllers/SampleApi.php
      <?php
      
      // Laravel 9: Sample Controller: SampleApi.php
      // outputs: application/json
      
      namespace App\Http\Controllers;
      
      use Illuminate\Http\Request;
      
      final class SampleApi extends Controller {
      
          public function handleSampleApi(Request $request) {
      
          //  $getVars = (array) $request->query(); // vars from $_GET
          //  $postVars = (array) $request->post(); // vars from $_POST
              $reqVars = (array) $request->all(); // vars from $_REQUEST = [ $_GET + $_POST ] ; much flexible to handle than working with separate $_GET / $_POST
      
              return response()->json(
                  [
                      'code'      => 200,
                      'status'    => 'OK',
                      'message'   => 'This is a sample API.',
                      'data'      => [ 'generator' => 'Laravel 9' ],
                  ]
              )->header('Content-Type', 'application/json'); // or can be 'text/json'
      
          }
      
      }
      
      // #end
      
      
    • Controller: app/Http/Controllers/HelloWorld.php
      <?php
      
      // Laravel 9: Sample Controller: HelloWorld.php
      // outputs: text/html
      
      namespace App\Http\Controllers;
      
      use Illuminate\Http\Request;
      
      final class HelloWorld extends Controller {
      
          public function handleSampleHelloWorld(Request $request) {
      
              return view('hello-world',
                  [
                      'title'     => 'Hello World',
                      'random'    => (int) rand(100, 999),
                  ]
              );
      
          }
      
      }
      
      // #end
      
      
    • View: resources/views/hello-world.blade.php
      @extends('#template')
      
      @section('title'){{ $title }}@endsection
      
      @section('main')
      <!-- Laravel 9: Sample View: hello-world.blade.php -->
      <h1>{{ $title }}</h1>
      This is a sample random number: <q>{{ $random }}</q>.
      @endsection
      
    • Template: resources/views/#template.blade.php
      <!DOCTYPE html>
      <!-- Laravel 9: Sample Template: #template.blade.php -->
      <html>
      <head>
      <meta charset="utf-8">
      <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta name="generator" content="Laravel 9">
      <link rel="icon" href="data:,">
      <title>{{ $title }}</title>
      </head>
      <body>
      @yield('main')
      </body>
      </html>
      


Smart.Framework 8.7 - overview

Smart.Framework Logo
  • Components: it includes a base system of 42 standalone portable classes (components) and some other 28 framework dependent classes.
  • Dependency injection: uses a standard auto-loader based dependency injection system that allows you to easy manage all the dependencies of your new created application library modules and inject them into your classes as needed.
  • Modularity (full supported): it have a modular architecture, which is a very valuable feature of this framework as the concept of portable code and reusable modules allows you to easily organize and reuse code across your application. Any new created / custom developed module can be reused in other projects and each particular module can contain: controllers, namespaced libraries (that can be reused in other modules), templates, views, javascript and css.
  • Templating engine: the built-in Markers-TPL (provided as default) is a powerful REGEX based templating engine that provides a low level grained control of variables, context based escapings, conditionals and loop cycles. This templating engine was inspired from Typo3 markers and developed later as a standalone and real templating engine all in Smart.Framework. The difference between this templating engine and the above ones is that it does not apply a default escaping by default, all variables must be explicit escaped depending on context, which makes the development more attractive by always thinking of the context and how to use a variable. At some glance it looks like a templating engine to be designed and used by more experienced developers, but with a very important security advantage: not even a piece of executable (PHP) code can be injected and re-interpreted in a template like this since it does not interpret executable code at all. More, this templating engine was ported to Javascript and Go Language as well as the first version written entirely in PHP, being a full portable templating engine. It also supports Twig, Twist or Typo3Fluid (provided as separate modules) as an alternative to it's default, built-in templating engine.
  • Database support: supports many database systems, including native support for Redis, MongoDB, MySQL, PostgreSQL, SQLite and DBA. It also includes some separate modules for easing the way of working with databases (Laminas DBAL) and an object-relational mapper (ORM) and a query builder (RedBean ORM).
  • Routing: this framework includes a simple but powerful routing system that allows you to define routes for your application and map them to specific controller actions. The support for extra features like SEO pretty-print routes can be achieved by example if using .htaccess and Apache Mod Rewrite.
  • Security: provides a range of built-in security features: input validation and sanitization, a sandboxed file system, secure cookies. It also provide a very interesting feature: a complete separation between 2 areas: frontend (index) area which is complete separated from backend (admin) area not only by using a different authentication system and accounts, but also at the code level execution. By default includes a zero-configuration, built-in, extendable authentication system for single or multi-user accounts on the backend area. It looks like the frontend authentication system have to be built (as considered) depending on the need of each particular project, but once that such system is built it can be reused as a module in other projects based on this framework as reusable code. It does not provide a CSRF by default but provides a very intelligent CAPTCHA which is a much more solid concept to protect a form from robots or flooding.
  • Console (provides a web based service, similar with CLI): the Task Area, a web based service (derived from the backend/admin area) which is quite similar with the console CLI scripts provided by other frameworks. There are advantages and disadvantages. The main advantage is that using a web based script can run remote tasks. The disadvantage is that needs some configuration before being used for the first time comparing with a CLI script which require zero configuration and can be used immediately.
  • Code Deploy: it includes all: a built-in code deploy packaging system, a javascript / css minify system (using NodeJS as external component), a web script to easy the management of code deploy over one or multiple remote servers.
  • Sample Code: a HTML "HelloWorld" Page and a "Sample (JSON) Api"
    • Route definitions:
      The default routes in Smart.Framework are always using a combination of the module name suffix and the PHP Controller file name prefix, separed by a dot.
      Example: mod-abc/test-controller.php will use the page route: abc.test-controller.
      So, mod-demo/hello-world.php will use the page route: demo.hello-world and so on.
      Thus the default route for the HelloWorld Controller would be: /?page=demo.hello-world.
      And the default route for the SampleApi Controller would be: /?page=demo.sample-api.
      If there is no need for SEO, the built-in routing system in Smart.Framework allows using a more easy (semantic) route instead without any additional setup as: /?/page/demo.hello-world (for the hello world) OR /?/page/demo.sample-api (for the sample API).
      But, for the SEO purposes having a nice pretty route is a must. An .htaccess rewrites file will have to be used, like in this example, for the Apache web server rewrites. For Nginx or other web servers the rewrite concept is similar but differs (not explained here).
      What we want to set below (for SEO) is having nice routes like /hello-world.html instead of the /?page=demo.hello-world and /sample-api.json instead of the /?page=demo.sample-api.
      # Sample (apache) .htaccess for pretty SEO routes, for Smart.Framework
      # below there are very particular settings to be clear how to define custom routes
      # in practice more general rules can be implemented such as ([a-z0-9\-])\.html or even more particular rules
      <IfModule mod_rewrite.c>
          RewriteEngine On
      
          # defining a custom rewrite rule to handle /hello-world.html as index.php?page=demo.hello-world
          RewriteCond    %{REQUEST_FILENAME} !-f
          RewriteCond    %{REQUEST_FILENAME} !-d
          RewriteRule    ^hello\-world\.html$    index.php?page=demo.hello-world    [QSA,L]
      
          # defining a custom rewrite rule to handle /sample-api.json as index.php?page=demo.sample-api
          RewriteCond    %{REQUEST_FILENAME} !-f
          RewriteCond    %{REQUEST_FILENAME} !-d
          RewriteRule    ^sample\-api\.json$    index.php?page=demo.sample-api    [QSA,L]
      </IfModule>
      
      After setting the above content in .htaccess and having Apache with mod_rewrite enabled, the route has become: /hello-world.html.

    • Controller: modules/mod-demo/sample-api.php
      <?php
      
      // Smart.Framework 8.7: Sample Controller: sample-api.php
      // outputs: application/json
      
      define('SMART_APP_MODULE_AREA', 'INDEX'); // allow this controller to run just in frontend area (not in backend or task area, as the purpose of this example)
      
      final class SmartAppIndexController extends SmartAbstractAppController {
      
          public function Initialize() {
      
              $this->PageViewSetCfg('rawpage', true); // make this page a raw response that can be any format (bypass the default text/html with templating)
              $this->PageViewSetCfg('rawmime', 'application/json'); // or can be 'text/json' ; set the mime type here
              $this->PageViewSetCfg('rawdisp', 'inline'); // set the mime disposition here
      
          }
      
          public function Run() {
      
              // Smart.Framework provide a native way to work only with $_REQUEST = [ $_GET + $_POST ], not with separate $_GET / $_POST variables, which still can be accessed via PHP internals
              // internal philosophy: separing request variables by GET or POST is a bad practice that should not be encouraged, avoid duplication due to extra memory consumption
              $reqVars = (array) $this->RequestVarsGet(); // vars from $_REQUEST = [ $_GET + $_POST ] ; much flexible to handle than working with separate $_GET / $_POST
      
              $this->PageViewSetVars([ // render the raw page ; raw pages have only one output channel (variable): MAIN
                  'MAIN' => (string) Smart::json_encode(
                      [
                          'code'      => 200,
                          'status'    => 'OK',
                          'message'   => 'This is a sample API.',
                          'data'      => [ 'generator' => 'Smart.Framework 8.7' ],
                      ]
                  )
              ]);
      
              return 200; // HTTP 200 OK status
      
          }
      
      }
      
      // #end
      
      
    • Controller: modules/mod-demo/hello-world.php
      <?php
      
      // Smart.Framework 8.7: Sample Controller: hello-world.php
      // outputs: text/html
      
      define('SMART_APP_MODULE_AREA', 'INDEX'); // allow this controller to run just in frontend area (not in backend or task area, as the purpose of this example)
      
      final class SmartAppIndexController extends SmartAbstractAppController {
      
          public function Initialize() {
      
              // the Smart.Framework Template have to be set in the Controller not in the view like Symfony or Laravel does
              // this concept is quite interesting because it allows to dynamic change the rendered templates for the same views directly via the controller
      
              // set template path to this module ; this can be changed anytime in the Run() method below if needed
              $this->PageViewSetCfg('template-path', '@'); // will search for templates in `modules/mod-demo/templates/`
      
              // set the default template for this controller ; this can be changed anytime in the Run() method below if needed
              $this->PageViewSetCfg('template-file', 'template.html'); // will use the `template.html` searching the above path
      
          }
      
          public function Run() {
      
              $title = 'Hello World';
              $this->PageViewSetVars([ // render the template which have 2 variables: MAIN and TITLE
                  'TITLE'     => (string) $title, // TITLE is html escaped in template using |html
                  'MAIN'      => (string) SmartMarkersTemplating::render_file_template( // not escaped because this should be HTML code not text
                      (string) $this->ControllerGetParam('module-view-path').'hello-world.mtpl.htm', // render the view which have 2 variables: TITLE and RANDOM
                      [
                          'TITLE'     => (string) $title, // TITLE is html escaped in view using |html
                          'RANDOM'    => (int) rand(100, 999), // RANDOM is html escaped in view using |int which is better in this case than |html
                      ]
                  )
              ]);
      
              return 200; // HTTP 200 OK status
      
          }
      
      }
      
      // #end
      
      
    • View: modules/mod-demo/views/hello-world.mtpl.htm
      <!-- Smart.Framework 8.7: Sample View: hello-world.mtpl.htm -->
      <h1>[###TITLE|html###]</h1>
      This is a sample random number: <q>[###RANDOM|int###]</q>.
      
    • Template: modules/mod-demo/templates/template.html
      <!DOCTYPE html>
      <!-- Smart.Framework 8.7: Sample Template: template.html -->
      <html>
      <head>
      <meta charset="utf-8">
      <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta name="generator" content="Smart.Framework 8.7">
      <link rel="icon" href="data:,">
      <title>[###TITLE|html###]</title>
      </head>
      <body>
      [###MAIN###]
      </body>
      </html>
      


A Comparison of the features provided by each framework

Built-In Feature Symfony Logo Symfony 6.2 Laravel Logo Laravel 9 Smart.Framework Logo Smart.Framework 8.7
Concept / Philosophy Best Practices, Standardization Enjoyable, Creative Experience Performance, Flexibility, Minimalism
License MIT (Open Source) MIT (Open Source) BSD (Open Source)
Web Developer Experience
(Target Level)
Medium
experienced web developers
Low
entry-level web developers
Advanced
expert web developers
Classification
(Web Development purposes)
Like a Truck
Heavyweight, Tons of Extra Features,
A bit Slower, Higher Resources Usage
Moderate
Mediumweight, Lot of Extra Features,
Fast Enough, Moderate Resources Usage
Like a Race Car
Lightweight, Flexible, Modular Extra Features,
Extremely Fast, Low Resources Usage
Peak Memory Consumption
("SampleApi" + "HelloWorld" Avg.)
2.38MB 1.42MB 0.38MB
Speed Benchmark
("SampleApi" + "HelloWorld" Avg.)
Concurrency Level: 25
126 requests/second
time: 216.244 msec (mean) / request
Page Speed not friendly
177 requests/second
time: 143.198 msec (mean) / request
Page Speed enough friendly
458 requests/second
time: 52.068 msec (mean) / request
Page Speed very friendly
Testing Environment
(CPU: i7 gen12, RAM: 32GB)
Apache/HTTPS/PHP8.1
Env:Prod, Debug:OFF
Apache/HTTPS/PHP8.1
Env:Prod, Debug:OFF
Apache/HTTPS/PHP8.1
Env:Prod, Debug:OFF
SEO Friendly Routes (standard)
(Example, "HelloWorld" Page)
Yes
/hello-world
(internal, uses also .htaccess rewrites)
Yes
/hello-world
(internal, optional .htaccess rewrites)
Yes
/hello-world.html
(requires .htaccess: rewrites)
Structure: Controllers
(Example, HelloWorld - Path)
src/Controller/
HelloWorld.php
app/Http/Controllers/
HelloWorld.php
modules/mod-demo/
hello-world.php
Structure: Views
(Example, HelloWorld - Path)
templates/views/
hello-world.twig.htm
Templating: Twig
resources/views/
hello-world.blade.php
Templating: Blade
modules/mod-demo/views/
hello-world.mtpl.htm
Templating: Markers-TPL
Persistent Cache Support Yes
Redis, Memcached, Couchbase, Files
Yes
Redis, Memcached, DynamoDB
Yes
Redis, MongoDB, DBA, SQlite
Database Connectors Yes
Doctrine
SQLite, PostgreSQL, MySQL/MariaDB, MsSQL, IbmDB2, Oracle
Yes
Eloquent
Redis, SQLite, PostgreSQL, MySQL/MariaDB, MsSQL
Yes
LibSmartDB
Redis, MongoDB, SQLite, PostgreSQL, MySQL/MariaDB
Console / Task Management Yes
CLI
Yes
CLI
Yes
Web-Based
Code Deploy Management No
 
No
 
Yes
AppCodePack/Unpack
Form / Data Security CSRF CSRF CAPTCHA
Target Projects Focus
(most use cases)
Intranet software and tools, Enterprise Grade Applications, Highly customizable web platforms, eCommerce platforms, Booking applications, Social Networking Sites, Online Social Marketplaces, Content Management Systems, Bulletin Board Software, Single Page Websites, Users Account Management platforms, Web based Design and Style Magazines, Web Based Multi-Media Platforms, Custom eLearning platforms, Online multiplayer Games, Online TV Channels. Software-As-Service web applications, On-demand streaming web apps, eLearning web applications, Crypto-Currency or NFT trading platforms, Stock trading based web management systems, Web based applications for managing rewards and recognition, Multilingual CMS systems, Educational Platforms for schools and universities, Small (presentation only) Websites, Large Corporate Websites, Online Business Platforms (ex: invoicing, contract management, ERP systems, Online / Web based eBanking or Retail systems). Various High-end or Medium sized Websites and Web APIs (with focus on SEO best practices, single or multi-language), Mobile Web Applications, Content Management Systems (the integrated PageBuilder module - Markdown based - will easy the content publishing), Hybrid Web Services (integrates well with some other technologies, ex: SmartGo, a Go Language extension framework or NodeJS), Backend Applications (ex: web-based email or repo management), Web based Administration Tasks, Web and Cloud Services (ex: WebDAV, CalDAV, CardDAV).
Conclusions In the beginning, Symfony may be harder to learn compared to other PHP frameworks. Symfony is not so easy to setup and use as Laravel. Requires some web development experience. This framework is enforcing many good practices for developers. It is intended for medium, large or very large projects but it comes with a cost: it almost doubles the cost of the hardware or virtual servers required to achieve the same number of audience than Laravel or Smart.Framework because of the high resources usage. The documentation is very good and comprehensive. Is quite bad that is missing a modular concept because reusable code to be shared between many similar project can be quite mandatory. Lower performance in real-time loading of applications when many users are using the application at the same time. Laravel is very easy to setup and use. Requires almost to none web development experience. Blade and Eloquent are not as good as Twig and Doctrine are because their architecture is not as solid and secure. Laravel has regular updates, which is excellent. But the downside to this is that older versions of the product quickly become buggy. Also, sometimes web developers may face difficulties while updating the new versions of the software. The documentation of Laravel is not as good as Symfony provides. By example it lacks some explanations for the api development and how to disable CSRF protection for particular api routes (which is quite trivial to find this answer by searching the web - elsewhere - just to see than actually you have to add an exception into
app/Http/Middleware/VerifyCsrfToken.php).
"Not so easy to master it", requires a lot of experience from the web developers that will use it in development or production. But it really worth because it allows to achieve huge performance metrics and can target extremely large audience with a reasonable hardware or virtualization cost. More, being a bit more low-level than Symfony or Laravel it allows developers to have a fine control over all aspects which sometimes are very hard to manage in other frameworks. There is one thing to notice: it needs some extra setup before running it in a production environment (ex: rewrite rules for routes, securing the access to some folders: tmp/) and need to work closely with the web servers, load balancer and proxies. It's persistent cache adapter can act on many levels, it can even act like a full featured HTTP Cache layer).


Routing and SEO approach of these frameworks, and what the practice says
Of course Smart.Framework can also implement routes such as /hello-world or /api/sample using rewrite rules in .htaccess (as Symfony or Laravel implement by default, just because Symfony or Laravel are focused on preserving their own standards more than a practical SEO approach), but from the SEO practice and experience by running for many years some high-end (very large traffic) websites Smart.Framework recommends using routes like /hello-world.html instead of /hello-world and /sample-api.json instead of /api/sample.
That is also true that Laravel or Symfony can implement (even if not their standard) routes like: /hello-world.html and /sample-api.json instead of /hello-world or /api/sample.
But to explain a point of view, in the last years the SEO practice shows with better results using sub-domains based routes. This in the case of Smart.Framework is very easy to manage: demo.site.dom/hello-world.html can be easy rewritten as /?page=demo.hello-world and so on. Having this practical sub-domains based routes approach on Symfony or Laravel is more complicate because they are missing the concept of modularity separation of Controllers and Routes, and combining .htaccess rewrites with their own routes could be a bit ... unpredictable.
Also there is one small thing to explain: a Symfony/Laravel route such as /some/route/param1/param2 can be easy rewritten with better SEO results as some-route,param1,param2.html or some-route--param1--param2.html. There are many large and quite important websites with very high SEO rankings that use this approach ... but this article will not cover any debate just explaining two different approaches/standards of using SEO friendly routes.
Why sub-domain based routes are better for SEO ? There are many debates over this approach, but the practice shows that the sub-domain as keyword ranks better than a sub-folder as keyword. Explanation: the keyword "demo" from "demo.site.dom/some-controller(.ext)" ranks better than "site.dom/demo/some-controller(.ext)".


An overall conclusion
The choice remain yours. Of course ! But choosing a web framework or another may have a serious impact over:
  • The size of your development team: choose Symfony if you have medium/large team(s). Or you can choose Laravel if you have small/medium team(s). Or you can choose Smart.Framework if you have small/medium or large team(s) but requires some very experienced web developers to be there ... the overall performance will be just amazing.
  • The developers experience: while Symfony and Laravel are popular, they can be used starting from amateur up to pro area, they are generally easy to jump-in ; frameworks like Smart.Framework are dedicated mostly to the professional area only. The difference would be like using amateur ski equipment vs. professional ski equipment - if you are a pro, you know what you are doing and you want a deep control of the pro like "equipment" where Smart.Framework excels ; if you are not quite a pro then you may risk an "accident" when going with such pro like "equipment" in some environments, so better choose Laravel or Symfony in this case.
  • The development budget: when speaking of single project it really does not matter too much, there are not considerable differences, except that over time Symfony deprecates the most quantity of code versus Laravel or Smart.Framework which are preserving a more solid LTS policy. But if you deal with many projects, you need skilled developers, a solid architecture for your project(s), a good policy to reuse the code as portable libraries or even modules / bundles / packages. All of these have an impact over the budget. Another fact that impacts the development budget is the development team(s) structure(s), what technology they already own, what they can learn, and so on ... It's always a matter of business logic and strategy here (what budget to allocate, what technology to use).
  • The operating cost: this is quite trivial to calculate, but in general the highest output in requests/second generated by a framework, the lowest cost of hardware / virtualization platform.
  • The TCO (total cost of ownership): calculate it simple: "the development budget" + "the operating cost (for 2-3 years)".


Final thoughts about frameworks (in general) vs. development languages
A honest opinion is that developing a web solution in PHP is ~2x faster than developing in NodeJS/Javascript, Python, Java and ~3x faster than Go Lang, Rust, .Net, Swift, Vala and perhaps ~4x faster than choosing C/C++ (in number of total development hours to achieve the same features) - by example working with JSON data except NodeJS/Javascript / PHP / Python becomes quite complicated, almost need a separate structure for each JSON model. But ... as reverse, by example, Go Lang or Rust performance would lower up to 5x - 10x the total operating cost explained above as they have been designed as special technologies for parallel/distributed computing, serverless, with high concurrency modern architectures by default, in their core.
At the end there is no perfect framework. And these 3 PHP frameworks are only a small "atom in the ocean of frameworks". And there are many other frameworks written in different languages than PHP such as Java, Python, Go language, NodeJS/Javascript, etc ... so many ... perhaps too many :-) but is quite good that web developers are having such a large set of options at all.