Validation
Evo will automatically validate request data to every parameters that is attached with attribute that implements Emsifa\Evo\Contracts\RequestValidator
interface. Evo's built-in Query
, Header
, Cookie
, Param
, and Body
attributes is doing validation because they are implementing that interface.
#
Validating Query, Header, Cookie, and ParamFor Query
, Header
, Cookie
, and Param
attributes, by default they choose validation rules by looking for its parameter type. For example:
#[Get]public function index( #[Query] int $limit, #[Query] int $offset, #[Query] ?string $keyword = null,){}
Evo will apply required|numeric
to $limit
and $offset
, also apply rule nullable|string
rule to $keyword
.
But you can also use your own validation rules by giving $rules
to attribute. For example:
#[Get]public function index( #[Query(rules: 'required|numeric|min:10')] int $limit, #[Query(rules: 'required|numeric|min:0')] int $offset, #[Query] ?string $keyword = null,){}
Now $limit
and $offset
parameters will use your defined rules instead of using the default rules.
#
Validating BodyFor Body
attribute. It will scan its DTO properties, and choose rules for each properties by looking for the property type and finding Illuminate\Contracts\Validation\Rule
attributes attached to it.
For example, if you have controller like this:
#[Post('checkout')]public function checkout(#[Body] CheckoutOrderDto $dto){ // ...}
Where CheckoutOrderDto
has properties like this:
<?php
namespace App\Dto;
use Emsifa\Evo\Dto;use Emsifa\Evo\Rules;
class CheckoutOrderDto extends Dto{ #[Rules\Required] #[Rules\Numeric] public string $phone;
#[Rules\Required] public string $address;
#[Rules\Required] #[Rules\Numeric] #[Rules\Size(11)] public string $subdistrict_id;
#[Rules\Required] #[Rules\Numeric] #[Rules\Size(5)] public string $postal_code;
#[ArrayOf(CheckoutOrderItemDto::class)] public array $items;}
And CheckoutOrderItemDto
like this:
<?php
namespace App\Dto;
use Emsifa\Evo\Dto;use Emsifa\Evo\Rules;
class CheckoutOrderItemDto extends Dto{ #[Rules\Required] #[Rules\Exists('products', 'id')] public string $product_id;
#[Rules\Required] #[Rules\Numeric] public int $qty;}
The Body
attribute will do this following validation for you:
Validator::make($data, [ 'phone' => 'required|string|numeric', 'address' => 'required|string', 'subdistrict_id' => 'required|string|numeric|size:11', 'postal_code' => 'required|string|numeric|size:5', 'items' => 'required|array', 'items.*.product_id' => 'required|string|exists:product,id', 'items.*.qty' => 'required|numeric',]);
#
Create Your Own Validation RuleEvo's validation rules is basically class implementing Illuminate\Contracts\Validation\Rule
interface and has Attribute
attribute attached on it.
For example, we will create Bit
rule that only accepts string with "0" and "1" characters.
First, create app/Rules/Bit.php
file.
Then write following code below:
<?php
namespace App\Rules;
use Attribute;use Illuminate\Contracts\Validation\Rule;
#[Attribute(Attribute::TARGET_PROPERTY)]class Bit implements Rule{ public function __construct(protected string $message = '') { }
public function passes($attribute, $value) { return is_string($value) && preg_match("/^(0|1)+$/", $value); }
public function message() { return __($this->message) ?: __("validation.bit") ?: "Invalid bit string"; }}
Now you can attach it to your DTO's property like this:
<?php
namespace App\Dto;
use Emsifa\Evo\Dto;use Emsifa\Evo\Rules;use App\Rules\Bit;
class MyDto extends Dto{ #[Rules\Required] #[Bit] public string $bit_string;}