Riutilizzo dei dati statici

1

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 è:

  1. È 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.
  2. Se è comune, ci sono dei pattern che risolvono questo problema?
  3. 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.

    
posta Sergey 01.06.2018 - 13:04
fonte

1 risposta

1

Se i vincoli sono usati dal validatore, dovrebbero essere un campo statico sulla classe Validator stessa. Inoltre, la classe del validatore è troppo generica per essere di qualche utilità. Dovrebbe specializzarsi nella convalida di una chiamata. Puoi usarlo in senso generico definendo un'interfaccia per i validatori:

interface Validator
{
    function validate($value) : ConstraintViolationListInterface
}

E quindi CallValidator può implementare l'interfaccia del Validatore e possedere i vincoli:

class CallValidator implements Validator
{
    private $validator;

    private static $constraints = 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(),
    ]);

    public function __construct(ValidatorInterface $validator)
    {
        $this->validator = $validator;
    }

    public function validate($value): ConstraintViolationListInterface
    {
        $violations = $this->validator->validate($value, self::$constraints);
        return $violations;
    }
}

Ora il validatore possiede i vincoli che controlla, sono statici (quindi una sola copia è conservata in memoria) e nessun altro può accedere a quei vincoli senza passare attraverso il validatore.

    
risposta data 01.06.2018 - 15:36
fonte

Leggi altre domande sui tag