Symfony
Translated from German using DeepL.
Date: April 2022
Reading time: 5 minutes
Symfony (opens in a new tab) is a PHP framework that was released in 2005. Many content management systems, such as Drupal (opens in a new tab), rely on Symfony, as it also offers reusable components.
Here you can find all the components of Symfony: https://symfony.com/components (opens in a new tab) On this page you can see which components are used in Drupal: https://symfony.com/projects/drupal (opens in a new tab)
The advantages are that you can work faster and more structured with such a framework. It also provides you with many functionalities. If you need something new, such as a form, you can install this feature. If you want to protect the application with a login, simply install the corresponding feature. This allows you to quickly create secure websites.
The Symfony project has over 3'000 contributors, 600'000 developers and 200 million monthly downloads. It is therefore a recognized and stable environment.
Setup
Requirements
To use Symfony, you must have PHP installed. It is also recommended to install the CLI.
brew install symfony-cli/tap/symfony-cli
You can also use Composer to execute certain commands later. However, this is much easier with the Symfony command.
To check whether all the prerequisites have been met, you can execute the following command.
symfony check:requirements
Create application
Symfony Documentation: https://symfony.com/doc/current/setup.html (opens in a new tab)
You can create a project like this:
symfony new my_project_directory --webapp
If you want to program a microservice, a console application or an API, you can omit the --webapp
.
symfony new my_project_directory
The project can be started with the Symfony command. However, you must first switch to the created project.
symfony server:start
After these few steps you will now see the Welcome page.
Hello World
Symfony Documentation: https://symfony.com/doc/current/page_creation.html (opens in a new tab)
Controller
To create a first page, you must create a controller under src/Controller
.
...
public function index(): Response {
return new Response(
'<html><body>Hello</body></html>'
);
}
...
Route
To make this page accessible, a route must be defined.
There are two variants for this.
YAML
The path can be associated with the controller in the configurations.
app_hello:
path: /
controller: App\Controller\HelloController::index
Annotation
However, I prefer the annotation. It's a bit faster with this. In addition, you can already see in the controller which route it is listening to.
First you have to install the annotations
package.
composer require annotations
You can then use the route annotation.
...
use Symfony\Component\Routing\Annotation\Route;
...
/**
* @Route("/")
*/
public function index(): Response {
return new Response(
'<html><body>Hello</body></html>'
);
}
...
Template
To display the data via a template, you must first install Twig.
composer require twig
You can then render the message in the controller using a template.
return $this->render('hello/hello.html.twig', [
'message' => 'Hello',
]);
This template can then use the message
.
<h1>{{ message }} World</h1>
Twig Doku: https://twig.symfony.com (opens in a new tab)
ORM
Symfony Dock: https://symfony.com/doc/current/doctrine.html (opens in a new tab)
With object-relational mapping
, data is converted in order to exchange it between different systems.
ORM allows you to work with objects in the code. However, these exist in the database as a table.
In order to work in Symfony according to the ORM principle, two packages must first be installed.
composer require symfony/orm-pack
composer require --dev symfony/maker-bundle
The database must then be connected in the configuration file.
DATABASE_URL="mysql://user:pw@127.0.0.1:8889/symfony"
You can create the database manually or in the console.
php bin/console doctrine:database:create
The database has now been created and connected. To create a class, the corresponding command is recommended again.
php bin/console make:entity
Now you can add the attributes very easily.
php bin/console make:entity
Class name of the entity to create or update:
> Sneaker
New property name (press <return> to stop adding fields):
> name
Field type (enter ? to see all types) [string]:
> string
Field length [255]:
> 255
Can this field be null in the database (nullable) (yes/no) [no]:
> no
New property name (press <return> to stop adding fields):
>
(press enter again to finish)
After this step, a class is created. You can see from the ORM mapping remarks that this is such a class.
<?php
namespace App\Entity;
use App\Repository\SneakerRepository;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: SneakerRepository::class)]
class Sneaker
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column(type: 'integer')]
private $id;
#[ORM\Column(type: 'string', length: 255)]
private $name;
public function getId(): ?int
{
return $this->id;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
}
This class can now handle the data locally. However, this information is not yet stored as a table in the database. To do this, the entity must be migrated.
php bin/console make:migration
The SQL required for the migration has now been created. To execute this, the following command must be executed.
php bin/console doctrine:migrations:migrate
Add field
Additional fields can also be added later without any problems.
php bin/console make:entity
You then have to generate a migration again and then synchronize.
php bin/console make:migration
php bin/console doctrine:migrations:migrate
Services
Services can also be implemented in Symfony. This allows you to see which services already exist.
php bin/console debug:autowiring
Create service
<?php
namespace App\Lucky;
class LuckyNumberHandler {
public function getLuckyNumber(int $max): int {
return random_int(0, $max);;
}
}
Such a service can now be used in a method in the controller.
...
use App\Lucky\LuckyNumberHandler;
...
class LuckyController extends AbstractController {
/**
* @Route("/lucky/number/{max}")
*/
public function number(int $max, LuckyNumberHandler $luckyNumberHandler): Response
{
return $this->render('lucky/number.html.twig', [
'number' => $luckyNumberHandler->getLuckyNumber($max),
]);
}
}
If you use the service multiple times, it is better to define it in the constructor. This way, you have to define the handler once and can then use it in the entire class.
...
use App\Lucky\LuckyNumberHandler;
...
class LuckyController extends AbstractController {
private $luckyNumberHandler;
public function __construct(LuckyNumberHandler $luckyNumberHandler) {
$this->$luckyNumberHandler = $luckyNumberHandler;
}
/**
* @Route("/lucky/number/{max}")
*/
public function number(int $max): Response
{
return $this->render('lucky/number.html.twig', [
'number' => $this->luckyNumberHandler->getLuckyNumber($max),
]);
}
}
Thanks to autowiring, all classes in the src/
folder can be used. No further configuration is required.
App\:
resource: '../src/'
exclude:
- '../src/DependencyInjection/'
- '../src/Entity/'
- '../src/Kernel.php'
However, you can also configure a service explicitly.
App\Service\SiteUpdateManager:
arguments:
$adminEmail: 'manager@example.com'
Conclusion
Working with Symfony is very pleasant, as you can progress quickly. The documentation (opens in a new tab) is also, in my opinion, detailed and easy to understand.