Controllers
Controllers usually extend AbstractController, an optional base class that adds shortcuts for the most common operations: rendering templates, returning JSON, redirecting, etc.
Need the incoming request? Type-hint a Request argument and Symfony passes it to you, with a clean object-oriented API for headers, cookies, query parameters and more.
Building an API? The json() helper serializes your data and sets the right response headers.
Or skip the boilerplate entirely: #[MapQueryParameter] maps a query string parameter (/api/search?query=symfony) straight into a typed method argument, with an optional default value.
<?phpnamespace App\Controller;use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;use Symfony\Component\HttpFoundation\JsonResponse;use Symfony\Component\HttpFoundation\Request;use Symfony\Component\HttpKernel\Attribute\MapQueryParameter;use Symfony\Component\Routing\Attribute\Route;class ApiController extends AbstractController{ #[Route('/api/status')] public function status(Request $request): JsonResponse { return $this->json([ 'status' => 'OK', 'ip' => $request->getClientIp(), ]); } #[Route('/api/search')] public function search( #[MapQueryParameter] string $query = '', ): JsonResponse { return $this->json(['query' => $query]); }}