Descriverò la situazione e alla fine porrò delle domande.
Devo convalidare un valore scalare usando il componente Symfony Validator . Il valore è un array associativo. Ora ho definito i seguenti vincoli di validazione in base alla struttura prevista:
new Constraints\Collection([
'Call' => new Constraints\NotBlank(),
'Start Time' => new Constraints\DateTime(['format' => 'd M Y H:i:s']),
'Caller ID' => new Nullable(),
'Calling Party Number' => new Nullable(new Phone()),
'Dialed Party Number' => new Nullable(new Phone()),
'Call Duration' => new Constraints\Regex(['pattern' => '/^\d{1,2}:\d{1,2}:\d{1,2}$/']),
'Receiving Agent' => new Nullable(),
'Is Abandoned' => new Constraints\Regex(['pattern' => '/^(True|False)$/']),
'Total Queue Duration' => new Constraints\Regex(['pattern' => '/^\d{1,2}:\d{1,2}:\d{1,2}$/']),
'Account Code' => new Nullable(),
'Initial Tag' => new Constraints\NotBlank(),
]);
dove Nullable
e Phone
sono vincoli personalizzati.
Questi vincoli devono essere riutilizzabili e per raggiungere questo obiettivo ho creato il seguente servizio di convalida:
use Symfony\Component\Validator\ConstraintViolationListInterface;
use Symfony\Component\Validator\Validator\ValidatorInterface;
class Validator
{
private $validator;
public function __construct(ValidatorInterface $validator)
{
$this->validator = $validator;
}
public function validate($value, ConstraintsProvider $constraintsProvider): ConstraintViolationListInterface
{
$violations = $this->validator->validate($value, $constraintsProvider->getConstraints());
return $violations;
}
}
E definito l'interfaccia ConstraintsProvider
:
interface ConstraintsProvider
{
public function getConstraints(): array;
}
che sarà implementato dai newables, incapsulando vincoli di validazione come questo:
class Call implements ConstraintsProvider
{
public function getConstraints(): array
{
return [
new Constraints\Collection([
'Call' => new Constraints\NotBlank(),
'Start Time' => new Constraints\DateTime(['format' => 'd M Y H:i:s']),
'Caller ID' => new Nullable(),
'Calling Party Number' => new Nullable(new Phone()),
'Dialed Party Number' => new Nullable(new Phone()),
'Call Duration' => new Constraints\Regex(['pattern' => '/^\d{1,2}:\d{1,2}:\d{1,2}$/']),
'Receiving Agent' => new Nullable(),
'Is Abandoned' => new Constraints\Regex(['pattern' => '/^(True|False)$/']),
'Total Queue Duration' => new Constraints\Regex(['pattern' => '/^\d{1,2}:\d{1,2}:\d{1,2}$/']),
'Account Code' => new Nullable(),
'Initial Tag' => new Constraints\NotBlank(),
])
];
}
}
E la convalida viene eseguita come
$validator=new Validator();
$validator->validate(['foo'=>'bar'],new Call());
Quello che mi stavo chiedendo è:
- È prassi comune aggiungere un livello di astrazione aggiuntivo per incapsulare alcuni dati che devono essere riusabili in tutta l'app? Il mio caso sono i vincoli di validazione.
- Se è comune, ci sono dei pattern che risolvono questo problema?
- C'è un modo migliore per risolvere il problema che ho dovuto affrontare?
Aggiorna
La classe Call
non è un'entità, è solo un involucro attorno ai vincoli da cui il servizio di convalida li prende. Il servizio di convalida viene utilizzato per convalidare i dati prima di riempire con loro un'entità. L'entità corrispondente ha la propria convalida definita nella sua configurazione.