Symfony2:如何通过考虑当前登录用户来验证实体?

时间:2016-03-28 15:08:38

标签: validation symfony

我正在使用User实体内的回调进行自定义验证。

因此我需要获取当前登录用户的User对象。

在控制器中,我可以这样做:

$user= $this->get('security.context')->getToken()->getUser();

但是我应该如何在User实体中进行呢?

1 个答案:

答案 0 :(得分:8)

如果要验证具有与外部依赖关系相关的任何逻辑的对象(在您的情况下是@security.context服务以获取当前用户)......您应该:

  • 创建自定义验证约束
  • 创建自定义验证程序服务以供约束
  • 使用
  • @security.context服务注入验证程序
  • 使用此新创建的验证约束来验证您的实体

解决方案在文档章节 Validators with Dependencies

中进行了描述

This video 说明为什么拥有以下RedBull验证器是绝对必要的。

型号/实体

use FamilyGuy\Validator\Constraints\Peter as PeterIsNotAllowedToOrder;

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

<强>配置

# 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"

<强>约束

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';
    }
}

<强>验证

// 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()
        ;
    }

您不能使用Callback约束来验证任何外部依赖关系。

请勿尝试将任何验证依赖直接注入您的域模型或实体。

验证逻辑通常应保留在实体之外。

注释已经是实体和symfony验证器之间的某种软耦合。这就是为什么建议将xml配置用于教义和验证映射的原因。