D
D
Dmitry2014-07-10 12:11:49
Yii
Dmitry, 2014-07-10 12:11:49

Yii2 behaviors. How to stop the process of saving a model from a behavior?

There is an Event model, a behavior has been created for it that saves data from another model (EventAttribute).
If you do so

public function beforeSave($insert) {
       parent::beforeSave($insert);              
       
        if(!$this->saveEavAttributes()){
            return false;
        }
        return true;
}

and the $this->saveEavAttributes() method returns FALSE, it takes me back to the add (edit) page and displays the errors.
But if you do it through the behavior method, so
public function events() {
        return [
            \yii\db\ActiveRecord::EVENT_BEFORE_INSERT => 'saveEavAttributes',
            \yii\db\ActiveRecord::EVENT_BEFORE_UPDATE => 'saveEavAttributes',
        ];
    }

then everything is processed as if everything is successful, erroneous attributes are simply not saved.
Question: How can this be fixed?

Answer the question

In order to leave comments, you need to log in

4 answer(s)
A
Alexander Zelenin, 2014-07-10
@zelenin

if you have reached beforeSave, then there should be no validation errors, and therefore all errors in saveEavAttributes

D
Dmitry, 2014-07-11
@drwhite87

And there is

public function saveEavAttributes() {
        $noError = TRUE;
        if (count($this->attributes > 0)) {
            foreach ($this->attributes as $attribute) {
                $attributeModel = $this->getAttributeModel($attribute);

                if (empty($attribute->value)) {
                    if ($attribute->required) {
                        $attribute->addError($this->alias, Yii::t('yii', '{attribute} cannot be blank.', ['attribute' => $attribute->name]));
                        return FALSE;
                    } else {
                        $attributeModel->delete();
                        return;
                    }
                }

                $attributeModel->event_id = $this->owner->id;
                $attributeModel->attribute_id = $attribute->id;
                $attributeModel->value = $this->owner->eavAttributes->{$attribute->alias}->value;
                if (!$attributeModel->save()) {
                    $attribute->addError($attribute->alias, str_replace('Value', $attribute->name, $attributeModel->errors['value'][0]));
                    $noError = FALSE;
                }
            }
        }

        return $noError;
    }

And then I display errors in the view with the help of a widget by standard means (an attribute model of the corresponding type comes to the view).
<div class="form-group field-event-<?= $model->alias ?>">
    <?= \yii\helpers\Html::label($model->name)?>
    <?= \yii\helpers\Html::input('text', $attribute, $model->value, ['class' => 'form-control'])?>
    <div class="has-error"><div class="help-block"><?= \yii\helpers\Html::error($model, $model->alias)?></div></div>
</div>

How can I stop the request with an error?

L
lithium_li, 2016-01-19
@lithium_li

When calling a method attached to an event in Behavior::events() , an event object is passed to the method argument:

public function beforeSave($event)
{
     $event->isValid = $this->saveEavAttributes();
}

The value returned by beforeSave() is ignored by yii, so there is no point in returning one of these methods in behavior.

Y
Yuri Kondratiev, 2017-09-14
@Joorich

Instead of returning false, throw an exception, catch it outside and handle it :)

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question