問題を解決しました。解決策を共有したいだけです。
考えられる解決策の 1 つは、 Callback 制約を使用することです。たとえば、質問で提供されているタグ リストの例に従います。
/**
* @Assert\Callback(methods={"isTagStringValid"})
*/
class AFormModel{
protected $tags;
public function isTagStringValid(ExecutionContext $context){
$tagsExploded = explode(',', $this->tags);
if(count($tagsExploded)==0){
$context->addViolationAtSubPath('tags', 'Insert at least a tag', array(), null);
}
if(count($tagsExploded)==1 && $tagsExploded[0]==='')
$context->addViolationAtSubPath('tags', 'Insert at least a tag', array(), null);
}
else if(count($tagsExploded)>10){
$context->addViolationAtSubPath('tags', 'Max 10 values', array(), null);
}
}
}
より洗練された方法は、「トークン」バリデーターを定義することです。次に例を示します。
namespace .....
use Symfony\Component\Validator\Constraint;
/**
* @Annotation
*/
class Token extends Constraint {
public $min;
public $max;
public $minMessage = '{{ min }} token(s) are expected';
public $maxMessage = '{{ max }} token(s) are expected';
public $invalidMessage = 'This value should be a string.';
public $delimiter = ',';
public function __construct($options = null){
parent::__construct($options);
if (null === $this->min && null === $this->max) {
throw new MissingOptionsException('Either option "min" or "max" must be given for constraint ' . __CLASS__, array('min', 'max'));
}
}
}
バリデータクラスは次のとおりです。
namespace ...
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
class TokenValidator extends ConstraintValidator {
public function isValid($value, Constraint $constraint) {
if ($value === null) {
return;
}
if(!is_string($value)){
$this->context->addViolation($constraint->invalidMessage, array(
'{{ value }}' => $value,
));
return;
}
$tokensExploded = explode($constraint->delimiter, $value);
$tokens = count($tokensExploded);
if($tokens==1){
if($tokensExploded[0]==='')
$tokens = 0;
}
if (null !== $constraint->max && $tokens > $constraint->max) {
$this->context->addViolation($constraint->maxMessage, array(
'{{ value }}' => $value,
'{{ limit }}' => $constraint->max,
));
return;
}
if (null !== $constraint->min && $tokens < $constraint->min) {
$this->context->addViolation($constraint->minMessage, array(
'{{ value }}' => $value,
'{{ limit }}' => $constraint->min,
));
}
}
}
このようにして、ユーザー定義のバリデーターをインポートし、質問で提案したようにどこでも使用できます。