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 %}
  • What to use if no route is specified? how can I redirect back with error messages? – Volatil3 Oct 21 '15 at 12:59
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 %}
  • How would I call that in a template? {{ errors.name }} does not seem to work using $model->getErrors(). – Jason McCallister Nov 22 '14 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. – Brandon Kelly Nov 22 '14 at 20:40
  • Thanks Brandon, I updated brads answer to reflect that but it requires peer review to update. – Jason McCallister Nov 22 '14 at 20:57
  • Approved (with minor tweaks) – Lindsey D Nov 22 '14 at 21:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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