You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: core/filters.md
+193-6Lines changed: 193 additions & 6 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -135,6 +135,108 @@ class Book
135
135
```
136
136
137
137
This configuration creates a dynamic parameter. API clients can now filter on any of the properties configured in the `SearchFilter` (in this case, `title` and `description`) by using a URL like `/books?search[title]=Ring` or `/books?search[description]=journey`.
138
+
139
+
When using the `:property` placeholder, API Platform automatically populates the parameter's `extraProperties` with a `_properties` array containing all the available properties for the filter. Your filter can access this information:
140
+
141
+
```php
142
+
public function apply(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, ?Operation $operation = null, array $context = []): void
// This allows your filter to know which properties are available for filtering
149
+
}
150
+
```
151
+
152
+
### Restricting Properties with `:property` Placeholders
153
+
154
+
There are two different approaches to property restriction depending on your filter design:
155
+
156
+
#### 1. Legacy Filters (SearchFilter, etc.) - Not Recommended
157
+
158
+
> [!WARNING]
159
+
> Filters that extend `AbstractFilter` with pre-configured properties are considered legacy. They don't support property restriction via parameters and may be deprecated in future versions. Consider using per-parameter filters instead for better flexibility and performance.
160
+
161
+
For existing filters that extend `AbstractFilter` and have pre-configured properties, the parameter's `properties` does **not** restrict the filter's behavior. These filters use their own internal property configuration:
162
+
163
+
```php
164
+
<?php
165
+
// This does NOT restrict SearchFilter - it processes all its configured properties
166
+
'search[:property]' => new QueryParameter(
167
+
properties: ['title', 'author'], // Only affects _properties, doesn't restrict filter
168
+
filter: new SearchFilter(properties: ['title' => 'partial', 'description' => 'partial'])
169
+
)
170
+
171
+
// To restrict legacy filters, configure them with only the desired properties:
172
+
'search[:property]' => new QueryParameter(
173
+
filter: new SearchFilter(properties: ['title' => 'partial', 'author' => 'exact'])
174
+
)
175
+
```
176
+
177
+
#### 2. Per-Parameter Filters (Recommended)
178
+
179
+
> [!NOTE]
180
+
> Per-parameter filters are the modern approach. They provide better performance (only process requested properties), cleaner code, and full support for parameter-based property restriction.
181
+
182
+
Modern filters that work on a per-parameter basis can be effectively restricted using the parameter's `properties`:
183
+
184
+
```php
185
+
<?php
186
+
// src/Filter/PartialSearchFilter.php
187
+
use ApiPlatform\Doctrine\Orm\Filter\FilterInterface;
188
+
use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface;
189
+
use ApiPlatform\Metadata\Operation;
190
+
use Doctrine\ORM\QueryBuilder;
191
+
192
+
final class PartialSearchFilter implements FilterInterface
193
+
{
194
+
public function apply(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, ?Operation $operation = null, array $context = []): void
// This WILL restrict to only title and author properties
220
+
'search[:property]' => new QueryParameter(
221
+
properties: ['title', 'author'], // Only these properties get parameters created
222
+
filter: new PartialSearchFilter()
223
+
)
224
+
]
225
+
)
226
+
])]
227
+
class Book {
228
+
// ...
229
+
}
230
+
```
231
+
232
+
**How it works:**
233
+
1. API Platform creates individual parameters: `search[title]` and `search[author]` only
234
+
2. URLs like `/books?search[description]=foo` are ignored (no parameter exists)
235
+
3. Each parameter calls the filter with its specific property via `$parameter->getProperty()`
236
+
4. The filter processes only that one property
237
+
238
+
This approach is recommended for new filters as it's more flexible and allows true property restriction via the parameter configuration.
239
+
138
240
Note that invalid values are usually ignored by our filters, use [validation](#parameter-validation) to trigger errors for wrong parameter values.
139
241
140
242
## OpenAPI and JSON Schema
@@ -291,7 +393,7 @@ Parameter Providers are powerful services that can inspect, transform, or provid
291
393
292
394
### `IriConverterParameterProvider`
293
395
294
-
This built-in provider takes an IRI string (e.g., `/users/1`) and converts it into the corresponding Doctrine entity object.
396
+
This built-in provider takes an IRI string (e.g., `/users/1`) and converts it into the corresponding Doctrine entity object. It supports both single IRIs and arrays of IRIs.
295
397
296
398
```php
297
399
<?php
@@ -307,6 +409,10 @@ use ApiPlatform\State\ParameterProvider\IriConverterParameterProvider;
307
409
uriTemplate: '/with_parameters_iris',
308
410
parameters: [
309
411
'dummy' => new QueryParameter(provider: IriConverterParameterProvider::class),
412
+
'related' => new QueryParameter(
413
+
provider: IriConverterParameterProvider::class,
414
+
extraProperties: ['fetch_data' => true] // Forces fetching the entity data
The `IriConverterParameterProvider` supports the following options in `extraProperties`:
438
+
439
+
-**`fetch_data`**: Boolean (default: `false`) - When `true`, forces the IRI converter to fetch the actual entity data instead of just creating a reference.
440
+
324
441
### `ReadLinkParameterProvider`
325
442
326
443
This provider fetches a linked resource from a given identifier. This is useful when you need to load a related entity to use later, for example in your own state provider.
@@ -370,14 +487,35 @@ The provider will:
370
487
- Optionally use the `uri_template` from `extraProperties` to construct the proper operation for loading the resource
371
488
- Return the loaded entity, making it available in your state provider
372
489
373
-
You can also control error handling by setting `throw_not_found` to `false` in the `extraProperties` to prevent exceptions when the linked resource is not found:
490
+
#### Array Support
491
+
492
+
Both `IriConverterParameterProvider` and `ReadLinkParameterProvider` support processing arrays of values. When you pass an array of identifiers or IRIs, they will return an array of resolved entities:
493
+
494
+
```php
495
+
// For IRI converter: ?related[]=/dummies/1&related[]=/dummies/2
496
+
// For ReadLink provider: ?dummies[]=uuid1&dummies[]=uuid2
| `hydra` | Hide the parameter from Hydra documentation (`false`). |
569
714
| `security` | A [Symfony expression](https://symfony.com/doc/current/security/expressions.html) to control access to the parameter. |
570
715
716
+
## Parameter Security
717
+
718
+
You can secure individual parameters using Symfony expression language. When a security expression evaluates to `false`, the parameter will be ignored and treated as if it wasn't provided.
719
+
720
+
```php
721
+
<?php
722
+
// api/src/Resource/SecureResource.php
723
+
use ApiPlatform\Metadata\ApiResource;
724
+
use ApiPlatform\Metadata\GetCollection;
725
+
use ApiPlatform\Metadata\HeaderParameter;
726
+
use ApiPlatform\Metadata\QueryParameter;
727
+
728
+
#[ApiResource(operations: [
729
+
new GetCollection(
730
+
uriTemplate: '/secure_resources',
731
+
parameters: [
732
+
'name' => new QueryParameter(
733
+
security: 'is_granted("ROLE_ADMIN")'
734
+
),
735
+
'auth' => new HeaderParameter(
736
+
security: '"secured" == auth',
737
+
description: 'Only accessible when auth header equals "secured"'
738
+
),
739
+
'secret' => new QueryParameter(
740
+
security: '"secured" == secret',
741
+
description: 'Only accessible when secret parameter equals "secured"'
742
+
)
743
+
]
744
+
)
745
+
])]
746
+
class SecureResource
747
+
{
748
+
// ...
749
+
}
750
+
```
751
+
752
+
In the security expressions, you have access to:
753
+
- Parameter values by their key name (e.g., `auth`, `secret`)
0 commit comments