【问题标题】:Yii2: validation errors that are not attribute specificYii2:非特定属性的验证错误
【发布时间】:2018-07-12 07:16:48
【问题描述】:

如何处理 Yii2 ActiveRecord 模型中与特定属性无关的通用验证错误?例如,当相关记录/模式设置为非活动状态时,我需要完全禁止保存模型。

我当然可以选择一个或多或少的随机属性并将错误消息分配给它,但是如果前端表单没有该属性并因此不显示错误怎么办?或者更糟糕的是,如果稍后某个场景禁用了该属性的验证(通过不将其包含在活动属性列表中)?

我当然可以在beforeSave()beforeValidate() 中返回false,但是我没有选项可以向用户指定为什么无法保存模型的消息,所以我真的不喜欢这个想法。

另外,我不想抛出异常,它应该只是向用户显示的软错误消息。

处理此问题的预期/最佳方法是什么?

【问题讨论】:

  • 如果它帮助您解决问题,请选择答案
  • 如果他们没有帮助怎么办?放轻松,伙计...
  • 好吧,写起来需要一分钟它对我没有用,因为...也许它可以解决,如果其他人可以抽出时间,你可以做那么多给你写一个答案,反正留下吧。

标签: php validation activerecord model yii2


【解决方案1】:

您是否查看过flash data,它们可用于显示successerrorswarnings不是 的消息> 特定于您的模型属性。由您决定在哪里使用它们。

我主要在 transaction 块中插入数据或保存模型,当我保存多个模型时,我使用 try catch 块来获取发生的任何模型的错误,并使用会话闪存和 ArrayHelper 在其中添加错误闪现消息。

为了您的目的,您可以按以下方式使用它。

设置 flash 消息
Yii::$app->session->setFlash('error','you are not allowed to perform this message');

您可以在视图中使用以下内容获取它

if(Yii::$app->session->hasFlash('error')){

echo Yii::$app->session->gettFlash('error');

}

一个更复杂的方法是\kartik\widgets\AlertBlock

使用作曲家安装它

php composer.phar require kartik-v/yii2-widget-alert "*"

然后使用以下代码在layouts文件夹中创建一个名为alerts.php的文件

use kartik\widgets\AlertBlock;

AlertBlock::widget (
        [
            'useSessionFlash' => false ,
            'type' => AlertBlock::TYPE_GROWL ,
            'alertSettings' => [
                'settings' => [
                    'type' => kartik\widgets\Growl::TYPE_SUCCESS ,
                    'icon' => 'glyphicon glyphicon-ok-sign' ,
                    'title' => 'Note' ,
                    'showSeparator' => true ,
                    'body' => Yii::$app->session->getFlash ( 'success' )
                ] ,
            ]
] );

AlertBlock::widget (
        [
            'useSessionFlash' => false ,
            'type' => AlertBlock::TYPE_GROWL ,
            'alertSettings' => [
                'settings' => [
                    'type' => kartik\widgets\Growl::TYPE_INFO ,
                    'icon' => 'glyphicon glyphicon-ok-sign' ,
                    'title' => 'Note' ,
                    'showSeparator' => true ,
                    'body' => Yii::$app->session->getFlash ( 'info' )
                ] ,
            ]
] );


AlertBlock::widget (
        [
            'useSessionFlash' => false ,
            'type' => AlertBlock::TYPE_GROWL ,
            'alertSettings' => [
                'settings' => [
                    'type' => kartik\widgets\Growl::TYPE_DANGER ,
                    'icon' => 'glyphicon glyphicon-ok-sign' ,
                    'title' => 'Note' ,
                    'showSeparator' => true ,
                    'body' => Yii::$app->session->getFlash ( 'error' )
                ] ,
            ]
] );


AlertBlock::widget (
        [
            'useSessionFlash' => false ,
            'type' => AlertBlock::TYPE_GROWL ,
            'alertSettings' => [
                'settings' => [
                    'type' => kartik\widgets\Growl::TYPE_DANGER ,
                    'icon' => 'glyphicon glyphicon-ok-sign' ,
                    'title' => 'Note' ,
                    'showSeparator' => true ,
                    'body' => Yii::$app->session->getFlash ( 'danger' )
                ] ,
            ]
] );


AlertBlock::widget (
        [
            'useSessionFlash' => false ,
            'type' => AlertBlock::TYPE_GROWL ,
            'alertSettings' => [
                'settings' => [
                    'type' => kartik\widgets\Growl::TYPE_WARNING ,
                    'icon' => 'glyphicon glyphicon-ok-sign' ,
                    'title' => 'Note' ,
                    'showSeparator' => true ,
                    'body' => Yii::$app->session->getFlash ( 'warning' )
                ] ,
            ]
] );

然后在$this->beginBody() 调用后将其包含在您的布局文件中,如下所示

<?= Yii::$app->view->renderFile ( '@frontend/views/layouts/alerts.php' ); ?>

那么您只需设置 Flash 消息,您甚至不必调用 getFlash(),扩展程序会自动显示它,您有以下可用变量

  • 成功
  • 信息
  • 危险
  • 警告
  • 错误

使用Yii::$app-&gt;session-&gt;setFlash('danger','You cannot do this');设置

编辑:

注意:每当您在设置 flash 消息后进行重定向时,请记住使用 returnredirect(),否则您可能会遇到消息未显示的问题。

return $this->redirect(['index']);

编辑 2:

您正在尝试为与当前保存的模型相关的任何特定模型添加错误消息,并且您想要一些允许您抛出异常并以格式良好的错误消息显示它们的灵魂,所以您的问题面临的是设置错误消息,如果我会这样做,我会使用以下方法。假设我有一个actionTest(),如下所示,它正在保存提交时的表单。

public function actionTest() {

    $model = new Campaign();

    if ($model->load(Yii::$app->request->post())) {

        //start transaction block
        $transaction = Yii::$app->db->beginTransaction();

        try {
            if (!$model->save()) {
                //throw an exception if any errors
                throw new \Exception(implode("<br />",\yii\helpers\ArrayHelper::getColumn($model->errors, 0,false)));
            }
            //commit the transaction if there arent any erorrs to save the record
            $transaction->commit();

        } catch (\Exception $ex) {

            //roll back the transaction if any exception
            $transaction->rollBack();

            //catch the error and display with session flash
            Yii::$app->session->setFlash('danger',$ex->getMessage());
        }
    }
    $this->render('test');
}

【讨论】:

  • 这主要是关于如何显示消息,而不是如何从模型返回错误消息。如果它是 API 的一部分,它也不会起作用。作为调用save() 方法的结果,人们想要返回一条消息。
  • 确实如此!问题是您没有添加任何源代码来说明您正在寻找什么用户关于与您的model-&gt;save() 触发器相关的错误,如果它由于任何其他约束或任何其他相关模型而拒绝更新,我将添加一个 try catch 块并将其包装在transaction 块中,如果@987654350 则抛出异常@ 为 false 并使用 msg 捕获并显示异常。 @TheStoryCoder
【解决方案2】:

然后选择随机属性的另一个选项是抛出带有特定错误代码的异常。使用错误代码常量及其消息创建最终类。然后将您的保存函数调用放在 try Catch 块中并捕获所有特定异常并将消息返回到前端

【讨论】:

  • 我不太明白...你能写一个简短的例子吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-15
  • 2012-12-03
  • 2011-02-11
  • 2012-04-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多