在Symfony中成功验证后应用正确的逻辑

在Symfony中成功验证后应用正确的逻辑,symfony,Symfony,首先,我专门为这个问题创建了下面的整个示例,因为实际示例非常大,所以如果它看起来很愚蠢,那么现在就假设它不是 我正试图想出一个解决方案,这样,如果验证成功通过,我就可以在controller中调用正确的私有方法(bankA()或bankB())。正如您在自定义验证约束中所看到的,我只检查$bank->code属性,但是条件实际上并不是那么简单(存在存储库检查等等)-(正如我前面所说,它是精简版本)。所以,请有人告诉我,在成功验证之后,我如何知道应该在控制器中调用哪个私有方法?如果有必要,我很乐意

首先,我专门为这个问题创建了下面的整个示例,因为实际示例非常大,所以如果它看起来很愚蠢,那么现在就假设它不是

我正试图想出一个解决方案,这样,如果验证成功通过,我就可以在controller中调用正确的私有方法(
bankA()
bankB()
)。正如您在自定义验证约束中所看到的,我只检查
$bank->code
属性,但是条件实际上并不是那么简单(存在存储库检查等等)-(正如我前面所说,它是精简版本)。所以,请有人告诉我,在成功验证之后,我如何知道应该在控制器中调用哪个私有方法?如果有必要,我很乐意创建专门的验证器,以便提供建议和示例

注意:我查阅了symfony group验证文档,但没有真正了解如何应用于我的场景

请求示例

  • {“id”:66,“code”:“A”}
  • {“id”:34,“code”:“B”}
控制器

use Symfony\Component\Validator\Validator\ValidatorInterface;

/**
 * @Route("bank", service="application_frontend.controller.bank")
 */
class BankController extends Controller
{
    private $validator;

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

    /**
     * @param Request $request
     *
     * @Route("")
     * @Method({"POST"})
     *
     * @throws Exception
     */
    public function indexAction(Request $request)
    {
        $content = $request->getContent();
        $content = json_decode($content, true);

        $bank = new Bank();
        $bank->id = $content['id'];
        $bank->code = $content['code'];

        $errors = $this->validator->validate($bank);
        if (count($errors)) {
            throw new Exception($errors[0]->getMessage());
        }

        // OK, validation has passed so which one do I call now ?!?!
        $this->bankA($bank);
        $this->bankB($bank);
    }

    private function bankA(Bank $bank)
    {
        // Do something nice with Bank
    }

    private function bankB(Bank $bank)
    {
        // Do something bad with Bank
    }
}
use Symfony\Component\Validator\Constraint;

/**
 * @Annotation
 */
class Bank extends Constraint
{
    public function getTargets()
    {
        return self::CLASS_CONSTRAINT;
    }

    public function validatedBy()
    {
        return get_class($this).'Validator';
    }
}

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;

class BankValidator extends ConstraintValidator
{
    public function validate($bank, Constraint $constraint)
    {
        if ($bank->code == 'A') {
            return;
        }

        if ($bank->code == 'B') {
            return;
        }

        $this->context->buildViolation('Bank error')->addViolation();
    }
}
银行模式

use Application\FrontendBundle\Validator\Constraint as BankAssert;

/**
 * @BankAssert\Bank
 */
class Bank
{
    /**
     * @var int
     */
    public $id;

    /**
     * @var string
     */
    public $code;
}
自定义验证程序

use Symfony\Component\Validator\Validator\ValidatorInterface;

/**
 * @Route("bank", service="application_frontend.controller.bank")
 */
class BankController extends Controller
{
    private $validator;

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

    /**
     * @param Request $request
     *
     * @Route("")
     * @Method({"POST"})
     *
     * @throws Exception
     */
    public function indexAction(Request $request)
    {
        $content = $request->getContent();
        $content = json_decode($content, true);

        $bank = new Bank();
        $bank->id = $content['id'];
        $bank->code = $content['code'];

        $errors = $this->validator->validate($bank);
        if (count($errors)) {
            throw new Exception($errors[0]->getMessage());
        }

        // OK, validation has passed so which one do I call now ?!?!
        $this->bankA($bank);
        $this->bankB($bank);
    }

    private function bankA(Bank $bank)
    {
        // Do something nice with Bank
    }

    private function bankB(Bank $bank)
    {
        // Do something bad with Bank
    }
}
use Symfony\Component\Validator\Constraint;

/**
 * @Annotation
 */
class Bank extends Constraint
{
    public function getTargets()
    {
        return self::CLASS_CONSTRAINT;
    }

    public function validatedBy()
    {
        return get_class($this).'Validator';
    }
}

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;

class BankValidator extends ConstraintValidator
{
    public function validate($bank, Constraint $constraint)
    {
        if ($bank->code == 'A') {
            return;
        }

        if ($bank->code == 'B') {
            return;
        }

        $this->context->buildViolation('Bank error')->addViolation();
    }
}

取决于有多少代码,你可以这样做

if ('A' === $bank->getCode()) {
    $this->bankA($bank);
} else {
    $this->bankB($bank);
}
或者

尽管如此,建议将所有这些工作转移到专用服务中,而不是控制器中。然后在控制器中使用类似于

$this->container->get('do_something_to_bank.service')->processAction($bank);

背后的逻辑是什么?如果代码是A,你会叫bankA;如果代码是B,你会叫bankB?这是对的吗?但是A和B只是演示的目的,所以我不只是在验证中检查它是A还是B。对于存储库和一些其他服务,
$bank->code
还有更多的检查。
$bank->code
可以是任何内容。我只是在方法名和请求负载中使用了A和B来简化代码,但显然我造成了误解,我只能怪我自己。总之,整个目标是知道在验证之后调用哪个方法。如果应用了X验证规则,则
bankA()
,如果使用了Y验证,则将在控制器中调用
bankB()
。另外,我实际上使用模型、工厂和服务来实现特定的逻辑,所以我并没有真正使用控制器来完成上面看到的所有代码。我只是想让它尽可能的整洁,足够公平。没有实际的代码,我发现很难对实际问题进行概念化。对不起,好吧,那就这么说吧。您想验证两次
$bank
模型。针对
BankStepOneValidator
执行一次,然后针对
BankStepTwoValidator
。这可能吗?另一个选项:我是否可以向验证器传递某种变量/参数,以便上面的
BankValidator
知道要运行哪个if语句?如果您只想执行步骤1,那么步骤2可以使用组和组序列。如果您只想验证它是否符合某些标准,那么我想您可以在第一个验证器中的对象中设置一个标志。老实说,我还是不知道你在找什么。