PHP code example of cryonighter / valid-request-bundle

1. Go to this page and download the library: Download cryonighter/valid-request-bundle library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

cryonighter / valid-request-bundle example snippets


return [
    // ...
    Cryonighter\ValidRequestBundle\ValidRequestBundle::class => ['all' => true],
];

use Cryonighter\ValidRequestBundle\Attribute\ValidRequest;
use Symfony\Component\Validator\Constraints as Assert;

#[ValidRequest]
class AuthUserRequest
{
    public function __construct(
        #[Assert\NotBlank]
        #[Assert\Email]
        public string $login,

        #[Assert\NotBlank]
        #[Assert\Length(min: 8)]
        public string $password,
    ) {}
}

use Cryonighter\ValidRequestBundle\Attribute\ValidRequest;

class AuthController
{
    #[Route('/user/auth', methods: [Request::METHOD_POST])]
    public function auth(
        #[ValidRequest] AuthUserRequest $authUserRequest,
    ): Response {
        // ...
    }
}

use Cryonighter\ValidRequestBundle\Attribute\ValidRequest;

class AuthController
{
    #[Route('/user/auth', methods: [Request::METHOD_GET, Request::METHOD_POST])]
    public function auth(
        #[ValidRequest] ?AuthUserRequest $authUserRequest,
    ): Response {
        if ($authUserRequest) {
            // Auth user
        } else {
            // Render auth form
        }
    }
}

use Cryonighter\ValidRequestBundle\Attribute\ValidRequest;
use Symfony\Component\Validator\ConstraintViolationListInterface;

class AuthController
{
    #[Route('/user/auth', methods: [Request::METHOD_GET, Request::METHOD_POST])]
    public function auth(
        ?AuthUserRequest $authUserRequest,
        ?ConstraintViolationListInterface $violations,
    ): Response {
        // ...
    }
}

use Cryonighter\ValidRequestBundle\Attribute\ValidRequest;
use Cryonighter\ValidRequestBundle\Enum\RequestValueSource;

#[ValidRequest(source: RequestValueSource::query)]
class GoodsFilterRequest
{
    // ...
}

use Cryonighter\ValidRequestBundle\Attribute\ValidRequest;

#[ValidRequest]
class SearchRequest
{
    public function __construct(
        #[Assert\NotBlank]
        public readonly string $query,

        public readonly string $sort = 'created_at',

        public readonly int $limit = 20,

        public readonly ?string $filter = null,
    ) {}
}

use Cryonighter\ValidRequestBundle\Attribute\ValidRequest;
use Symfony\Component\Validator\Constraints as Assert;

class Settings
{
    public function __construct(
        public string $lang,
    ) {}
}

#[ValidRequest]
class ProfileUserRequest
{
    public function __construct(
        #[Assert\Valid]
        public ?Settings $settings,
    ) {}
}

use Cryonighter\ValidRequestBundle\Attribute\ValidRequest;
use Symfony\Component\Validator\Constraints as Assert;

#[ValidRequest]
class CheckoutRequest
{
    public function __construct(
        // Тип свойства — интерфейс. Конкретный класс берётся из Assert\Type.
        #[Assert\Type(type: CardPayment::class)]
        #[Assert\Valid]
        public PaymentMethodInterface $method,

        // Тип свойства — базовый класс, но нужен именно наследник.
        #[Assert\Type(type: EmailNotification::class)]
        #[Assert\Valid]
        public Notification $notification,

        // Несколько Assert\Type с группами: класс выбирается по активной группе.
        // Для группы Card — CardPayment, для группы Crypto — CryptoPayment.
        #[Assert\Type(type: CardPayment::class, groups: ['Card'])]
        #[Assert\Type(type: CryptoPayment::class, groups: ['Crypto'])]
        #[Assert\Valid]
        public AbstractPaymentMethod $refund,

        // Тип mixed: одна группа собирает объект, другая оставляет примитивный id.
        #[Assert\Type(type: CardPayment::class, groups: ['Full'])]
        #[Assert\Type(type: 'int', groups: ['Ref'])]
        public mixed $source,
    ) {}
}

