Hitting DELETE [Raw Symfony 4]

In my opinion DELETE is the second easiest HTTP verb to implement. Our delete method will, as the name suggests, let our Symfony 4 API consumer delete an Album. In the real world, you likely would restrict the DELETE function to specific users with specific roles.

If your requirements are that you need to restrict who can call the delete route then please watch this video next.

Let's look at the Behat scenario to refresh our memory of how a DELETE call should work:

    Given there are Albums with the following details:
      | title                              | track_count | release_date              |
      | some fake album name               | 12          | 2020-01-08T00:00:00+00:00 |
      | another great album                | 9           | 2019-01-07T23:22:21+00:00 |
      | now that's what I call Album vol 2 | 23          | 2018-02-06T11:10:09+00:00 |

  Scenario: Can delete an Album
    Given I request "/album/3" using HTTP GET
    Then the response code is 200
    When I request "/album/3" using HTTP DELETE
    Then the response code is 204
    When I request "/album/3" using HTTP GET
    Then the response code is 404

The gist being:

1) Check the album exists 2) Delete the album 3) Confirm the album no longer exists

As our Behat tests are isolated from our implementation, the only way we can do this is to "dogfood" our own API.

Implementing DELETE

Prepare yourself, this code is long and complex:

     * @Route(
     *     "/album/{id}",
     *     name="delete_album",
     *     methods={"DELETE"},
     *     requirements={"id"="\d+"}
     * )
     * @param int $id
     * @return JsonResponse
    public function delete($id)
        $existingAlbum = $this->findAlbumById($id);


        return new JsonResponse(

We've already done all the hard work through implementing the other controller methods.

We re-use the $this->findAlbumById($id) private method call to ensure any invalid Album id requests will throw a 404.

If the Album does exist we ask Doctrine to remove / delete the record from the table the next time changes are flushed off to the database.

And on the very next line we call a flush to ensure the record is immediately deleted.

As there's nothing further to say, we return a 204 / no content response.

The good news?

We're (almost) done with our basic Symfony 4 API implementation:

php vendor/bin/behat

# ...

12 scenarios (12 passed)
52 steps (52 passed)
0m2.15s (10.68Mb)

There's just one more problem that we need to address. And this is typically only going to affect you once you ship your code off to production. We're going to get on to this in the very next video.


# Title Duration
1 What will our JSON API actually do? 08:46
2 What needs to be in our Database for our Tests to work? 12:32
3 Cleaning up after each Test Run 02:40
4 Docker makes for Easy Databases 09:01
5 Healthcheck [Raw Symfony 4] 07:53
6 Send in JSON data using POST [Raw Symfony 4] 05:33
7 Keep your data nice and tidy using Symfony's Form [Raw Symfony 4] 10:48
8 Validating incoming JSON [Raw Symfony 4] 08:26
9 Nicer error messages [Raw Symfony 4] 06:23
10 GET'ting data from our Symfony 4 API [Raw Symfony 4] 08:11
11 GET'ting a collection of Albums [Raw Symfony 4] 01:50
12 Update existing Albums with PUT [Raw Symfony 4] 05:00
13 Upsetting Purists with PATCH [Raw Symfony 4] 02:39
14 Hitting DELETE [Raw Symfony 4] 02:11
15 How to open your API to the outside world with CORS [Raw Symfony 4] 07:48
16 Getting Setup with Symfony 4 and FOSRESTBundle [FOSRESTBundle] 09:11
17 Healthcheck [FOSRESTBundle] 06:14
18 Handling POST requests [FOSRESTBundle] 08:31
19 Saving POST data to the database [FOSRESTBundle] 09:44
20 Work with XML, or JSON, or Both [FOSRESTBundle] 04:31
21 Going far, then Too Far with the ViewResponseListener [FOSRESTBundle] 03:19
22 GET'ting data from your Symfony 4 API [FOSRESTBundle] 05:58
23 GET'ting a Collection of data from your Symfony 4 API [FOSRESTBundle] 01:27
24 Updating with PUT [FOSRESTBundle] 02:58
25 Partially Updating with PATCH [FOSRESTBundle] 02:15
26 DELETE'ing Albums [FOSRESTBundle] 01:27
27 Handling Errors [FOSRESTBundle] 08:58
28 Introducing the API Platform [API Platform] 08:19
29 The Entry Point [API Platform] 04:30
30 The Context [API Platform] 05:52
31 Healthcheck - Custom Endpoint [API Platform] 05:17
32 Starting with POST [API Platform] 07:08
33 Creating Entities with the Schema Generator [API Platform] 07:38
34 Defining A Custom POST Route [API Platform] 07:31
35 Finishing POST [API Platform] 06:29
36 GET'ting One Resource [API Platform] 02:50
37 GET'ting Multiple Resources [API Platform] 02:59
38 PUT to Update Existing Data [API Platform] 02:19
39 DELETE to Remove Data [API Platform] 01:15
40 No One Likes Errors [API Platform] 03:28