Search code examples
symfonyfosuserbundle

How to create a new FOSUserBundle user programatically using the same validation as on web form?


I am running a Symfony 2.8 based web app using FOSUserBundle to manage users. Creating new users with a web form is absolutely no problem.

Now I would like to add a feature to create new users with a REST api. Of course submitting username, password, email, etc. to a controller is no big deal:

public function registerAction(Request $request) {    
    $requestJson = json_decode($request->getContent(), true); 

    $username = $requestJson[JSON_KEY_USERNAME];
    $email    = $requestJson[JSON_KEY_MAIL];
    $password = $requestJson[JSON_KEY_PASSWORD];
    ...

    $this->registerUser($username, $email, $password);

    ...
}

private function registerUser($username, $email, $password, $locale, $timezone, $currency) {
    $userManager = $this->get('fos_user.user_manager');

    $emailExist = $userManager->findUserByEmail($email);
    $userNameExists = $userManager->findUserByUsername($username);

    if ($emailExist || $userNameExists)
        return false;

    $user = $userManager->createUser();

    $user->setUsername($username);
    $user->setEmail($email);
    $user->setPlainPassword($password);
    ...

    $user->setLocked(0); 
    $user->setEnabled(0); 

    $userManager->updateUser($user);

    return true;
}

However, this performs no validation at all. If for example the username is empty an NotNullConstraintViolationException is thrown when persisting the user object.

Of course I could manually re-implement the same validation process which is used by the RegistrationForm (username not empty, not taken, no invalid characters, password min length, e-mail format, etc.) and pass back the same error messages but this would mean to reinvent the wheel.

Is it somehow possible to run the exact same validation which is used by the RegistrationForm?


Solution

  • Symfony validator can work independently. In a controller you can use validator service like this:

    $violations = $this->get('validator')->validate($user, null, ['your_groups_here']);
    // Or inject Symfony\Component\Validator\Validator\ValidatorInterface into a service.
    

    It will return a ConstraintViolationListInterface, you can loop trough this object.

    You can check FOSUserBundle validation groups here: https://github.com/FriendsOfSymfony/FOSUserBundle/blob/master/Resources/config/validation.xml