[Symfony] Getting the payload of an HTTP POST request

Published on 2020-02-22 • Modified on 2020-02-22

In this snippet, we will see how to get the payload of a HTTP POST request from a Symfony controller. This is useful for example when creating an API. You often want to send a payload as a JSON object like:

{
  "firstname": "Fab",
  "lastname": "Pot"
}

Note that if you execute the snippet with the run button, the payload will be empty as the request was not posted. To test if it works, use CULR or a rest client like postman with the example I put above. You must post to the "/en/snippets/getting-the-payload-of-a-http-post-request/run" URL. Be careful, that the json_decode() function doesn't necessarily return an array. If if you put a string like "1111", it will be considered as valid JSON and it will not return an array but an integer.


<?php declare(strict_types=1);

// src/Controller/Snippet/Snippet79Trait.php

namespace App\Controller\Snippet;

use Symfony\Component\HttpFoundation\Request;
use function Symfony\Component\String\u;

/**
 * I am using a PHP trait in order to isolate each snippet in a file.
 * This code should be called from a Symfony controller extending AbstractController (as of Symfony 4.2)
 * or Symfony\Bundle\FrameworkBundle\Controller\Controller (Symfony <= 4.1).
 * Services are injected in the main controller constructor.
 *
 * @see https://symfony.com/doc/current/components/string.html
 */
trait Snippet79Trait
{
    public function snippet79(Request $request): void
    {
        // Payload is a string
        $payloadString = $request->getContent();
        echo sprintf('$payloadString (%s)  : "%s"'."\n", gettype($payloadString), $payloadString);

        // But if you pass true as the first argument it will return a resource object
        $payloadResource = $request->getContent(true);
        echo sprintf('$payloadResource (%s)'."\n", gettype($payloadResource));

        $u = u($payloadString); // Let's play with the new string component

        // if empty, nothing to do left
        if ($u->isEmpty()) {
            echo 'Payload is empty! (test with cURL or postman)'."\n";

            return;
        }

        if ($u->length() > 100) {
            echo 'Payload is too big!'."\n";

            return;
        }

        $json = json_decode($payloadString, true);
        if (json_last_error() !== JSON_ERROR_NONE) {
            echo "Can't decode payload!"."\n";

            return;
        }

        echo 'JSON is valid:'."\n";
        var_dump($json);

        // This line will allow us to see the results when using CURL or postman without having the full HTML rendering
        if ($request->isMethod(Request::METHOD_POST)) {
            die();
        }

        // That's it! 😁
    }
}