use Cryonighter\ValidRequestBundle\Attribute\ValidRequest;
use Symfony\Component\Validator\Constraints as Assert;

class Contact
{
    public function __construct(
        #[Assert\Choice(choices: ['email', 'phone'])]
        public string $type,

        #[Assert\Length(min: 5, max: 100)]
        public string $value,
    ) {}
}

#[ValidRequest]
class ProfileUserRequest
{
    public function __construct(
        #[Assert\NotBlank]
        #[Assert\All([
            new Assert\NotBlank(),
            new Assert\Type(Contact::class),
        ])]
        #[Assert\Valid]
        public array $contacts,
    ) {}
}

use Cryonighter\ValidRequestBundle\Attribute\ValidRequest;
use Symfony\Component\Validator\Constraints as Assert;

class Wizard
{
    public function __construct(
        #[Assert\NotBlank]
        #[Assert\Length(min: 2, max: 50)]
        public string $name,

        #[Assert\Range(min: 1, max: 100)]
        public int $spellPower,
    ) {}
}

class Warrior
{
    public function __construct(
        #[Assert\NotBlank]
        #[Assert\Length(min: 2, max: 50)]
        public string $name,

        #[Assert\Positive]
        public int $strength,
    ) {}
}

#[ValidRequest]
class PartyRequest
{
    public function __construct(
        #[Assert\All([
            new Assert\Type(type: Wizard::class, groups: ['Wizards']),
            new Assert\Type(type: Warrior::class, groups: ['Warriors']),
        ])]
        #[Assert\Valid]
        public array $party,
    ) {}
}

#[Route('/party/wizards', methods: [Request::METHOD_POST])]
public function createWizards(
    #[ValidRequest(groups: ['Default', 'Wizards'])]
    PartyRequest $request,
): Response {
    // $request->party — массив инстансов Wizard
}

#[Route('/party/warriors', methods: [Request::METHOD_POST])]
public function createWarriors(
    #[ValidRequest(groups: ['Default', 'Warriors'])]
    PartyRequest $request,
): Response {
    // $request->party — массив инстансов Warrior
}

#[Assert\Valid(groups: ['Default', 'Wizards', 'Warriors'])]
public array $party;

use Cryonighter\ValidRequestBundle\Attribute\BindRequestParam;

class ProfileUserRequest
{
    public function __construct(
        #[BindRequestParam(name: 'id')]
        #[Assert\Positive]
        public int $userId,
    ) {}
}

use Cryonighter\ValidRequestBundle\Attribute\BindRequestParam;

class ProfileUserRequest
{
    public function __construct(
        #[BindRequestParam(source: RequestValueSource::attributes)]
        #[Assert\Language]
        public string $lang,
    ) {}
}

use Cryonighter\ValidRequestBundle\Attribute\BindRequestParam;
use Cryonighter\ValidRequestBundle\Attribute\ValidRequest;
use Cryonighter\ValidRequestBundle\Enum\RequestValueSource;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\Validator\Constraints as Assert;

#[ValidRequest]
class ProfileUserRequest
{
    public function __construct(
        #[BindRequestParam(source: RequestValueSource::files)]
        #[Assert\File(
            maxSize: '64k',
            mimeTypes: [
                'image/jpeg',
                'image/png',
                'image/gif',
                'image/bmp',
                'image/webp',
                'image/svg+xml',
                'image/avif',
                'image/apng',
            ],
            maxSizeMessage: 'File is too large ({{ size }} {{ suffix }}). Maximum size is {{ limit }} {{ suffix }}',
            mimeTypesMessage: 'Please upload the correct image ({{ types }})'
        )]
        public ?UploadedFile $avatar,
    ) {}
}

#[ValidRequest(groups: ['Default', 'Create'])]

class CountryRequest
{
    public function __construct(
        #[BindRequestParam(source: RequestValueSource::attributes, groups: ['Update'])]
        #[Assert\NotBlank]
        #[Assert\Country]
        public string $code,

        #[Assert\NotBlank]
        public string $name,
    ) {
    }
}

