5

I'm working on validation with Craft. I have a custom plugin that allows public submission. However, I want to make sure I can pass errors back to the template. The key is trying to make my code as "dynamic" as possible. Meaning I do not want to specify the errors one by one.

Here is my sample controller (keep in mind I don't care what the model says is required, trying to keep the code agnostic of the model.)

public function actionSave() {

    // require a post request
    $this->requirePostRequest();

    // assign specific fields we are listening for
    $post = craft()->request->getPost('fields');

    // create a new Request model
    $model = MyModel::populateModel($post);

    // validate the model attributes
    if ($model->validate()) {
        // save the record

        // redirect to posted url
    }

    $errors = $model->getAllErrors();

    craft()->urlManager->setRouteVariables(array(
        'errors'    => $errors
    ));

}

Using $model->getAllErrors() returns an array as listed below:

array
(
    0 => 'Name cannot be blank.'
    1 => 'Details cannot be blank.'
    2 => 'Email is not a valid email address.'
)

How would I return that array to specific fields in my template like so:

{% if errors.email is defined ? errors.email | length %}
    <div data-alert class="alert">
        {{ errors.email }}
    </div>
{% endif %}
1
  • What to use if no route is specified? how can I redirect back with error messages?
    – Volatil3
    Oct 21, 2015 at 12:59

1 Answer 1

5

If you use $model->getErrors() instead, it should return a multidimensional array of errors indexed by attribute name like so:

array(
    'email' => array(
        'First email error.',
        'Second email error.',
    ),
    'firstName' => array(
        'First firstName error.',
    ),
);

Or you can get errors specifically for an attribute like so:

$model->getErrors('email');

Then update the template to check for the errors, since it is now a multidimensional array that's returned.

{% if errors.email is defined ? errors.email | length %}
<div data-alert class="alert">
    {% for error in errors.email %}
        {{ error }}
    {% endfor %}
</div>
{% endif %}
4
  • How would I call that in a template? {{ errors.name }} does not seem to work using $model->getErrors(). Nov 22, 2014 at 18:53
  • @JasonMcCallister If there were any errors on the name attribute, then errors.name will be an array of all of those errors. Nov 22, 2014 at 20:40
  • Thanks Brandon, I updated brads answer to reflect that but it requires peer review to update. Nov 22, 2014 at 20:57
  • Approved (with minor tweaks)
    – Lindsey D
    Nov 22, 2014 at 21:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.