Budujemy formularz dla naszej relacji. Kontynuacja lekcji poprzednich. Do dzieła.
Ok, utwórzmy formularz komendą:
symfony console make:form
Nazwa CommentType, klasa Comment. Teraz przechodzimy i usuwamy pole post:
class CommentType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('content');
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => Comment::class,
]);
}
}
Post będziemy dodawać poprzez route i auto-wiring (to jest wnioskować po tym, dodawać metodą entity setPost i zapisywać entity managerem).
Ok, tworzymy comment.html.twig:
{% extends 'base.html.twig' %}
{% block title %}Post - Add Comment{% endblock %}
{% block body %}
<h1>{{ post.title }}</h1>
<p>{{post.content}} </p>
{{ form_start(form) }}
<div>{{ form_errors(form)}}</div>
<div>
{{ form_label(form.content, 'Please enter the comment') }}
{{ form_widget(form.content) }}
{{ form_errors(form.content) }}
</div>
<div>
<button type="submit">Add comment!</button>
</div>
{{ form_end(form) }}
{% endblock %}
Jak widać, będziemy musieli przekazać post oraz form. Dobra, zabieramy się za metodę w micro post controller:
#[Route('/micro_post/{post}/comment', name: 'app_micro_post_comment')]
public function addComment(MicroPost $post, Request $request, EntityManagerInterface $entityManager): Response
{
$form = $this->createForm(CommentType::class, new Comment());
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$comment = $form->getData();
$comment->setPost($post);
$entityManager->persist($comment);
$entityManager->flush();
$this->addFlash('success', 'Your comment have been updated.');
return $this->redirectToRoute(
'app_micro_post_show',
['post' => $post->getId()]
);
}
return $this->render(
'micro_post/comment.html.twig',
[
'form' => $form,
'post' => $post
]
);
}
Wyjaśnienie:
- Stosujemy znany nam auto-wiring (route model binding mówiąc językiem Laravela) aby zamienić nazwę id z route na entity pod nazwą $post
- Request będzie potrzebny do przeprocesowania formularza
- EntityManager jest potrzebny bo zapisujemy do bazy danych
- Kontroler ma dziedziczoną metodę createForm
- Tworzymy formularz w oparciu o klasę CommentType oraz nowy obiekt Comment (Entity) bo ma to być formularz dodawania nowego obiektu
- Robimy handleReqest, to nie Laravel, więc często tutaj mamy taki odpowiednik Route::match(’post”get’) a w zasadzie to Route::any jakby się czepiać szczegółów
- W bloku if mamy co jeśli form został wysłany i przeszedł walidację
- Tworzymy komentarz, ustawiamy post, entity manager robi persist i flush
- Robimy flash message dziedziczoną metodą kontrolera addFlash
- Zwracamy redirect z parametrem post, bo app_micro_post_show używa auto-wiring z taką nazwą właśnie
- Post posiada metodę getId, którą bierzemy ID, bo takie wartości przyjmuje parametr post (auto wiring)
- Jeżeli jesteśmy w „get” a nie „post” (poza blokiem if) to trzeba renderować template przekazując utworzony formularz oraz post, który mamy dzięki auto-wiring
Wiem, że jak to się czyta, to wygląda strasznie, w dodatku sama logika też może na pierwszy rzut oka być lekko nieintuicyjna, ale jeżeli solidnie przerobiliśmy poprzednie ćwiczenia, to wszystko powinno być dla nas jasne i oczywiste a moje gadanie powyżej to coś, co przelecimy okiem i zastanowimy się po co w ogóle takie oczywistości tak tłumaczyć.
Jeżeli nie – albo musimy przerobić materiał raz jeszcze, albo zacząć od łatwiejszego frameworka (Laravel, własny framework) bo Symfony jest jakie jest, niektórzy mogą uznać, że trudne.