Controllers
Orkestra controllers follow PSR-15 standards and support dependency injection for better testability and maintainability.
Abstract Controller
All controllers extend the AbstractController
class which implements PSR-15's RequestHandlerInterface
:
use Orkestra\Services\Http\Controllers\AbstractController;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
class UserController extends AbstractController
{
public function handle(ServerRequestInterface $request): ResponseInterface
{
// Handle the request
return $this->response;
}
}
Dependency Injection
Controllers support dependency injection through the constructor:
class UserController extends AbstractController
{
private UserService $userService;
private LoggerInterface $logger;
public function __construct(
UserService $userService,
LoggerInterface $logger
) {
$this->userService = $userService;
$this->logger = $logger;
}
public function handle(ServerRequestInterface $request): ResponseInterface
{
$users = $this->userService->getAllUsers();
$this->logger->info('Retrieved users', ['count' => count($users)]);
return $this->response;
}
}
Request Handling
Controllers receive PSR-7 request objects:
class UserController extends AbstractController
{
public function handle(ServerRequestInterface $request, array $params): ResponseInterface
{
// Get request data
$data = $request->getParsedBody();
// Get query parameters
$query = $request->getQueryParams();
// Get headers
$headers = $request->getHeaders();
// Get request method
$method = $request->getMethod();
// Get request attributes (route parameters)
$id = $params['id'];
return $this->response;
}
}
Response Handling
Controllers return PSR-7 response objects, strings or json serializable objects/arrays:
class UserController extends AbstractController
{
public function __invoke(ServerRequestInterface $request): ResponseInterface
{
$data = [
'users' => [
['id' => 1, 'name' => 'John'],
['id' => 2, 'name' => 'Jane']
]
];
// Set response body
$this->response->getBody()->write(json_encode($data));
// Set response headers
$this->response = $this->response
->withHeader('Content-Type', 'application/json')
->withStatus(200);
return $this->response;
}
}
class UserController extends AbstractController
{
public function __invoke(ServerRequestInterface $request): array
{
return [
'users' => [
['id' => 1, 'name' => 'John'],
['id' => 2, 'name' => 'Jane']
]
];
}
}
class HelloController extends AbstractController
{
public function __invoke(ServerRequestInterface $request): string
{
return 'Hello Word';
}
}
Attribute Parameters
Controllers can add defined parameters with validation to be used in Route Definition and validation:
use Orkestra\Services\Http\Attributes\Param;
class UserController extends AbstractController
{
#[Param('my_value_1', type: 'string', validation: 'required|min:3|max:255')]
#[Param('my_value_2', validation: 'required', enum: ParamType::class)]
public function handle(ServerRequestInterface $request): ResponseInterface
{
/** Your code */
return $this->response;
}
}
Entity Parameters
You can even define entire entities as route parameters, this will autommatically add the User entity params in Route Definition and validation:
use Orkestra\Services\Http\Attributes\Entity;
class UserController extends AbstractController
{
#[Entity(User::class)]
public function handle(ServerRequestInterface $request): ResponseInterface
{
/** Your code */
return $this->response;
}
}
use Orkestra\Services\Http\Attributes\Param;
#[Param('entity_value_1', type: 'string', validation: 'required|min:3|max:255')]
class User
{
#[Param]
public int $entity_value_2;
}
Best Practices
- Follow PSR-15 standards
- Use dependency inversion
- Keep controllers focused
- Validate input data
- Use proper HTTP status codes
- Handle errors gracefully
- Document your endpoints
- Use consistent response formats
Related Topics
- Routing - Define routes for controllers
- API Development - Build APIs with controllers