1: <?php
2:
3: namespace LaravelUi5\Core\Attributes;
4:
5: use Attribute;
6: use LaravelUi5\Core\Enums\ParameterSource;
7: use LaravelUi5\Core\Enums\ValueType;
8:
9: /**
10: * Declarative runtime parameter definition for Parameterizable classes.
11: *
12: * Apply this attribute multiple times on a class (Ui5Action, Resource/Data provider,
13: * Report provider) to describe each expected request parameter. A central
14: * ParameterResolver will:
15: * - read all #[Parameter(...)] attributes,
16: * - extract raw values from the request (path/query/body),
17: * - cast them according to ParameterType,
18: * - resolve Eloquent models when type=Model,
19: * - enforce required/nullable/default semantics,
20: * - and return an immutable, normalized argument bag.
21: *
22: * **Key distinction**: `name` vs. `uriKey`
23: * - `name` = *logical backend name*
24: * Used as array key in the resolved argument bag and as identifier in the
25: * application code (controller, handler, service).
26: *
27: * - `uriKey` = *external transport key*
28: * The concrete identifier used on the communication layer (path segment or
29: * query string key). This is what the client sends, and what is reflected
30: * into the manifest.
31: *
32: * This separation allows:
33: * - Stable API contracts even if backend internals are refactored.
34: * - Aliasing: `uriKey` may differ from `name` (e.g. legacy URL key mapped to
35: * a cleaner internal parameter name).
36: * - Explicit, enterprise-grade clarity in manifests and generated clients.
37: *
38: * **Path resolution**
39: * - If you use a catch-all {uri} route, `uriKey` specifies the segment name.
40: * - The order of #[Parameter(...)] attributes in the source code defines the
41: * positional order of path parameters.
42: *
43: * **Example**
44: * <code>
45: * #[Parameter(
46: * name: 'projectModel',
47: * uriKey: 'project',
48: * type: ValueType::Model,
49: * source: ParameterSource::Path,
50: * model: Project::class
51: * ),
52: * Parameter(
53: * name: 'withPositions',
54: * uriKey: 'withPositions',
55: * type: ValueType::Bool,
56: * source: ParameterSource::Query,
57: * required: false,
58: * default: false
59: * )
60: * ]
61: * </code>
62: */
63: #[Attribute(Attribute::TARGET_CLASS | Attribute::IS_REPEATABLE)]
64: class Parameter
65: {
66: /**
67: * @param string $name Logical parameter name (used as array key in the resolved args)
68: * @param string $uriKey External transport key (path segment or query key, as seen by the client)
69: * @param ValueType $type Declared runtime type (drives casting/model binding)
70: * @param ParameterSource $source Where to read from: Path, Query, Body
71: * @param bool $required If true and no value is provided (after source lookup), the resolver fails (400)
72: * @param bool $nullable Allow explicit null (distinct from “missing”); if true and null provided, no cast is applied
73: * @param mixed $default Default used when value is missing and not required
74: * @param class-string|null $model Eloquent model FQCN; required when $type = ValueType::Model
75: */
76: public function __construct(
77: public string $name,
78: public string $uriKey,
79: public ValueType $type,
80: public ParameterSource $source = ParameterSource::Path,
81: public bool $required = true,
82: public bool $nullable = false,
83: public mixed $default = null,
84: public ?string $model = null,
85: ) {}
86: }
87: