Skip to main content
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.
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.
array
List of RequestMethod constants this handler accepts — for example, [RequestMethod::GET, RequestMethod::POST]. Defaults to all HTTP methods when omitted.
string
An optional human-readable name for this mapping. Useful for logging and debugging.
array
List of media types this handler consumes — for example, ['application/json']. Requests with a non-matching Content-Type are rejected.
array
List of media types this handler produces — for example, ['application/json']. Used to negotiate the response Content-Type.

RequestMethod Enum Values

RequestMethod (namespace dev\winterframework\enums\RequestMethod) defines constants for every HTTP method the framework accepts in the method array.

Class-level and Method-level Paths Combined

ProductController.php
Path variables — for example, {id} — are not allowed in a class-level #[RequestMapping]. They may only appear in method-level path definitions.

HTTP Method Shortcuts

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

#[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.
string
Name of the incoming parameter. Defaults to the PHP variable name when omitted.
bool
Whether the parameter must be present in the request. Defaults to true. Set to false to make it optional.
mixed
Value used when the parameter is absent and required is false.
string
Where to read the value from. Defaults to 'request'. See the source table below.

Source Values

#[RequestParam] only accepts scalar PHP types (string, int, float, bool). For custom classes, use #[RequestBody] instead.

#[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.
Every {placeholder} that appears in the path must have a matching #[PathVariable] parameter, and every #[PathVariable] parameter must correspond to a {placeholder}. A mismatch raises an InvalidSyntaxException at startup.

#[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.
AddRequest.php
Only one #[RequestBody] parameter is allowed per handler method. You can freely combine it with #[PathVariable] and #[RequestParam] parameters in the same method signature.

Single-string-arg constructor fallback

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:
Any other constructor shape fails here and the request is rejected with 400 Bad Request.
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.

File uploads (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:
  • Declare text fields as scalars (string, int, float, bool) — values are type-cast.
  • Declare a file field as 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).
  • A multi-file field (<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.

Typed list properties

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.