Mit dem composer das Projekt erstellen. Dazu auf DOS-Ebene ins htdocs-Verzeichnis gehen und den Befehl composer create-project symfony/skeleton zielpfad eingeben. Zielpfad ist das Verzeichnis innerhalb von htdocs, in dem das Projekt erstellt werden soll.
Im Verzeichnis public muss eine .htaccess erstellt werden. Die bekommt folgenden Inhalt:
<IfModule mod_rewrite.c>
RewriteEngine On
# Determine the _RewriteBase automatically and set is
# as environment variable
RewriteCond %{REQUEST_URI}::$1 ^(/.+)/(.*)::\2$
RewriteRule ^(.*) - [E=BASE:%1]
# If the requested filename existes, simply serve it.
# We only want to let Apache serve files and not directories.
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule .? - [L]
# Rewrite all other queries to the front controller.
RewriteRule .? %{ENV:BASE}/index.php [L]
</IfModule>
Subversion
Damit die Versionierung klappt, muss Subversion eingerichtet werden. Dazu in PHPStorm unter VCS / Import into Version Control aufrufen und in das gewünschte Repository exportieren. Anschließend gleich wieder mit VCS / Get from Version Control importieren, damit Änderungen erkannt werden.
Dann noch im Dateiexplorer über das Kontextmenü die nicht erforderlichen Verzeichnisse von Subversion ausnehmen.
Zugriff auf die neue Site
Für den Zugriff auf die Site sind zwei Anpassungen erforderlich:
In der httpd-vhosts.conf müssen die folgenden Zeilen eingefügt werden, wobei die Parameter hinter DocumentRoot und ServerName natürlich angepasst werden müssen.
<virtualhost *:80=""> DocumentRoot "C:\xampp\htdocs\symfony\public" ServerName symphony.test </virtualhost>
Anschließend muss XAMPP neu gestartet werden.
Die zweite Änderung muss auf denjenigen PCs innerhalb des lokalen Netzes durchgeführt werden, auf denen die Seite angezeigt werden soll. Und zwar in der Datei C:\Windows\System32\drivers\etc\hosts. Dort muss für die neue Site eine neue Zeile eingefügt werden: 192.168.0.12 adlibitum.test. Die IP ist dabei die IP des XAMPP-Servers und der zweite Parameter derjenige, der in der httpd-vhosts.conf als ServerName eingetragen worden ist.
Profiler
Der Profiler liefert viele interessante Informationen zum Programm im aktuellen Status zurück. Das ist die Statuszeile am unteren Bildschirmrand.
composer require profiler --dev
Logger
Der Logger liefert viele zusätzliche Informationen zum Programm im aktuellen Status zurück.
composer require logger
Debugger installieren
In das Verzeichnis mit der neuen Internetsite wechseln.
composer require debug --dev composer unpack debug
Der zweite Befehl dient dazu, das Paket in die einzelnen Komponenten aufzulösen. Damit können diese gezielt an die benötigte Version angepasst oder entfernt werden.
Router installieren
composer require annotations
Das sorgt auch dafür, dass die Use-Statements automatisch ergänzt werden, falls erforderlich.
Security Checker installieren
Um die Packages auf Sicherheitslecks prüfen zu können, kann der sec-checker verwendet werden.
composer require sec-checker --dev
Damit wird auch erreicht, dass nach jeder Installation eines Pakets ein Sicherheitscheck durchgeführt wird. Um eine Prüfung ohne Installation durchzuführen: composer install.
Twig installieren
Wenn HTML-Templates verwendet werden sollen, wird Twig benötigt:
composer require twig
Damit das dann auch genutzt werden kann, muss der Controller den AbstractController extenden: class XxxController extends AbstractController
Maker-Bundle
Dieses Bundle wird für zahlreiche Funktionen benötigt.
composer require symfony/maker-bundle --dev
Datenbanktreiber
Mit Doctrine sind Datenbankfunktionen möglich.
composer require doctrine
Konfiguriert wird in der .env:
DATABASE_URL=mysql://db_user:db_password@127.0.0.1:3306/db_name?serverVersion=mariadb-10.4.14
Die mariadb ist wichtig, sonst kommt der Fehler sync-metadata-storage soll gestartet werden. Unter Umständen sind auch in der config\packages\doctrine.yaml Einstellungen erforderlich.
Anschließend kann auf DOS-Ebene die Datenbank mit php bin/console doctrine:database:create erstellt werden.
Tabellen werden mit php bin/console make:entity erstellt. Anschließend mit php bin/console make:migration eine Migration erstellen. Diese im Verzeichnis migrations prüfen, bevor sie mit php bin/console doctrine:migrations:migrate ausgeführt wird.
Debug-Infos
Um an beliebiger Stelle im Code Debugginginfos zu bekommen, kann dump($var); eingebaut werden. Das erzeugt in der Debugging-Statuszeile ein neues Symbol: ein Fadenkreuz. Über dieses können die Inhalte der Variablen betrachtet werden. Die Verwendung ist auch in twig-Dateien möglich. Dort einfach {{ dump() }} einfügen.
Unter Windows erfolgt der Aufruf der Konsole mit php bin/console.
Routing
Um das Routing in den Kommentarblock zu schreiben, müssen Annotations installiert sein: composer require annotations. Im Docbloc über der Funktion dann @Route("/") einfügen, wobei zwischen den Anführungszeichen die Route steht. Im Beispiel die Route für index.
Darüber hinaus ist es sinnvoll, den Namen für die Route selbst festzulegen. Dadurch kann der Controller über ein und denselben Namen referenziert werden, auch wenn der Name der Funktion geändert wird. Um den Namen von Hand festzulegen, einfach einen zweiten Parameter mit angeben:
/**
* @Route("/", name="app_homepage")
*/
public function homepage()
{
return new Response("Hallo Homepage!");
}
Zum Aufrufen dieser Router dient dann
href="{{ path('app_homepage') }}
Erwartet der Controller Parameter, so sind diese in Form eines Array zusätzlich einzutragen:
href="{{ path('article_show',{slug:'nur-ein-test'}) }}"
HTML-Vorlagen
HTML-Vorlagen können dank Twig verwendet werden: composer require twig. Die Templates dafür kommen in das Verzeichnis templates.
Damit Twig genutzt werden kann, muss die Controllerklasse erweitert werden: extends AbstractController. Eingebunden wird dann mit dem Befehl return $this->render(). Der Aufruf erwartet zwei Parameter: der erste ist die zu verwendende Vorlage, der zweite sind zu übergebenden Parameter in Form eines Arrays.
/**
* @Route("/fahrten/{slug}")
*/
public function fahrten($slug)
{
return $this->render('homepage/base.html.twig',[
"title" => ucwords(str_replace("-", " ", $slug)),
]);
}
Assets
Mit Assets kann man im Code automatische Referenzen einbauen. Zur Nutzung mit dem Befehl composer require asset installieren. Damit kann man dann in Twigdateien folgendes verwenden:
<link rel="stylesheet" href="{{ asset('css/styles.css') }}">
Markdown
Um per Twig auszugebenden Text zu formatieren, muss ein Markdownbundle installiert werden: composer require knplabs/knp-markdown-bundle.
Übersetzungen
Installieren mit composer require symfony/translation.
Im YAML-Format werden die Strings OHNE “ eingegeben. Das Leerzeichen nach dem Doppelpunkt zwischen den Sprachen ist wichtig!
Formulare
Installieren mit composer require form.
Zunächst eine Klasse für das Formular erstellen. Diese muss Bedingungen erfüllen:
NAMExFormType extends AbstractType
Der Name muss mit FormType beendet werden und die Klasse muss die oben genannte Klasse erweitern. Darin dann eine Funktion erstellen (Strg+O):
public function buildForm() {
$builder
->add('NameDBFeld') //so oft wie erforderlich
;
Im Kontroller wird dann das Formular gerendert:
$form = $this-> createForm(NAMExFormType::class);
return $this-> render('Verzeichnis/NAMEz.htlm.twig', [
'NAMEy' => $form->createView(),
])
Im Template, wird schnell erstellt, indem man im Kontroller den Cursor auf den Templatenamen setzt und Alt+Enter drückt, dann folgendes einfügen:
{{ form_start (NAMEy) }}
{{form_widget(NAMEy) }}
{{ form_end (NAMEy) }}
Um die Formulardaten zu verarbeiten, den Kontroller wie folgt erweitern:
public function new(EntityManagerInterface $em, Request $request) //httpFoundation
...
{
$form = $this->createForm(ArticleFormType::class);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$data = $form->getData();
$article = new Article();
$article->setTitle($data['title']);
$article->setContent($data['content']);
$article->setAuthor($this->getUser());
$em->persist($article);
$em->flush();
$this->addFlash('erfolg', "Hat geklappt!");
return $this->redirectToRoute('admin_article_list');
}
return $this->render('article_admin/new.html.twig', [
'articleForm' => $form->createView(),
]);
}
Damit der Anwender weiß, dass es geklappt hat, soll eine entsprechende Meldung angezeigt werden. Dazu die DB-Klasse erweitern:
$this->addFlash('erfolg', "Meldung");
Sowohl erfolg als auch Meldung sind beliebige Texte. Gespeichert wird in der Session und die Inhalte können nur 1x gelesen werden, weil sie beim Lesen gleich gelöscht werden.
Zur Anzeige der Meldung im Twig-Template einfach einbauen:
{% for message in app.flashes('erfolg') %}
{{ message }}
{% endfor %}
Um eine solche Variable zu prüfen, ohne sie zu löschen:
{{ app.session.flashBag.peek('erfolg')|length > 0 ? '' : 'mb-5' }}
Man kann sich das Leben auch vereinfachen, indem man das Formular an die DB-Klasse bindet. Dann wird nicht nur der Feldtype automatisch erkannt, auch die manuelle Zuweisung der Formularfelder zu den DB-Feldern kann entfallen. Dazu in der Formularklasse eine neue Funktion einbauen – Strg+O / Configure Options:
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Article::class
]);
}
Im Kontroller zur DB-Klasse können dann die manuellen Zuweisungen entfallen. Statt dessen wird eine Variable für die DB-Klasse verwendet:
/** @var Article $article */
$article = $form->getData();
$article->setAuthor($this->getUser());
Das Article muss dabei vom Typ App\Entity sein.
Formulare können auch automatisch mit Formatvorlagen verknüpft werden. Dazu muss in config\packages die twig.yaml angepasst werden:
form-themes:
- 'bootstrap_4_layout.html.twig'
Welche Themes es gibt, kann man bei Symfony nachschauen.
Die Feldtypen können auch von Hand angepasst werden. Infos gibt es bei Symfony. Infos zu den Formattypen gibt es hier. Der hinzugefügte Feldtyp muss vom Typ Symfony\Component\Form\Extension\Core\Type sein. Übrigens, um den zweiten Parameter zu überspringen, null eintragen.
Auswahllisten anhand von DB-Feldern werden ebenfalls mit ->add befüllt. Als dritter Parameter wird die gewünschte DB angegeben.
-> add('author', EntityType::class, [
'class' => User::class
])
In dieser Klasse braucht es dann aber eine spezielle Funktion:
public function __toString()
{
return $this->getFirstName();
}
Hier wird dasjenige Feld aus der zuvor definierten Tabelle übergeben, das hier genannt wird.
Soll ein definiertes Feld angesprochen werden, wird so gearbeitet:
-> add('author', EntityType::class, [
'class' => User::class,
'choice_label' => function(User $user) {
return sprintf('(%d) %s', $user->getId(), $user->getFirstName());
},
])
Wenn keine der Optionen aus der Liste vorausgewählt sein soll:
'placeholder' => 'Bitte auswählen',
Für individuelle Abfragen muss zunächst das Repository deklariert werden – in der Formklasse:
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
Um die Variablen automatisch zu initialisieren, den Cursor auf die Variable setzen, Alt-Enter drücken und den Code erzeugen lassen. Dann im Formularbereich eine neue Variable einfügen:
'choices' => $this->userRepository
->findAllEmailAlphabetical(),
Diese Funktion findAllEmailAlphabetical muss dann im Repository\userRepository.php erzeugt werden:
public function findAllEmailAlphabetical()
{
return $this->createQueryBuilder('u')
->orderBy('u.email', 'ASC')
->getQuery()
->execute();
}