Attributes

The core feature of this bundle, the below attributes mainly exist to facilitate handling requests and responses.

RequestBody

This attribute is one with the most features in it. It decodes the request message body and passes it to a method argument in a controller. It supports scalars, objects, collections, and file-based method arguments.

Scalars

For scalar method arguments the ConverterManager is used if necessary.

namespace App\Controller;

use Jungi\FrameworkExtraBundle\Attribute\RequestBody;
use Symfony\Component\Routing\Attribute\Route;

class MessageController
{
    #[Route('/messages', methods: ['POST'])]
    public function sendMessage(#[RequestBody] string $message)
    {
        // ..
    }
}

Objects

On the contrary to the scalar types, it uses the MessageBodyMapperManager to decode the request message body.

namespace App\Controller;

use Jungi\FrameworkExtraBundle\Attribute\RequestBody;
use Symfony\Component\Routing\Attribute\Route;

class UserController
{
    #[Route('/users', methods: ['POST'])]
    public function registerUser(#[RequestBody] UserRegistrationData $data)
    {
        // ..
    }
}

Collections

Unfortunately, at the current state, PHP does not support declaring a collection with the desired type. In order to achieve that, the type parameter has been provided. It accepts types of well-known syntax type[].

namespace App\Controller;

use Jungi\FrameworkExtraBundle\Attribute\RequestBody;
use Symfony\Component\Routing\Attribute\Route;

class RoleController
{
    #[Route('/roles', methods: ['POST'])]
    public function createRoles(#[RequestBody('RoleCreationData[]')] array $rolesData)
    {
        // ..
    }
}

Files

When the request message body contains a file, you can declare your method argument as UploadedFile, File, SplFileInfo or SplFileObject. Thanks to the TmpFileUtils you can query those objects for any public method like getFilename(), getPathname() and so on.

namespace App\Controller;

use Jungi\FrameworkExtraBundle\Attribute\RequestBody;
use Symfony\Component\Routing\Attribute\Route;

class PictureController
{
    #[Route('/pictures', methods: ['POST'])]
    public function savePicture(#[RequestBody] \SplFileInfo $file)
    {
        // ...
    }
}

UploadedFile

It's a bit a special one, it covers all public methods like getClientOriginalName() or getClientMimeType().

The getClientOriginalName() uses the Content-Disposition header. In general, this header is used in responses and in multipart/form-data requests. For this to work, the Content-Disposition must be set to inline, and the filename parameter must be provided.

On the contrary, the getClientMimeType() uses the Content-Type header.

POST /pictures HTTP/1.1
Content-Type: image/png
Content-Disposition: inline; filename=foo.png
namespace App\Controller;

use Jungi\FrameworkExtraBundle\Attribute\RequestBody;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\Routing\Attribute\Route;

class PictureController
{
    #[Route('/pictures', methods: ['POST'])]
    public function savePicture(#[RequestBody] UploadedFile $file)
    {
        $filename = $file->getClientOriginalName(); // foo.png
        $mimeType = $file->getClientMimeType(); // image/png
        $path = $file->getPathname();
        // ...
    }
}

RequestParam

It binds a request parameter to a method argument in a controller. It supports multipart/form-data requests and that means you can even access a file through this attribute.

namespace App\Controller;

use Jungi\FrameworkExtraBundle\Attribute\RequestParam;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\Routing\Attribute\Route;

class PictureController
{
    #[Route('/pictures', methods: ['POST'])]
    public function savePicture(
        #[RequestParam] UploadedFile $file, 
        #[RequestParam('desc')] string $description
    ) {
        // ...
    }
}

If a method argument cannot be nullable, and a request parameter cannot be found, a 400 HTTP response is returned.

QueryParam

It binds a query parameter to a method argument in a controller.

namespace App\Controller;

use Jungi\FrameworkExtraBundle\Attribute\QueryParam;
use Symfony\Component\Routing\Attribute\Route;

class UserController
{
    #[Route('/users', methods: ['GET'])]
    public function getUsers(
        #[QueryParam('q')] ?string $searchQuery, 
        #[QueryParam] ?int $limit
    ) {
        // ...
    }
}

If a method argument cannot be nullable, and a query parameter cannot be found, a 400 HTTP response is returned.

QueryParams

It is similar to the @QueryParam, but instead of a single query parameter, it takes all query parameters to pass them as a single method argument in a controller. This attribute requires an argument to be of an object type.

namespace App\Controller;

use Jungi\FrameworkExtraBundle\Attribute\QueryParams;
use Symfony\Component\Routing\Attribute\Route;

class UserController
{
    #[Route('/users', methods: ['GET'])]
    public function getUsers(#[QueryParams] UserQueryData $queryData)
    {
        // ...
    }
}

RequestCookie

It binds a cookie value to a method argument in a controller.

namespace App\Controller;

use Jungi\FrameworkExtraBundle\Attribute\RequestCookie;
use Symfony\Component\Routing\Attribute\Route;

class SessionController
{
    #[Route('/sessions/current', methods: ['GET'])]
    public function getCurrentSessionInformation(#[RequestCookie] string $sessionId)
    {
        // ...
    }
}

If a method argument cannot be nullable, and a request cookie cannot be found, a 400 HTTP response is returned.

RequestHeader

It binds a header value to a method argument in a controller.

namespace App\Controller;

use Jungi\FrameworkExtraBundle\Attribute\RequestHeader;
use Symfony\Component\Routing\Attribute\Route;

class ReportController
{
    #[Route('/reports/monthly-revenue', methods: ['GET'])]
    public function getMonthlyRevenueReport(#[RequestHeader('Accept-Language')] string $acceptableLanguage)
    {
        // ...
    }

    #[Route('/reports/monthly-visitors', methods: ['GET'])]
    public function getMonthlyVisitorsReport(#[RequestHeader('Accept')] array $acceptableMediaTypes)
    {
        // ...
    }
}

If a method argument cannot be nullable, and a request header cannot be found, a 400 HTTP response is returned.

As you can see in the example when a method argument is declared as array it will pass all values of the header to it.

Last updated