2016-03-28 25 views

Odpowiedz

8

Jeśli chcesz sprawdzić poprawność obiekt z dowolnej logiki związanej z zewnętrznego uzależnienia (w przypadku usługi @security.context uzyskać bieżącego użytkownika) ... należy:

  • utworzyć niestandardową Potwierdzanie ograniczenie
  • stworzyć niestandardowy walidator usługi wykorzystywane przez ograniczenie
  • wstrzyknąć usługę @security.context do walidatora
  • skorzystać z tej nowo utworzonej ograniczenia poprawności do sprawdzania poprawności podmiot,

Rozwiązaniem jest opisana w rozdziale dokumentacji Validators with Dependencies


This video pokazuje, dlaczego nie jest to absolutnie konieczne, aby mieć następującą Redbull walidator.

modelu/Entity

use FamilyGuy\Validator\Constraints\Peter as PeterIsNotAllowedToOrder; 

class Order 
{ 
    /** @PeterIsNotAllowedToOrder/RedBull */ 
    public $drink; 

Config

# app/config/services.yml 
services: 
    validator.red_bull: 
     class: FamilyGuy\Validator\Constraints\Peter\RedBullValidator 
     # for symfony < 2.6 use @security.context 
     arguments: ["@security.token_storage"] 
     tags: 
      - name: "validator.constraint_validator" 
       alias: "peter_red_bull_constraint_validator" 

Ograniczenie

use Symfony\Component\Validator\Constraint; 

namespace FamilyGuy\Validator\Constraints\Peter; 

/** 
* @Annotation 
*/ 
class RedBull extends Constraint 
{ 
    /** @var string */ 
    public $message = 'Peter... You are not allowed to order %drink%.'; 

    /** @return string */ 
    public function validatedBy() 
    { 
     // has to match the validator service's alias ! 
     return 'peter_red_bull_constraint_validator'; 
    } 
} 

Validator:

// For symfony < 2.6 use SecurityContextInterface 
// use Symfony\Component\Security\Core\SecurityContextInterface; 
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; 
use Symfony\Component\Validator\Constraint; 
use Symfony\Component\Validator\ConstraintValidator; 

namespace FamilyGuy\Validator\Constraints\Peter; 

class RedBullValidator extends ConstraintValidator 
{ 

    /** @var TokenStorageInterface|SecurityContextInterface */ 
    protected $tokenStorage; 

    /** @param TokenStorageInterface|SecurityContextInterface $token_storage */ 
    public function __construct(TokenStorageInterface $token_storage) 
    { 
     $this->tokenStorage = $token_storage; 
    } 

    public function validate($drink, Constraint $constraint) 
    { 
     $currentUser = $this->tokenStorage->getToken()->getUser()->getName(); 

     if ($currentUser !== "Peter") { 
      return; 
     } 

     if ($drink !== "RedBull") { 
      return 
     } 

     $this->context->buildViolation($constraint->message) 
      ->setParameter('%drink%', $drink) 
      ->addViolation() 
     ; 
    } 

Nie można i nie powinno się używać Callback ograniczenie do sprawdzania przed każdym uzależnienia zewnętrznego.

Nie należy próbować wstrzykiwać żadnych zależności sprawdzania poprawności do modelu domeny lub podmiotów bezpośrednio.

Logika walidacji powinna być przechowywana poza jednostkami w ogóle.

Adnotacje są już pewnego rodzaju miękkim sprzężeniem między jednostkami i walidatorem symfony. Z tego powodu zaleca się zwykle używanie konfiguracji xml do mapowania doktryn i walidacji.

+0

Dziękuję. Ale to nie działa dla mnie. SecurityContextInterface wydaje się być przestarzałe od wersji 2.6 lub coś podobnego. Używam symfony3. – rvaliev

+1

Zaktualizowano odpowiedź. W Symfony 2.6+ '@ security.token_storage' zapewnia metodę' getToken() 'zamiast' @ security.context' ... ale mógłbyś to sobie wyobrazić;) Jeśli moja odpowiedź dostarcza cennych informacji może rozważyć zaakceptowanie lub przynajmniej przejęcie go. – nifr

+1

Jestem nowy w symfony, więc nie mogłem sam tego zrozumieć. W każdym razie teraz działa! Dziękuję Ci bardzo! :) – rvaliev