Get started with Symfony 4

Symfony is indeed a popular PHP framework. With 50M monthly downloads and a strong community is really an option to consider starting your next project with Symfony 4. What I’ll try to show you in this article is answering in questions about how to create your first Symfony 4 project, what have changed from past versions, some step to step explanations about some new features.

What’s new in this version?

The biggest change is given by “Micro by default”. When do we compare with Symfony 3, at the very first step after the installation, the amount of required packages is way lighter! If before the developers were complaining about removing twig, doctrine or swift mailer bundles, now they have only what is really necessary! This is good. As Silex framework by reach end of life at June 2018, the chance of starting small and grow as the project need is proven to be very reliable on this new Symfony version.

After changing the way how the framework is built there are, at least, two more topics that worth to mention. First, there are no bundles by default. Until Symfony 3 we could create separate bundles and work individually with them, now we are developing our application and the architecture is defined by us. Could we do this also before? Yes, sure, inside the default AppBundle. Now on, you need just to create your logic inside your App namespace.

Second, Symfony Flex. This new player is proving to be an awesome creation from SensioLabs. Basically Symfony Flex helps to install and configure project dependencies using recipes. These recipes contain steps to be executed when you manage your dependencies with composer, defining configuration files and other stuff. A great example is, when you require to composer the Doctrine Bundle, you no longer need to add the extra line on AppKernel.php file or the extra configurations at the yaml files as well. Of course, if you are new at this Symfony 4 I guess you no need to worry about this. Please find more details about official and contributors Symfony flex recipes at www.symfony.sh

Create your first (or not…) Symfony 4 project

We no need Symfony Installer anymore! Now, creating a Symfony 4 project relies only on Composer commands. So, do you have Composer and PHP 7.1 installed? Execute then:

$ composer create-project symfony/skeleton sf4App

Please check the output:

Installing symfony/skeleton (v4.0.5)
- Installing symfony/skeleton (v4.0.5): Loading from cache
Created project in sf4App
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 21 installs, 0 updates, 0 removals
- Installing symfony/flex (v1.0.68): Loading from cache

Prefetching 4 packages 🎵
- Downloading (100%)

- Installing symfony/polyfill-mbstring (v1.7.0): Loading from cache
- Installing symfony/console (v4.0.4): Loading from cache
- Installing symfony/routing (v4.0.4): Loading from cache
- Installing symfony/http-foundation (v4.0.4): Loading from cache
- Installing symfony/yaml (v4.0.4): Loading from cache
- Installing symfony/framework-bundle (v4.0.4): Loading from cache
- Installing symfony/http-kernel (v4.0.4): Loading from cache
- Installing symfony/event-dispatcher (v4.0.4): Loading from cache
- Installing psr/log (1.0.2): Loading from cache
- Installing symfony/debug (v4.0.4): Loading from cache
- Installing symfony/finder (v4.0.4): Loading from cache
- Installing symfony/filesystem (v4.0.4): Loading from cache
- Installing psr/container (1.0.0): Loading from cache
- Installing symfony/dependency-injection (v4.0.4): Loading from cache
- Installing symfony/config (v4.0.4): Loading from cache
- Installing psr/simple-cache (1.0.0): Loading from cache
- Installing psr/cache (1.0.1): Loading from cache
- Installing symfony/cache (v4.0.4): Loading from cache
- Installing symfony/dotenv (v4.0.4): Loading from cache
Writing lock file
Generating autoload files
Symfony operations: 4 recipes (20a9cae5ef55c012060a49b09599293b)
- Configuring symfony/flex (>=1.0): From github.com/symfony/recipes:master
- Configuring symfony/framework-bundle (>=3.3): From github.com/symfony/recipes:master
- Configuring symfony/console (>=3.3): From github.com/symfony/recipes:master
- Configuring symfony/routing (>=4.0): From github.com/symfony/recipes:master
Executing script cache:clear [OK]
Executing script assets:install --symlink --relative public [OK]

Some files may have been created or updated to configure your new packages.
Please review, edit and commit them: these files are yours.


What's next?


* Run your application:
1. Change to the project directory
2. Execute the php -S 127.0.0.1:8000 public/index.php command;
3. Browse to the http://localhost:8000/ URL.

Quit the server with CTRL-C.
Run composer require server --dev for a better web server.

* Read the documentation at https://symfony.com/doc

Understanding the output