class AuthController
{
    #[Route('/country', methods: [Request::METHOD_POST])]
    public function create(
        #[ValidRequest(groups: ['Default', 'Create'])]
        ?CountryRequest $countryRequest,
    ): Response {
        // ...
    }

    #[Route('/country/{code}', methods: [Request::METHOD_PUT])]
    public function update(
        string $code,

        #[ValidRequest(groups: ['Default', 'Update'])]
        ?CountryRequest $countryRequest,
    ): Response {
        // ...
    }
}

use App\ValueObject\UserId;
use Cryonighter\ValidRequestBundle\Caster\CastContext;
use Cryonighter\ValidRequestBundle\Caster\CastResult;
use Cryonighter\ValidRequestBundle\Caster\ValueCasterInterface;
use Cryonighter\ValidRequestBundle\Schema\PropertyType;

class UserIdCaster implements ValueCasterInterface
{
    public function supports(PropertyType $type): bool
    {
        return !$type->builtin && is_a($type->name, UserId::class, true);
    }

    public function cast(mixed $value, CastContext $context): CastResult
    {
        if (is_numeric($value) && $value > 0) {
            return CastResult::converted(new UserId($value));
        }

        return CastResult::skip();
    }
}

use Cryonighter\ValidRequestBundle\Contract\PatcherInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\String\Slugger\SluggerInterface;

class SlugPatcher implements PatcherInterface
{
    public function __construct(private SluggerInterface $slugger)
    {
    }

    public function patch(mixed $value, Request $request): mixed
    {
        if ($value) {
            return $value;
        }

        $title = $request->request->get('title', '');

        return strtolower($this->slugger->slug($title));
    }
}

use Cryonighter\ValidRequestBundle\Attribute\BindRequestParam;
use Cryonighter\ValidRequestBundle\Attribute\ValidRequest;
use Symfony\Component\Validator\Constraints as Assert;

#[ValidRequest]
class ArticleRequest
{
    public function __construct(
        #[Assert\NotBlank]
        #[Assert\Length(max: 255)]
        public string $title,

        #[BindRequestParam(patcher: SlugPatcher::class)]
        #[Assert\NotBlank]
        #[Assert\Regex(pattern: '/^[a-z0-9]+(?:-[a-z0-9]+)*$/')]
        public string $slug,
    ) {}
}

use Cryonighter\ValidRequestBundle\Attribute\BindRequestParam;

class UserRequest
{
    #[BindRequestParam(name: 'login')]
    private string $username;

    public function __construct(
        #[BindRequestParam(name: 'login')]
        string $email,
    ) {
        $this->username = $email;
    }
}

use Cryonighter\ValidRequestBundle\Attribute\BindRequestParam;

class UserRequest
{
    #[BindRequestParam(name: 'login')]
    private string $username;

    public function setUsername(string $email): void
    {
        $this->username = $email;
    }
}

use Cryonighter\ValidRequestBundle\Attribute\BindRequestParam;

class UserRequest
{
    #[BindRequestParam(name: 'login')]
    public string $username;
}

use Cryonighter\ValidRequestBundle\Attribute\BindRequestParam;

class UserRequest
{
    #[BindRequestParam(name: 'login')]
    private string $username;
}

use Symfony\Component\Serializer\Attribute\DiscriminatorMap;

#[DiscriminatorMap(
    typeProperty: 'type',
    mapping: [
        'product' => Product::class,
        'shipping' => Shipping::class,
    ],
    defaultType: 'product',
)]
interface InvoiceItemInterface
{
    // ...
}

#[Assert\Type(type: Product::class, groups: ['Product'])]
#[Assert\Type(type: Shipping::class, groups: ['Shipping'])]
#[Assert\Valid]
public InvoiceItemInterface $invoice;

#[Assert\All([
    new Assert\Type(type: Product::class, groups: ['Product']),
    new Assert\Type(type: Shipping::class, groups: ['Shipping']),
])]
#[Assert\Valid]
public array $invoices;