在beforeSave()和halt save()调用上,从CakePHP 3.8模型返回自定义422实体错误的正确方法是什么?

在beforeSave()和halt save()调用上,从CakePHP 3.8模型返回自定义422实体错误的正确方法是什么?,php,cakephp,cakephp-3.0,Php,Cakephp,Cakephp 3.0,我目前正在致力于将422个http验证错误添加到基于Cake 3.8的API中 对于任务控制器,我有如下内容: <?php class TasksController extends AppController { public function initialize() { parent::initialize(); } public function add(string $id): void { $valid

我目前正在致力于将422个http验证错误添加到基于Cake 3.8的API中

对于任务控制器,我有如下内容:

<?php

class TasksController extends AppController
{
    public function initialize()
    {
        parent::initialize();
    }

    public function add(string $id): void
    {
        $validationErrors = [];

        $task = $this->newEntity($this->request->getData(););

        if ($this->Tasks->save($task)) {
            // Errors added to entity in before save will not cause
            // save() to return false and stop the proccess from
            // making it here
            $this->response = $this->response->withStatus(200);
        } else {
            $validationErrors = [$task->getErrors()];
            if (count($validationErrors) > 0) {
                $this->response = $this->response->withStatus(422);
            } else {
                throw new BadRequestException("The posted entity is is invalid.");
            }
        }

        // Render json output for success / errors
        $this->set($this->createViewVars(['entity' => $task], $validationErrors));
    }
}
<?php

class TasksTable extends AppTable
{
    public function initialize(array $config)
    {
        parent::initialize($config);
    }

    public function beforeSave(Event $event, Entity $task, ArrayObject $options)
    {
        parent::beforeSave($event, $task, $options);

        $task->setError('technician', 'No default technician was able to be found');

        if(count($task->getErrors()) > 0) {
            $event->stopPropagation();
        }

    }
}

beforemashall
似乎不是这样做的地方。是否有某些原因导致它无法进入正常验证(在修补实体时发生)或规则(在保存之前发生)?这两个都是为这类事情而设计的。此外,您不需要停止事件的传播;如果实体中有任何错误,则不会执行保存。@GregSchmidt查看代码时,如果需要的话,我可能会将beforemashall中的内容转换为beforeSave?这种逻辑基本上是通过站点设置进行梳理,并根据系统中的设置自动填充某些字段,因此它不是验证代码,它只是在预填充过程中揭示验证问题。有时,这些值可能来自最终用户,在这种情况下,该逻辑甚至不会运行。我想我们可以将字段留空,让它们落在验证系统上,以防没有任何内容需要预填充?我删除了问题的BeforeMarshall部分,因为它可以解决。我认为最“蛋糕式”的方法可能是使用
beforeSave
来填充字段,然后让规则检查这些值是否有效。@GregSchmidt这当然是一个选项,但如果禁用了
checkRules
,则不会触发该事件。我想说,您的第一直觉是,数据操作应该在marshall()之前进入
,这是正确的,至少就请求数据而言是正确的。进一步操作有效实体和手动中止保存过程应进入
beforeSave()
。我不确定显示的代码有什么问题,即使它不会导致返回
false
,但返回
null
(使用
$event->setResult(false)
return false
),它仍然应该中止保存过程并进入
else
分支。