#[GetMapping]
Handles HTTP GET requests
Winter Boot uses PHP 8 native attributes for routing. Instead of maintaining a central routes file, you place mapping attributes directly on controller methods — or on the controller class itself to establish a base URI prefix. The framework reads these attributes at startup, builds a routing table, and dispatches every incoming request to the correct handler with all parameters already bound and type-cast.
#[RequestMapping]#[RequestMapping] (namespace dev\winterframework\stereotype\web\RequestMapping) can be applied at class level to set a base URI prefix, or at method level to define the full route for that handler. When both are present, the class-level path is prepended to the method-level path automatically.
path string|array (required)
The URI pattern for this mapping. Supports {variable} placeholders for path variables. Accepts a single string or an array of strings to map multiple paths to the same handler.
method array
List of RequestMethod constants this handler accepts — for example, [RequestMethod::GET, RequestMethod::POST]. Defaults to all HTTP methods when omitted.
name string
An optional human-readable name for this mapping. Useful for logging and debugging.
consumes array
List of media types this handler consumes — for example, ['application/json']. Requests with a non-matching Content-Type are rejected.
produces array
List of media types this handler produces — for example, ['application/json']. Used to negotiate the response Content-Type.
RequestMethod (namespace dev\winterframework\enums\RequestMethod) defines constants for every HTTP method the framework accepts in the method array.
| Constant | HTTP Method |
|---|---|
RequestMethod::GET |
GET |
RequestMethod::HEAD |
HEAD |
RequestMethod::POST |
POST |
RequestMethod::PUT |
PUT |
RequestMethod::PATCH |
PATCH |
RequestMethod::DELETE |
DELETE |
RequestMethod::OPTIONS |
OPTIONS |
RequestMethod::TRACE |
TRACE |
<?php
use dev\winterframework\stereotype\RestController;use dev\winterframework\stereotype\web\RequestMapping;use dev\winterframework\enums\RequestMethod;
#[RestController]#[RequestMapping(path: '/api/v1')] // base prefix for every method belowclass ProductController{ // Handled at GET /api/v1/products #[RequestMapping(path: '/products', method: [RequestMethod::GET])] public function listProducts(): array { return []; }
// Handled at POST /api/v1/products #[RequestMapping(path: '/products', method: [RequestMethod::POST])] public function createProduct(): array { return []; }}Winter Boot ships five convenience attributes that combine #[RequestMapping] with a fixed HTTP method. They accept the same path, name, consumes, and produces parameters, but you never need to specify method explicitly.
#[GetMapping]
Handles HTTP GET requests
#[PostMapping]
Handles HTTP POST requests
#[PutMapping]
Handles HTTP PUT requests
#[DeleteMapping]
Handles HTTP DELETE requests
#[PatchMapping]
Handles HTTP PATCH requests
use dev\winterframework\stereotype\web\GetMapping;
#[GetMapping(path: '/users')]public function listUsers(): array{ return $this->userService->findAll();}#[RequestParam]#[RequestParam] (namespace dev\winterframework\stereotype\web\RequestParam) binds a query-string value, POST field, cookie, or HTTP header to a method parameter. Apply it at the parameter level.
name string
Name of the incoming parameter. Defaults to the PHP variable name when omitted.
required bool
Whether the parameter must be present in the request. Defaults to true. Set to false to make it optional.
defaultValue mixed
Value used when the parameter is absent and required is false.
source string
Where to read the value from. Defaults to 'request'. See the source table below.
| Value | Reads from |
|---|---|
request |
URL query string or POST body (checked in that order) |
get |
URL query string only ($_GET) |
post |
POST url-encoded / form body only ($_POST) |
cookie |
HTTP cookie ($_COOKIE) |
header |
HTTP request header |
use dev\winterframework\stereotype\web\GetMapping;use dev\winterframework\stereotype\web\PostMapping;use dev\winterframework\stereotype\web\RequestParam;
// Query-string: GET /divide?a=10&b=2#[GetMapping(path: '/divide')]public function divide( #[RequestParam] int $a, #[RequestParam] int $b,): float { return $a / $b;}
// Optional parameter with a default value#[GetMapping(path: '/greet')]public function greet( #[RequestParam(required: false, defaultValue: 'World')] string $name,): string { return 'Hello, ' . $name;}
// Read from a specific HTTP header#[PostMapping(path: '/orders')]public function createOrder( #[RequestParam(name: 'X-Tenant-Id', source: 'header')] string $tenantId,): array { return $this->orderService->create($tenantId);}
// Read from a cookie#[GetMapping(path: '/profile')]public function profile( #[RequestParam(name: 'session_token', source: 'cookie')] string $token,): array { return $this->sessionService->getProfile($token);}#[PathVariable]#[PathVariable] (namespace dev\winterframework\stereotype\web\PathVariable) binds a URI template segment — the {placeholder} in the path string — to a method parameter. The placeholder name must match the PHP variable name, or you can specify it explicitly via the name option. Supported scalar types are string, int, float, and bool.
use dev\winterframework\stereotype\web\GetMapping;use dev\winterframework\stereotype\web\PathVariable;
// GET /hello/Alice → "Hello, Alice"#[GetMapping(path: '/hello/{name}')]public function sayHello(#[PathVariable] string $name): string{ return 'Hello, ' . $name;}
// GET /users/42 → finds user with id 42#[GetMapping(path: '/users/{id}')]public function getUser(#[PathVariable] int $id): array{ return $this->userService->findById($id);}#[RequestBody]#[RequestBody] (namespace dev\winterframework\stereotype\web\RequestBody) binds the entire HTTP request body to a method parameter. Winter Boot deserialises JSON, XML, URL-encoded form bodies, and multipart forms into the target class automatically. The parameter must be type-hinted with a concrete class, or string to receive the raw body. Union types are not supported.
use dev\winterframework\stereotype\web\PostMapping;use dev\winterframework\stereotype\web\RequestBody;
// Accepts both JSON and url-encoded bodies:// {"a": 10, "b": 20} or a=10&b=20#[PostMapping(path: '/calc/add')]public function add(#[RequestBody] AddRequest $request): int{ return $this->calcService->add($request->a, $request->b);}class AddRequest{ public int $a; public int $b;}#[PostMapping(path: '/webhooks/ingest')]public function ingest(#[RequestBody] string $rawPayload): array{ $data = json_decode($rawPayload, true); return $this->webhookService->handle($data);}When the request Content-Type is none of form, multipart, JSON, or XML — or when parsing is disabled (see disableParsing below) — the raw body string is passed straight to your class constructor. The class must therefore declare a constructor taking a single string argument:
class CsvPayload{ public array $rows;
public function __construct(string $raw) { $this->rows = explode("\n", trim($raw)); }}Any other constructor shape fails here and the request is rejected with 400 Bad Request.
disableParsing bool
Skips JSON/XML deserialisation. Defaults to false. When true, the raw body is handed to the single-string-arg constructor instead — useful for hand-rolled formats.use dev\winterframework\stereotype\web\PostMapping;use dev\winterframework\stereotype\web\RequestBody;
#[PostMapping(path: '/import')]public function import(#[RequestBody(disableParsing: true)] CsvPayload $payload): array{ return $this->importService->handle($payload->rows);}multipart/form-data)For multipart/form-data requests, text fields and uploaded files are merged into a single map keyed by field name, then bound to your DTO by property name:
string, int, float, bool) — values are type-cast.HttpUploadedFile (namespace dev\winterframework\web\http\HttpUploadedFile) to get a typed object — getFilePath() for the temp path, plus getName(), getSize(), getError() / getErrorText(). Declare it as array instead to receive the raw $_FILES entry (name, type, tmp_name, error, size).<input type="file" name="photos" multiple>) keeps PHP’s parallel-array $_FILES shape — normalise it yourself, or inject HttpRequest and use getFiles() / getFile($name) instead.use dev\winterframework\stereotype\web\PostMapping;use dev\winterframework\stereotype\web\RequestBody;use dev\winterframework\web\http\HttpUploadedFile;
class AvatarUpload{ public string $username; public HttpUploadedFile $avatar; // matches <input name="avatar" type="file"> // public array $avatar; // alternative: raw $_FILES entry}
#[PostMapping(path: '/avatar')]public function upload(#[RequestBody] AvatarUpload $req): array{ return ['tmp' => $req->avatar->getFilePath(), 'size' => $req->avatar->getSize()];}DTO properties may be typed as StringList, IntegerList, or FloatList (namespace dev\winterframework\type) to receive JSON arrays (or repeated field[] form params) as typed collections. Numbers are coerced to strings for StringList; whole-number strings are coerced to integers for IntegerList (floats such as 1.5, 2.0, or "2.0" are rejected); integers and numeric strings are coerced to floats for FloatList. Anything else is rejected with 400 Bad Request.
use dev\winterframework\type\FloatList;use dev\winterframework\type\IntegerList;use dev\winterframework\type\StringList;
class BulkRequest{ public StringList $csvRow; // ["a", "b"] — or ["a", 1] → ["a", "1"] public IntegerList $ids; // [1, "2"] → [1, 2] public FloatList $scores; // [1.5, 2, "3.25"] → [1.5, 2.0, 3.25]}