2022
Symfony

Symfony

Datum: April 2022
Lesedauer: 5 Minuten


Symfony (opens in a new tab) ist ein PHP Framework, welches im Jahre 2005 veröffentlicht wurde. Viele Content Management Systeme, wie Drupal (opens in a new tab), setzen auf Symfony, da es auch wiederverwendbare Komponente bietet.

Hier findet man alle Komponenten von Symfony: https://symfony.com/components (opens in a new tab)
Unter dieser Seite sieht man, welche Komponenten in Drupal verwendet werden: https://symfony.com/projects/drupal (opens in a new tab)

Die Vorteile sind, dass man mit einem solchen Framework sowohl schneller, als auch strukturierter arbeiten kann. Es stellt einem auch viele FunktionalitĂ€ten zur VerfĂŒgung. Wenn man etwas neues benötigt, wie beispielsweise ein Formular, so kann man dieses Feature installieren. Soll die Applikation mit einem Login geschĂŒtzt werden, installiert man wieder einfach das entsprechende Feature. So kann man schnell sichere Webseiten erstellen.
Das Symfony Projekt hat ĂŒber 3'000 Mitwirkende, 600'000 Entwickler und 200 Millionen monatliche Downloads. Es ist also eine anerkannte und auch stabile Umgebung.

Setup

Voraussetzungen

Um Symfony zu verwenden, muss man PHP installiert haben. Zudem empfiehlt es sich, die CLI zu installieren.

brew install symfony-cli/tap/symfony-cli

Man kann auch Composer verwenden, um spĂ€ter gewisse Befehle auszufĂŒhren. Mit dem Symfony Kommando geht dies aber einiges leichter.
Um zu prĂŒfen, ob alle Voraussetzungen geschaffen sind, kann man den folgenden Befehl ausfĂŒhren.

symfony check:requirements

Applikation erstellen

Symfony Doku: https://symfony.com/doc/current/setup.html (opens in a new tab)

Ein Projekt kann man so erstellen:

symfony new my_project_directory --webapp

Will man einen Microservice, eine Konsolenapplikation oder eine API programmieren, kann man das –-webapp weglassen.

symfony new my_project_directory

Das Projekt kann mit dem Symfony Befehl gestartet werden. Zuvor muss man aber noch in das erstellte Projekt wechseln.

symfony server:start

Nach diesen wenigen Schritten sieht man nun die Welcome Seite.

welcome

Hello World

Symfony Doku: https://symfony.com/doc/current/page_creation.html (opens in a new tab)

Controller

Um eine erste Seite zu erstellen, muss man einen Controller unter src/Controller anlegen.

HelloController.php
...
public function index(): Response {
    return new Response(
        '<html><body>Hello</body></html>'
    );
}
...

Route

Damit diese Seite auch zugÀnglich ist, muss eine Route definiert werden.
Dazu gibt es zwei Varianten.

YAML

In den Konfigurationen kann man den Pfad mit dem Controller assoziieren.

config/routes.yaml
app_hello:
    path: /
    controller: App\Controller\HelloController::index

hello

Annotation

Ich bevorzuge jedoch die Annotation. Mit dieser ist man etwas schneller. Zudem sieht man so schon im Controller, auf welche Route dieser hört.
Vorerst muss man das annotations Paket installieren.

composer require annotations

Danach kann man die Route Annotation verwenden.

HelloController.php
...
 
use Symfony\Component\Routing\Annotation\Route;
 
...
 
/**
* @Route("/")
*/
public function index(): Response {
	return new Response(
		'<html><body>Hello</body></html>'
	);
}
 
...

Template

Um die Daten ĂŒber ein Template anzuzeigen, muss man zuerst Twig installieren.

composer require twig

Danach kann man die Message im Controller ĂŒber ein Template rendern.

HelloController.php
return $this->render('hello/hello.html.twig', [
    'message' => 'Hello',
]);

Dieses Template kann dann die message verwenden.

templates/hello/hello.html.twig
<h1>{{ message }} World</h1>

Twig Doku: https://twig.symfony.com (opens in a new tab)

ORM

Symfony Doku: https://symfony.com/doc/current/doctrine.html (opens in a new tab)

graph

Beim object-relational mapping werden Daten umgewandelt, um diese zwischen verschiedenen Systemen auszutauschen.
Mithilfe des ORM kann man im Code mit Objekten arbeiten. Diese existieren in der Datenbank aber als Tabelle.

Um in Symfony nach dem ORM Prinzip zu arbeiten, muss man vorerst zwei Pakete installieren.

composer require symfony/orm-pack
composer require --dev symfony/maker-bundle

Danach muss man in der Konfigurationsdatei die Datenbank verbinden.

.env
DATABASE_URL="mysql://user:pw@127.0.0.1:8889/symfony"

Mann kann die Datenbank manuell oder auch in der Konsole erstellen.

php bin/console doctrine:database:create

Nun hat man die Datenbank erstellt und verbunden. Um eine Klasse anzulegen, empfiehlt sich wieder der dazugehörige Befehl.

php bin/console make:entity

Nun kann man die Attribute sehr leicht hinzufĂŒgen.

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)

Nach diesem Schritt wird eine Klasse erstellt. Anhand der ORM Mapping Bemerkungen sieht man, dass es sich um eine solche Klasse handelt.

<?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;
    }
}

Diese Klasse kann nun lokal mit den Daten umgehen. Jedoch sind diese Informationen noch nicht als Tabelle in der Datenbank gespeichert. Um dies zu tun, muss man die EntitÀt migrieren.

php bin/console make:migration

Nun wurde das nötige SQL fĂŒr die Migration erstellt. Um dieses auch auszufĂŒhren, muss man noch den folgenden Befehl ausfĂŒhren.

php bin/console doctrine:migrations:migrate

Feld hinzufĂŒgen

SpĂ€ter können auch ohne Probleme weitere Felder hinzugefĂŒgt werden.

php bin/console make:entity

Dabei muss man dann auch wieder eine Migration generieren und danach synchronisieren.

php bin/console make:migration
php bin/console doctrine:migrations:migrate

Services

Auch in Symfony können Services umgesetzt werden. So kann man sehen, welche Services bereits bestehen.

php bin/console debug:autowiring

Service erstellen

src/Lucky/LuckyNumberHandler.php
<?php
namespace App\Lucky;
 
class LuckyNumberHandler {
    public function getLuckyNumber(int $max): int {
        return random_int(0, $max);;
    }
}

Ein solcher Service kann nun im Controller in einer Methode verwendet werden.

src/Controller/LuckyController.php
...
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),
        ]);
    }
}

Verwendet man den Service mehrfach, so ist es besser, wenn man diesen im Konstruktor definiert. So muss man den Handler einmalig definieren und kann ihn dann in der gesamten Klasse verwenden.

src/Controller/LuckyController.php
...
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),
        ]);
    }
}

Dank des Autowiring können alle Klassen, welche sich im src/ Ordner befinden, verwendet werden. Dazu muss man nichts weiter konfigurieren.

config/services.yaml
App\:
    resource: '../src/'
    exclude:
        - '../src/DependencyInjection/'
        - '../src/Entity/'
        - '../src/Kernel.php'

Man kann einen Service aber auch explizit konfigurieren.

config/services.yaml
App\Service\SiteUpdateManager:
    arguments:
        $adminEmail: 'manager@example.com'

Fazit

Die Arbeit mit Symfony ist sehr angenehm, da man schnell voran kommt. Auch die Dokumentation (opens in a new tab) ist, meiner Meinung nach, ausfĂŒhrlich und verstĂ€ndlich.