We have moved our forum to GitHub Discussions. For questions about Phalcon v3/v4/v5 you can visit here and for Phalcon v6 here.

Model uniqueness validation triggered after successful insert

I have a problem, my model uniquenss validation is triggered after a succesfull update so I get both the success flash message and error flash message. I use slightly modified code from vokuro and invo examples.

//MODEL

public function validation()
{
    $validator = new Validation();

    $validator->add('email', new Uniqueness([
        "message" => "The email is already registered"
    ]));

    $validator->add("username", new Uniqueness([
        "message" => "The username is taken, try a new one"
    ]));

    return $this->validate($validator);
}

/**
 * Initialize method for model.
 */
public function initialize()
{
    $this->setSource("users");
    $this->belongsTo('role_id', 'Models\Role', 'id', ['alias' => 'Role']);
}

//CONTROLLER    

/**
 * @Route("/register", methods={"GET", "POST"})
 */
public function registerAction()
{
    $form = new RegisterForm();

    if ($this->request->isPost()) {

        if ($form->isValid($this->request->getPost()) != false) {

            $user = new User([
                'name' => $this->request->getPost('name', 'striptags'),
                'email' => $this->request->getPost('email'),
                'password' => $this->security->hash($this->request->getPost('password')),
                'hash' => $this->security->getRandomBytes(),
                'role_id' => 5
            ]);

            $this->flash->setAutomaticHtml(true);

            if ($user->save()) {

                $this->flash->success('You have successfully registered');

                return $this->dispatcher->forward([
                    'controller' => 'auth',
                    'action' => 'register'
                ]);

            }

            $this->flash->error($user->getMessages());
        }
    }

    $this->view->form = $form;
}

//VIEW
    {{ form("class": "form-search") }}

  <div class="page-header">
      <h2>
          Sign Up
      </h2>
      </div>

    {{ content() }}
    {{ form.messages() }}

    <label>{{ form.label("name") }}</label>
    <div class="form-group {{ form.hasMessagesFor('name') ? 'has-error' : '' }}">
        {{ form.render("name") }}
    </div>

    <label>{{ form.label("username") }}</label>
    <div class="form-group {{ form.hasMessagesFor('username') ? 'has-error' : '' }}">
    <div class="input-group">
        <span class="input-group-addon"><i class="fa fa-user"></i></span>
        {{ form.render("username") }}
    </div>
    </div>

  <label>{{ form.label("email") }}</label>
  <div class="form-group {{ form.hasMessagesFor('email') ? 'has-error' : '' }}">
      <div class="input-group">
          <span class="input-group-addon">@</span>
          {{ form.render("email") }}
      </div>
  </div>

  <label>{{ form.label("password") }}</label>
  <div class="form-group {{ form.hasMessagesFor('password') ? 'has-error' : '' }}">
      {{ form.render("password") }}
  </div>

  <label>{{ form.label("confirmPassword") }}</label>
  <div class="form-group {{ form.hasMessagesFor('confirmPassword') ? 'has-error' : '' }}">
      {{ form.render("confirmPassword") }}
  </div>

  <label>
      {{ form.render("terms") }} {{ form.label("terms") }}
  </label>

  <div class="form-group">
      {{ form.render("Sign Up") }}
  </div>

  {{ form.render("csrf", ["value": security.getToken()]) }}
  {{ form.messageFor("csrf") }}

  <hr>

  {{ endForm() }}


432
Accepted
answer

Figured it out, when you use the same controller action for both the POST and GET http requests and if you dispatcher->forward to the same controller action after successfull entry the dispatcher will trigger both methods somehow, and thus the model will try to create the same user with the same data again