Example action:
<?php
namespace App\Action\User;
#[\Symfony\Component\Routing\Attribute\Route('/user/{id}')]
#[\AdrBundle\Attribute\Responder(\AdrBundle\Response\Responder\JsonResponder::class)]
class Info
{
public function __construct(
private UserRepository $userRepository
) {}
public function __invoke(int $id): array
{
$user = $this->userRepository->find($id);
return ['user' => $user]
}
}
# config/routing.yaml
user_info:
resource: '../src/Action/User/Info.php'
type: adr # "type: action" works too
other_actions:
resource: '../src/Action/Other/'
type: adr # "type: action" works too
Or more complex way to add routing:
<?php
// config/routes.php
use Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator;
return static function (RoutingConfigurator $routes): void {
// ...
$finder = (new Symfony\Component\Finder\Finder())
->in(__DIR__.'/../src/*/Action')
->name('*.php')
->files();
foreach ($finder as $file) {
$routes->import(
$file->getRealPath(),
'action'
);
}
// ...
};
In example above we create independent action and make it's routing and responder configuration. When we make request
to path http://localhost/user/5 - action will find a User and Responder will represent it's data to json response.
However, we still can use this action in another services, like commands, but if your action has a dependencies, you
need to declare action as public: true
:
services:
App\Action\User\Info:
public: true
Tip: action __invoke arguments has resolving thru symfony controller argument resolver, so u can use it to resolve you're data to objects or anything else.
Bundle have list of most usage responders:
- DefaultResponder - expecting action return string or null
- FileResponder - expecting action return file path as string or \SplFileInfo
- JsonResponder - expecting action return array or serializable object
(if symfony/serializer is used). Optional can have attribute
AdrBundle\Attribute\ContentDispositionType
- RedirectResponder - expecting action return url string
- TemplatingResponder - expecting action return array and have
additional
Symfony\Bridge\Twig\Attribute\Template
attribute
To create your own custom responder you must implement \AdrBundle\Response\Contract\ResponderInterface
and add service
tag adr.action.responder
.
Example responder:
<?php
namespace App\Responder;
use AdrBundle\Response\Contract\ResponderInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
class ApiResponder implements ResponderInterface
{
public function __invoke(mixed $data, array $attributes, array $responseArguments): JsonResponse
{
if (!is_array($data)) {
throw new \RuntimeException(\sprintf('Action must return array, %s given.', gettype($data)));
}
return new JsonResponse(['data' => $data], ...$responseArguments);
}
}
Example yaml configuration:
services:
App\Responder\ApiResponder:
tags: ['adr.action.responder']