Trusted answers to developer questions
Trusted Answers to Developer Questions

Related Tags

php
community creator

How to install Symfony 4

Alessandro Minoccheri

Symfony 4 is the newest version of one of the most famous PHP frameworks. It was released November 30, 2017, and is having great success! One of the biggest differences between this version and older ones is the presence of very small dependencies installed when you init your Symfony 4 project. Symfony 4 is so tiny that the Silex project has been dismissed.

How to Install Symfony 4

In order to create a new Symfony 4 application, you need to have PHP 7.1 (or higher) and Composer installed. With Composer installed, you can create the project by launching this command into your console:

composer create-project Symfony/website-skeleton my-project

This is the command used for traditional web applications that download a Symfony project’s base skeleton with a ready-to-start default configuration. If you are building microservices, console applications, or APIs, consider using the much simpler skeleton project:

composer create-project symfony/skeleton my-project

In this version, there are no bundles installed, so it’s smaller.

Directory Structure

Symfony 4 has changed its directory structure quite a bit in accordance with frameworks and community requests. Now, the new directory structure is:

app/ – The application configuration, templates, and translations where you can find the AppKernel file (the main entry point of an application’s configuration).

bin/ – Executable files (e.g., bin/console).

src/ – The project’s PHP code where you have controllers, templates, and entity directories. There isn’t a main bundle in this folder because Symfony 4’s idea was to have a single project instead of many packages within a project.

tests/ – Automatic tests (e.g., unit tests with PHPUnit, Behat, etc.)

var/ – Generated files (cache, logs, etc.)

vendor/ – External libraries installed by the composer.

public/ – The webroot directory where public and static files are stored like images, stylesheets, and JavaScript files – this folder is the old “web” folder.

Environment Variables

When designing your system, you may want to have different variables that are not the same in other environments. In previous Symfony versions, you would put that variable into a file called parameters.yml in parameters.yml.yourenv. In Symfony 4, that file doesn’t exist (you can change your code to use it, but it’s a little complex), so you have to write those variables in a file called .env in the project root. You can have different .env files, but that will depend on how many environments you have in your application. Here is a sample .env file:

DB_USER=root
DB_PASS=pass

You can also use variables inside it, like this:

DB_USER=root
DB_PASS=${DB_USER}pass

The component reading those files is the Dotenv component that parses .env files to make environment variables stored in them accessible (via getenv(), $_ENV, or $_SERVER). If you don’t already have the Dotenv component in your project, you can launch the following command to form your CLI:

composer require symfony/dotenv

To get the value of an environment variable, use the following syntax inside your code:

$dbUser = getenv('DB_USER');

Remember, Symfony Dotenv never overwrites existing environment variables.

Autowiring

Autowiring is one of the most powerful features in Symfony 4 (you’ve been able to use it since the Symfony 3.3 version). It allows you to manage services in the container with minimal configuration, without specifying, for example, all the arguments that have to be passed to your service (now controllers are also services). So, if you have a service class where you need to pass into the __construct method, know that, with some other services, you’ll only need to enable auto wiring and Symfony will do it for you!

Example:

namespace App\Service;
use App\Util\Bar;
use Psr\Log\LoggerInterface;
class Foo
{
    private $logger;
    public function __construct(LoggerInterface $logger)
    {
        $this->logger = $logger;
    }
}

In the older method, you needed to do this into your services.yml,

app.foo:
class:AppBundle\Services\Foo
arguments:['@logger']

In this new version you can do this:

app.foo:
class:AppBundle\Services\Foo
public: true

So, you’ll only need to specify public as true. Since you have plenty of arguments to declare many services, you will gain save time!

Services aren’t public, so you’ll need to render it true into services.yml:

services:
    _defaults:
        autowire: true
        autoconfigure: true
        public: true

This is the default configuration of your services and, as you can see, it’s under _defaults. If you want to have a different configuration for your service, for example, a private service, you can write this:

services:
    _defaults:
        autowire: true
        autoconfigure: true
        public: true

App\Services\YourService:
class:App\Services\YourService
public: false

So, the Autowire option indicates to Symfony to automatically inject dependencies in your services. The Autoconfigure option indicates that Symfony should automatically register your services as commands, event subscribers, etc.

Controllers are also services, so it’s easy to make unit tests on them instead of using slow integration tests. Now, you can inject services inside your controller, like this:

public function index(LoggerInterface $logger) 
{
    $logger->info('This is a injected service!');
    //code
}

With this action, you can inject LoggerInterface directly without having to instantiate it inside the action!

Flex and Recipes

Symfony Flex is a Composer plugin called when you run the require composer, update composer, or remove composer commands. When you run those flex search commands inside Symfony Flex, the server will take it, install it and configure it for you if the package is on there. The power of Flex is that you don’t have to watch all the libraries’ readme files to configure your package because there is a recipe that does it for you. You don’t need to add your new bundle into AppKernel.php because flex already did it when you install it. If your package doesn’t exist, the server will fallback on Composer standard behavior.

Flex keeps track of the recipes it installed in a symfony.lock file that must be committed to your code repository. Recipes are stored in two different GitHub repositories:

  • Recipe is a curated list of recipes for maintained, high quality packages. Symfony Flex looks into this repository by default.

  • Recipes-Contrib contains all the recipes created by the community. All of them are guaranteed to work, but their associated packages could be unmaintained. Symfony Flex ignores these recipes by default, but you can execute the following command to start using them in your project:

composer config extra.symfony.allow-contrib true

Inside this site Symfony you can view the recipes complete list where you can find how to install them into your project. Sometimes, there is an alias you can use (like the one below) to be faster and remember the command easier:

composer require logger

A recipe contains a manifest.json file where the package configuration is stored. When Flex installs this package, it gets the manifest.json file and applies the default configuration to your project. This way, you can immediately use the new library without writing any configuration.

The messenger component

The messenger component helps applications send and receive messages to/from other applications or message queues. In order to install the component, you need to launch the following from your console:

composer require symfony/messenger

How does it work?

The sender serializes and sends a message to somethinga message broker or a third party API. The bus dispatches the message. The behavior of the bus is in its ordered middleware stack. The component comes with a set of middleware that you can use. When using the message bus with Symfony’s FrameworkBundle, the following middleware is configured for you:

LoggingMiddleware: logs the processing of your messages

SendMessageMiddleware: enables asynchronous processing

HandleMessageMiddleware: calls the registered handle

Once the message is dispatched to the bus, it will be handled by a “message handler”. A message handler is a PHP callablea function or an instance of a class that will do the required processing for your message. In order to send and receive messages, you will have to configure the adapter. The adapter will be responsible for communicating with your message broker or 3rd parties. Then, the receiver deserializes and forwards the message to the handler(s). This can be a message queue puller or an API endpoint.

RELATED TAGS

php
community creator

CONTRIBUTOR

Alessandro Minoccheri
Copyright ©2022 Educative, Inc. All rights reserved
RELATED COURSES

View all Courses

Keep Exploring