After Composer finishes his work, we can check that three different tasks were done. The first task is to clone a skeleton structure. After, composer will do the usual task of getting all composer.json dependencies. Finally, Symfony Flex takes in action. As a Composer plugin Flex will execute all recipes from the installed dependencies. As a hint, a message is presented to tell you how to fire up locally your application and suggests you to install a new dependency (we'll cover that later).

The project is created, What’s next?

After the project is done, and before fire it up to browse it, there’s some things to note.

Project repository

One cool “feature” is that a git repository is automatically created. Change your directory to the project’s directory and:

$ git status

In order to keep track of our changes in this article I’ll commit this project, so do not forget to add our remote origin if you want to.

Project structure

With this new version, and looking for the skeleton we really can find a minimal, but powerful version in terms of scalability. Let’s look for the folder directory:

./
├── bin
│ └── console
├── composer.json
├── composer.lock
├── config
│ ├── bundles.php
│ ├── packages
│ │ ├── dev
│ │ ├── framework.yaml
│ │ ├── routing.yaml
│ │ └── test
│ ├── routes.yaml
│ └── services.yaml
├── public
│ └── index.php
├── src
│ ├── Controller
│ └── Kernel.php
├── symfony.lock
├── var
│ ├── cache
│ │ └── dev
│ └── log
└── vendor
├── autoload.php

There’s some changes from the past versions in terms of file structure.

bin/ folder

In this folder you can find application extra helpers. console (Symfony Console component) can be found in this directory to help us to execute commands (we will cover this later) and also a phpunit executable if you require that dependency.

public/ folder

A new folder not seen before. What it was a web/ folder is now a public/ folder. This is the document root for your web application.

Another change at this level is around the FrontControllers, not having anymore the app.php FrontController or app_dev.php FrontController. This way index.php is the only FrontController and the environment is handled by configurations.

config/ folder

This is one of the folders that the developer will handle. All service definitions, parameters, routes and bundle configurations are defined here. So if you want to define your services for the container you will make it at the services.yaml file and (if not using annotations) manage routes in the routes.yaml file.

An important topic is the Environment oriented development. Symfony 4 relies now on Environment Variables for some configuration level. The APP_ENV variable will define if your application behaves as dev, test, prod, or another folder you create inside packages/ folder, and yes, to create an application environment you only have to create a folder inside packages/ folder. To choose which environment to run change the environment variable in the .env file created in the project directory.

src/ folder

It’s a well known code folder. In this folder you will create your application’s logic.

A small change from previous Symfony version is the kernel.php file. As Symfony 4 is no longer a bundle oriented framework this kernel.php will act as your bootstrap logic triggering Container and Routes configuration, but also to let you define later your compiler pass logic overriding build() function.

var/ folder

There’s not too much to say about this folder. Here Symfony will store cache and logs.

Installing your first dependency

Let’s have a better look for Symfony Flex actions when we require a new dependency.

Again, Symfony Flex is a Composer plugin, this means that adds some behaviour to Composer (nothing new in here). So as the composer create-project has suggested, let's require the dependency server. Please note that there's no vendor name on this require like <vendor-name>/<package-name> and this happens thanks to the alias composer feature. If you search at http://www.symfony.sh for the server recipe you will find that server in one of the alias for this Symfony Bundle. So:

$ composer require server

./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 2 installs, 0 updates, 0 removals
- Installing symfony/process (v4.0.4): Loading from cache
- Installing symfony/web-server-bundle (v4.0.4): Loading from cache
Writing lock file
Generating autoload files
Symfony operations: 1 recipe (d7d2fa3d92c4ee1cb95162e0b12f62ab)
- Configuring symfony/web-server-bundle (>=3.3): From github.com/symfony/recipes:master
Executing script cache:clear [OK]
Executing script assets:install --symlink --relative public [OK]

Some files may have been created or updated to configure your new packages.
Please review, edit and commit them: these files are yours.

Understanding the output

Obviously Composer starts by downloading the packages, then Symfony Flex will check for any recipes and execute them (what in this case happened for one recipe). What if we check git status?

$ git status

On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)

modified: .gitignore
modified: composer.json
modified: composer.lock
modified: config/bundles.php
modified: symfony.lock

no changes added to commit (use "git add" and/or "git commit -a")

composer.* files will store dependencies data, symfony.lock will act has the composer.lock file regarding executed recipes and bundles.php enables this new required bundle in the application.

The Symfony Console

So far, we created a new project and required the Symfony server dependency. This dependency is an extended way to use the PHP built-in server to allow you start a web server while developing locally. How can you use it as other useful commands? Using Symfony Console, that one in the bin/ folder.

$ bin/console

Calling console component like above, you will see the full options list of what you can do with it. You should see a list similar to:

Symfony 4.0.4 (kernel: src, env: dev, debug: true)

Usage:
command [options] [arguments]

Options:
-h, --help Display this help message
-q, --quiet Do not output any message
-V, --version Display this application version
--ansi Force ANSI output
--no-ansi Disable ANSI output
-n, --no-interaction Do not ask any interactive question
-e, --env=ENV The Environment name. [default: "dev"]
--no-debug Switches off debug mode.
-v|vv|vvv, --verbose Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug

Available commands:
about Displays information about the current project
help Displays help for a command
list Lists commands
assets
assets:install Installs bundles web assets under a public directory
cache
cache:clear Clears the cache
cache:pool:clear Clears cache pools
cache:pool:prune Prune cache pools
cache:warmup Warms up an empty cache
config
config:dump-reference Dumps the default configuration for an extension
debug
debug:autowiring Lists classes/interfaces you can use for autowiring
debug:config Dumps the current configuration for an extension
debug:container Displays current services for an application
debug:event-dispatcher Displays configured listeners for an application
debug:router Displays current routes for an application
lint
lint:yaml Lints a file and outputs encountered errors
router
router:match Helps debug routes by simulating a path info match
server
server:run Runs a local web server
server:start Starts a local web server in the background
server:status Outputs the status of the local web server for the given address
server:stop Stops the local web server that was started with the server:start command

You can pass as an option the name of the command you want to execute. For instance:

$ bin/console cache:clear

This command will clear your application’s cache.

So did you realise already about the server bundle?

...
server
server:run Runs a local web server
server:start Starts a local web server in the background
server:status Outputs the status of the local web server for the given address
server:stop Stops the local web server that was started with the server:start command
...

With this specific options you can run synchronously the web server or simply start it asynchronously:

$ bin/console server:start

Got the success message? Let’s browse it then!

Recap

What you could get from this article:

  • Create a Symfony 4 Project
  • Read the basic new features and what changed from Symfony 3 to 4.
  • Add dependencies and see Symfony Flex working
  • Browse your first (or not) Symfony 4 application
One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.