Uczymy się tworzyć kontroler w projekcie Symfony z lekcji poprzedniej. Rozwijamy umiejętności korzystania z popularnego frameworku PHP Symfony.
Ok, piszemy komendę:
symfony console make:controller
Poprosi o nazwę. Podajemy HelloController.
Utworzy coś takiego:
class HelloController extends AbstractController
{
#[Route('/hello', name: 'app_hello')]
public function index(): Response
{
return $this->render('hello/index.html.twig', [
'controller_name' => 'HelloController',
]);
}
}
Jak widać routing i kontroler są w Symfony nieodłączne, inaczej niż w Laravelu. Wiele metod jest dostępnych przez dziedziczenie (Symfony jest dużo bardziej abstrakcyjne i warstwowe niż Laravel, który i tak ma tych warstw więcej niż trochę).
Mamy tutaj render oraz „compact”, przekazanie zmiennej do kontekstu. Mamy też route i jego name. Rzućmy komendę:
symfony server:start
I przechodzimy pod adres /hello zobaczyć czy działa. Ok, teraz zobaczmy jak działa. Szukamy templates, hello, index.html.twig. To mamy:
{% extends 'base.html.twig' %}
{% block title %}Hello HelloController!{% endblock %}
{% block body %}
<style>
.example-wrapper { margin: 1em auto; max-width: 800px; width: 95%; font: 18px/1.5 sans-serif; }
.example-wrapper code { background: #F5F5F5; padding: 2px 6px; }
</style>
<div class="example-wrapper">
<h1>Hello {{ controller_name }}! ✅</h1>
This friendly message is coming from:
<ul>
<li>Your controller at <code>C:/xampp/htdocs/symfapp/src/Controller/HelloController.php</code></li>
<li>Your template at <code>C:/xampp/htdocs/symfapp/templates/hello/index.html.twig</code></li>
</ul>
</div>
{% endblock %}
W ogóle nie przypomina to blade. Jeżeli już, to przypomina języki templatkowe, które są bardzo popularne w języku Python. Filozofia jest jednak ta sama.
Rzućmy okiem na base.html.twig:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>{% block title %}Welcome!{% endblock %}</title>
<link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 128 128%22><text y=%221.2em%22 font-size=%2296%22>⚫️</text><text y=%221.3em%22 x=%220.2em%22 font-size=%2276%22 fill=%22%23fff%22>sf</text></svg>">
{% block stylesheets %}
{% endblock %}
{% block javascripts %}
{% block importmap %}{{ importmap('app') }}{% endblock %}
{% endblock %}
</head>
<body>
{% block body %}{% endblock %}
</body>
</html>
Jeżeli orientujemy się w Laravelu i przerobiliśmy projekt „własny framework MVC w PHP” to nie powinniśmy mieć problemów w ogarnięciu się raz dwa w tym, co się dzieje.
Jeżeli jest to nasz pierwszy framework + słabo znamy wzorce projektowe, OOP, bazy danych, popularne wzorce (MVC, Repository-Entity) oraz zagadnienia frameworkowe to raczej polecam się poduczyć, bo Symfony może być minimalnie dla nas za trudne.
Ok, wykonajmy komendę poniżej, bo jedna rzecz nam umyka:
symfony console debug:router
Nasz route będzie pod ANY. Tak, w Symfony wszystko jest pod ANY, chyba że określimy inaczej:
class HelloController extends AbstractController
{
#[Route('/hello', name: 'app_hello', methods: ['GET', 'HEAD'])]
public function index(): Response
{
return $this->render('hello/index.html.twig', [
'controller_name' => 'HelloController',
]);
}
}
W ten sposób określamy jakie metody są dostępne dla naszego route. Jeżeli solidnie przerobiliśmy Laravela, to będziemy wiedzieć, że tam routes trzeba było ustawiać w pewnej kolejności, aby jedna nie przykrywała drugiej.
Cóż, w Symfony to inaczej wygląda, routing jest w kontrolerach, a zatem tam jest takie coś, jak priorytet. Oto przykład, jak to wygląda:
class BlogController extends AbstractController
{
/**
* This route has a greedy pattern and is defined first.
*/
#[Route('/blog/{slug}', name: 'blog_show')]
public function show(string $slug): Response
{
// ...
}
/**
* This route could not be matched without defining a higher priority than 0.
*/
#[Route('/blog/list', name: 'blog_list', priority: 2)]
public function list(): Response
{
// ...
}
}
W Laravelu po prostu musielibyśmy pamiętać, aby Route::get(’/blog/list’, …) było nad Route::get(’/blog/{slug}’, …), tak aby „list” nie zostało potraktowane jako slug.