3

For example, how might we ensure that firstName is set.

3 Answers 3

4

At the time of writing the users.onBeforeSave event runs after validation, which means that we can’t add errors to the user easily.

The solution I’ve currently come up with is a plugin that adds custom validation rules to a user model, as well as a controller to handle the form submission.

Model

Firstly, I’ve extended the UserModel and added custom validation rules as needed.

<?php

namespace Craft;

class MyPlugin_UserModel extends UserModel
{
    protected function defineAttributes()
    {
        // Get the rules defined in UserModel
        $rules = parent::defineAttributes();

        // Add custom rules
        $rules['firstName'] = array(AttributeType::String, 'required' => true);
        $rules['lastName'] = array(AttributeType::String, 'required' => true);

        // If it’s a new user, require the password
        $isNewUser = !isset($this->id);
        if ($isNewUser) {
            $rules['password'] = array(AttributeType::String, 'required' => true);
        }

        return $rules;
    }
}

Controller

Secondly, I’ve created a controller action that will handle form submissions. This populates our custom user model with the input and runs the standard validate() flow.

<?php

namespace Craft;

class MyPlugin_UsersController extends BaseController
{
    protected $allowAnonymous = array('actionSaveUser');

    public function actionSaveUser()
    {
        $this->requirePostRequest();

        // Get input
        $post = craft()->request->getPost();

        // Create an instance of our model
        $user = new MyPlugin_UserModel($post);

        if (!$user->validate()) {
            // Add any errors from the validation to the user
            $user->addErrors($user->getContent()->getErrors());

            // Respond with errors
            if (craft()->request->isAjaxRequest()) {
                $this->returnJson(array(
                    'errors' => $user->getErrors(),
                ));
            } else {
                craft()->userSession->setError(Craft::t('Couldn’t save user.'));

                // Send the account back to the template
                craft()->urlManager->setRouteVariables(array(
                    'account' => $user
                ));
            }
        } else {
            // If all is well, run the default UsersController method
            craft()->runController('users/saveUser');
        }
    }
}

Template

For reference, here’s the action input in the template. Essentially, it’s just prepending the plugin handle before the default action.

<input type="hidden" name="action" value="myPlugin/users/saveUser">
3

In a plugin, you can use the onBeforeSaveUser event.

In your plugin's main file, use the following init function:

public function init(){
    //Tap into the onBeforeSaveUser event
    craft()->on('users.onBeforeSaveUser', function(Event $event) {

        //Get the user object from the raised event
        $user = $event->params['user'];

        //If the first name is blank, do not allow the save to continue
        if($user->firstName == '')
        {
            $event->performAction = false;
        }
    });
}
1
  • Thanks, @Aaron. That was my first port of call, however it doesn’t allow for validation (in a single request). Oct 14, 2015 at 14:15
2

I just ran into this issue myself. I have custom fields assigned to the user model in the dashboard that weren't being validated.

Marking those fields are required in the dashboard for the user model was all I had to do to ensure that they are required using the standard Craft saveUser controller. Depending on what your validation needs are this might work for you too.

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.