The component provides an ability to create nested filters and a nested array of filters. To demonstrate the composition, we will use a sample filter:
namespace App\Request;
use Spiral\Filters\Attribute\Input\Post;
use Spiral\Filters\Model\Filter;
class AddressFilter extends Filter
{
#[Post]
public string $city;
#[Post]
public string $address;
}
This Filter can accept the following data format:
{
"city": "San Francisco",
"address": "Address"
}
You can create compound filters by nesting other filters inside them. Simply declare the field with a child filter
and add the attribute Spiral\Filters\Attribute\NestedFilter
:
namespace App\Request;
use Spiral\Filters\Attribute\Input\Post;
use Spiral\Filters\Attribute\NestedFilter;
use Spiral\Filters\Model\Filter;
class ProfileFilter extends Filter
{
#[Post]
public string $name;
#[NestedFilter(class: AddressFilter::class)]
public AddressFilter $address;
}
This Filter will accept the data in the format:
{
"name": "Antony",
"address": {
"city": "San Francisco",
"address": "Address"
}
}
You can get access to the nested Filter using class properties:
public function index(ProfileFilter $profile): void
{
dump($profile->address->city); // San Francisco
}
Both the filters will be validated together. In case of an error in the address
filter, the error will be mounted in a sub-array:
{
"name": "This field is required.",
"address": {
"city": "This field is required."
}
}
In some cases, you might need to use a data prefix different from the actual key assigned to the nested Filter, use the
parameter prefix
in the NestedFilter
:
namespace App\Request;
use Spiral\Filters\Attribute\Input\Post;
use Spiral\Filters\Attribute\NestedFilter;
use Spiral\Filters\Model\Filter;
class ProfileFilter extends Filter
{
#[Post]
public string $name;
#[NestedFilter(class: AddressFilter::class, prefix: 'addr')]
public AddressFilter $address;
}
This Filter can accept the following data format:
{
"name": "This field is required.",
"addr": {
"city": "This field is required."
}
}
Note
You can skip the use of theaddress
key internally, errors will be mounted accordingly.
You can populate an array of filters at the same time. Use an array property type and add theattribute
Spiral\Filters\Attribute\NestedArray
with a Filter class for each element as the parameter class
and data input:
use Spiral\Filters\Attribute\Input\Post;
use Spiral\Filters\Attribute\NestedArray;
use Spiral\Filters\Model\Filter;
class MultipleAddressesFilter extends Filter
{
#[Post]
public string $name;
#[NestedArray(class: AddressFilter::class, input: new Post('addresses'))]
public array $addresses;
}
Such Filter can accept the following data format:
{
"key": "value",
"addresses": [
{
"city": "San Francisco",
"address": "Address"
},
{
"city": "Minsk",
"address": "Address #2"
}
]
}
You can access array filters via the array accessor:
public function index(MultipleAddressesFilter $ma)
{
dump($ma->addresses[0]->city); // San Francisco
dump($ma->addresses[1]->city); // Minsk
}
Note
The errors will be mounted accordingly.
You can create an array of filters based on a data prefix different from the key name in the Filter, use the
parameter prefix
in the NestedArray
:
namespace App\Request;
use Spiral\Filters\Attribute\Input\Input;
use Spiral\Filters\Attribute\Input\Post;
use Spiral\Filters\Attribute\NestedArray;
use Spiral\Filters\Model\Filter;
class MultipleAddressesFilter extends Filter
{
#[Post]
public string $name;
#[NestedArray(class: AddressFilter::class, input: new Input('addresses'), prefix: 'addr')]
public array $addresses;
}
This Filter supports the following data format:
{
"key": "value",
"addr": [
{
"city": "San Francisco",
"address": "Address"
},
{
"city": "Minsk",
"address": "Address #2"
}
]
}
You can still access the nested array filters using the addresses
property:
public function index(MultipleAddressesFilter $ma): void
{
dump($ma->addresses[0]->city); // San Francisco
dump($ma->addresses[1]->city); // Minsk
}
You can use nested child filters as part of a larger composite Filter. Use the prefix .
(root) to do that:
namespace App\Request;
use Spiral\Filters\Attribute\Input\Post;
use Spiral\Filters\Attribute\NestedFilter;
use Spiral\Filters\Model\Filter;
class ProfileFilter extends Filter
{
#[Post]
public string $name;
#[NestedFilter(class: AddressFilter::class, prefix: '.')]
public AddressFilter $address;
}
The AddressFilter
will receive data from the top-level, meaning you can send a request like that:
{
"name": "Antony",
"city": "San Francisco",
"address": "Address"
}