TheStoryCoder
TheStoryCoder

Reputation: 3640

Yii2: Can I create rules and custom error messages that apply when DELETING a model?

I want to delete a model but it might have related records in another model when will prohibit me doing so. How can I best use the already defined relationships to check if delete will be successful? Potentially there could also be non-relationship reasons for not allowing a delete.

Once I have determined my error messages how can I best store them and pass them on to the front-end? beforeDelete() only returns true or false but I of course need to provide user with friendly error messages saying WHY the record can't be deleted...

Relationship already defined is for example:

public function getPhonenumbers() {
    return $this->hasMany(Phonenumber::class, ['ph_contactID' => 'contactID']);
}

Upvotes: 1

Views: 975

Answers (2)

rob006
rob006

Reputation: 22174

You can throw exception in beforeDelete() with error message, and catch it in controller.

public function beforeDelete() {
    if ($this->getPhonenumbers()->exist()) {
        throw new DeleteFailException('Records with phone numbers cannot be deleted.');
    }

    return parent::beforeDelete();
}

And in controller action:

try {
    $model->delete();
} catch (DeleteFailException $esception) {
    Yii::$app->session->setFlash('error', $exception->getMessage());
}

Upvotes: 1

TheStoryCoder
TheStoryCoder

Reputation: 3640

From the answers of @vishuB and @rob006 I got ideas for coming up with my own solution which I think will be superior as I can provide multiple error messages, it can be used in an API as well, and it doesn't rely on try/catching exceptions:

public function beforeDelete() {
    if (!parent::beforeDelete()) {
        $this->addError('contactID', 'For some unknown reason we could not delete this record.');
    }

    if (!empty($this->phonenumbers)) {
        $this->addError('contactID', 'Contact is linked to a used phone number and cannot be deleted.');
    }

    if ($some_other_validation_fails) {
        $this->addError('contactID', 'Contact cannot be deleted because it is more than two months old.');
    }

    return ($this->hasErrors() ? false : true);
}

Then in my action I do this:

$contact = Contact::findOne($contactID);
if (!$contact->delete()) {
    return $contact->getErrors();  //or use flash messages and redirect to page if you prefer
}
return true;

Upvotes: 1

Related Questions