Skip to content

Commit 974e823

Browse files
authored
Merge pull request #32 from SymfonyCasts/ch3
Add scripts to the 3st chapter
2 parents d957816 + 0bc1138 commit 974e823

File tree

1 file changed

+109
-2
lines changed

1 file changed

+109
-2
lines changed

sfcasts/handle-form.md

Lines changed: 109 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,110 @@
1-
# Processing the Submitted Form in the Controller
1+
# Processing the Submitted Form
22

3-
TODO
3+
Alright, we've built, created, rendered, and styled our form (I swear, I’ve
4+
done my best so far!). I've given it my all and now our form is ready for
5+
submission. Now, as any seasoned backend developer will tell you, the real
6+
fun begins when we start dealing with that submitted data. Let's jump back
7+
into our controller and make this form functional.
8+
9+
## Updating Controller to Handle Form Data
10+
11+
Open up `src/Controller/AdminController.php`, and in the `newStarshipPart()`
12+
method, right below the form object, add `$form->handleRequest()`.
13+
14+
To pull this off, we need to pass the current request object to this
15+
method. You're familiar with this by now. Inject a `$request` from
16+
HTTP Foundation as a method argument and pass the `$request` to this
17+
method. You might be wondering what this `handleRequest()` is all about.
18+
It simply grabs the submitted data from the request, applies that data to
19+
your form, and now your form contains the user's submitted values.
20+
21+
## Checking Form Submission
22+
23+
Next, we want to know whether the form has actually been submitted or we just
24+
load the form page. That's a breeze — just write `if ($form->isSubmitted())`.
25+
Then within that `if`, we can retrieve the submitted data with `$form->getData()`.
26+
27+
Since our form type has a `data_class` option set to `StarshipPart::class`,
28+
the data you retrieve here isn't a straightforward PHP array. Instead, it's a
29+
`StarshipPart` entity instance with the fields already filled in for us.
30+
Skeptical? Go ahead and check it yourself. Let's assign it to a `$part`
31+
variable and below `dd($part)`.
32+
33+
## Testing Our Form
34+
35+
Back in the browser, I'll quickly fill in the form. Hit create to submit it
36+
and voila, a shiny new `StarshipPart` object with the data we sent. Notice
37+
that no ID is set because Doctrine hasn't saved it in the database yet.
38+
I'll quickly add a PHPDoc above the variable to make PhpStorm's autocomplete
39+
happier, and delete the `dd()` statement.
40+
41+
## Saving Data with Doctrine's EntityManager
42+
43+
To save the new part, we need Doctrine's `EntityManager`. Inject it with
44+
`EntityManagerInterface $entityManager` in the method signature. Then, back
45+
in the `if`, add `$entityManager->persist($part)`, passing the `$part`
46+
object and next `$entityManager->flush()`.
47+
48+
Back to the browser, I'll set the name to: "Legacy Hyperdrive".
49+
Give it a fair price, and don’t forget about important note:
50+
51+
> Be careful with high revs!
52+
53+
Now, hit the submit button again. Did it finally work? Well, at least there are
54+
no errors. Head to the `$part` page and search for "legacy hyperdrive".
55+
There it is, your new shiny Starship part, ready for sale.
56+
57+
## Celebrating Success with Flash Messages
58+
59+
Let's celebrate this moment properly. I'm going to add a successful flash
60+
message. Flash messages are temporary messages stored in the session and
61+
shown exactly once. They are perfect for things like:
62+
63+
> Your part was created successfully!
64+
65+
If you peek into `templates/base.html.twig` You'll see we already have code
66+
that loops over flash messages and renders them with nice styling depending
67+
on the type: success, warning, error, default. After saving the entity to the
68+
database, let's write this: `$this->addFlash()`
69+
70+
First argument: the message “type” - it helps to control styling. Write
71+
`success` here. Second argument: the content of the message. How about
72+
`sprintf('The part "%s" was created.', $part->getName())`.
73+
74+
## Avoiding Duplication and Redirecting User
75+
76+
To avoid duplicate form submissions when the user refreshes the page - which
77+
might lead to unwanted parts floating around in space - let's finish the
78+
process with a redirect. This is a classic best practice for POST forms.
79+
Let's return `$this->redirectToRoute()`.
80+
81+
We can redirect anywhere, but I'll send users back to the part list for
82+
convenience. It should be `app_part_index` route name.
83+
84+
## Testing the Overall Flow
85+
86+
Alright, let's create a new part again. How about a quantum reactor for the
87+
name, set a price, and for notes, I'll say:
88+
89+
> Do not exceed 120% core flux
90+
91+
OK, submit the form again, and there it is. Our success flash message,
92+
announcing that the part quantum reactor was successfully created. And if I
93+
try to refresh the page, the message is gone, so it was shown only once,
94+
and Chrome does not ask me if I want to resubmit the form again, so it was
95+
redirected properly too. Sweet!
96+
97+
## Adding a Second Submit Button
98+
99+
Right now we only have one submit button: Create. But imagine this, if
100+
you're feeling productive, caffeinated, on a roll, and you want to create
101+
multiple parts quickly, one after the other, you could do this with a few
102+
extra clicks each time, clicking on the link to return to the form. But
103+
wouldn't it be so much faster to have a second submit button, that, instead
104+
of creating and going back to the list, creates and stays on this page with an
105+
empty form open, so you can immediately create another part?
106+
107+
Well, it might not be much faster, but it still could save someone a few hours
108+
of their life over the course of many years of adding those parts.
109+
You might be wondering, is that even possible? Absolutely! And we'll figure out
110+
how in the next chapter.

0 commit comments

Comments
 (0)