Skip to content

Instantly share code, notes, and snippets.

@dmz9
Last active April 26, 2018 09:38
Show Gist options
  • Save dmz9/28a69a66c1ed555581e3f27c28662ee8 to your computer and use it in GitHub Desktop.
Save dmz9/28a69a66c1ed555581e3f27c28662ee8 to your computer and use it in GitHub Desktop.
subset symfony validator
<?php
namespace AppBundle\Rest\Request;
use AppBundle\Validator\Constraints\Subset;
use JMS\Serializer\Annotation as Serializer;
use Symfony\Component\Validator\Constraints as Assert;
/**
* Class CreateProductRequest
* @package AppBundle\Rest\Request
*/
class CreateProductRequest {
/**
* @var int[]
* @Assert\NotBlank()
* @Subset(multiple=true, entityClass="AppBundle\Entity\Category", repositoryMethod="getCategoriesIDs")
* @Serializer\Type(name="array<int>")
*/
public $category;
}
app.dto_validator.subset:
class: AppBundle\Validator\Constraints\SubsetValidator
tags:
- { name: validator.constraint_validator, alias: 'app.dto_validator.subset' }
arguments: ['@doctrine']
<?php
namespace AppBundle\Validator\Constraints;
use Symfony\Component\Validator\Constraints\Choice;
/**
* Constraint for the Subset Validator
* расширеная версия choice, использующая репозиторий как источник choices.
* для использования надо указать класс сущности для получения репозитория и метод для получения данных
*
* @Annotation
* @Target({"PROPERTY"})
*
*/
class Subset extends Choice {
public $service = 'app.dto_validator.subset';
public $entityClass;
public $repositoryMethod;
/**
* The validator must be defined as a service with this name.
*
* @return string
*/
public function validatedBy() {
return $this->service;
}
public function getRequiredOptions() {
return array_merge( [
'entityClass',
'repositoryMethod' ], parent::getRequiredOptions() );
}
}
<?php
namespace AppBundle\Validator\Constraints;
use Doctrine\Common\Persistence\ManagerRegistry;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\Constraints\ChoiceValidator;
use Symfony\Component\Validator\Exception\InvalidOptionsException;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
class SubsetValidator extends ChoiceValidator {
private $registry;
public function __construct( ManagerRegistry $registry ) {
$this->registry = $registry;
}
public function validate( $value, Constraint $constraint ) {
if ( ! $constraint instanceof Subset ) {
throw new UnexpectedTypeException( $constraint, __NAMESPACE__ . '\Subset' );
}
if ( ! class_exists( $constraint->entityClass ) ) {
throw new InvalidOptionsException( "Constraint should specify existing entity class",
[ 'entityClass' => $constraint->entityClass ] );
}
$repo = $this->registry->getRepository( $constraint->entityClass );
if ( ! method_exists( $repo, $constraint->repositoryMethod ) ) {
throw new InvalidOptionsException( "Constraint should specify existing repository method", [
'entityClass' => $constraint->entityClass,
'repositoryMethod' => $constraint->repositoryMethod ] );
}
$constraint->choices = call_user_func([$repo, $constraint->repositoryMethod]);
parent::validate( $value, $constraint );
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment