I'm doing a custom validation using callback inside the User entity.
Therefore I need to get the User object of the currently logged user.
In controller I can do it like this:
$user= $this->get('security.context')->getToken()->getUser();
But how should I do it inside the User entity?
If you want to validate an object with any logic related to an external dependency (in your case the @security.context
service to get the current user) ... you should:
@security.context
service into the validatorThe solution is described in the documentation chapter Validators with Dependencies
This video shows why it's absolutely necessary to have the following RedBull validator.
Model/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"
Constraint
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()
;
}
You can't and you shouldn't use the Callback
constraint to validate against any external dependency.
Don't try to inject any validation dependency into your domain model or entities directly.
Validation logic should be kept out of entities in general.
Annotations are already some sort of soft-coupling between entities and the symfony validator. That's why it's recommended to use xml configuration for doctrine- and validation-mappings usually.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With