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

How can I use "Validation\Validator" without using "Forms\Form" right?

Phalcon is very good framework (in my opinion). I'm a beginner in working with frameworks. Phalcon's documentation is well and I've found answers on many questions just reading instructions and examples on the official website and github. A lot of examples of Validation has showed how to make validation by using Forms (or Models). I want create forms in Volt without Forms like this:

<h2>Sign up using this form</h2>

<div id="messages">{{ flash.output() }}</div>

{{ form("registration", "method":"post") }}

<p>
    <label for="username">Name</label>
    {{ text_field("username", "size": 32) }}
</p>
<p>
    <label for="password">Password</label>
    {{ text_field("password", "type": "password", "size": 32, "maxsize": 100) }}
</p>
<p>
    {{ submit_button("Register") }}
</p>

{{ end_form() }}

First, I created "RegistrationValidation.php":

<?php

use Phalcon\Validation;
use Phalcon\Validation\Validator\Regex;
use Phalcon\Validation\Validator\StringLength;

class RegistrationValidation extends Validation
{
    public function initialize()
    {
        $this
        ->add('name', new Regex([
            'message'    => 'The name is required',
            'pattern'    => '/\+44 [0-9]+/',
            'allowEmpty' => true
        ]))
        ->add('name', new StringLength([
            'messageMinimum' => 'The name is too short',
            'min'            => 2
        ]));
        $this->setFilters('username', 'trim');
        $this->setFilters('password', 'trim');
    }

    public function getMessages()
    {
        $messages = [];
        foreach (parent::getMessages() as $message) {
            switch ($message->getType()) {
                case 'PresenceOf':
                    $messages[] = 'Заполнение поля ' . $message->getField() . ' обязательно';
                break;
            }
        }
        return $messages;
    }
}

but what should I do next?

How can I flash messages from getMessages function (RegistrationValidation.php) in view and add validator in RegistrationController?

Or how can I create it in the RegistrationController, also flash messages in view and validate POST? I think, that shioud be done like this (by creating a function in the RegistrationController):

<?php

// ...

public function validate() {
    // ...
}

// ...

but what's next? All attempts to find the right way brought me to a standstill. Help me please! Thanks a lot!



9.3k
Accepted
answer
edited Apr '16

Something like this should work

class MyController extends \Phalcon\Mvc\Controller
{

    public function registerAction()
    {
        $validation = new RegistrationValidation();
        $messages = $validation->validate($this->request->getPost());

        if (empty($messages)) {
            // ... OK
        } else {
            // ... ERROR
            foreach ($messages as $message) {
                $this->flashSession->error($message->getMessage());
            }
        }
    }

}


11.1k

Thanks! You helped me very much:)



11.1k
edited Apr '16

Hello again. Please can you help me again? How can I do validation using models? Without forms, like this:

<?php
// /app/models/Users.php

use Phalcon\Mvc\Model;
use Phalcon\Validation;
use Phalcon\Validation\Validator\Regex;
use Phalcon\Validation\Validator\StringLength;
use Phalcon\Validation\Validator\Uniqueness;

class Users extends Model
{
    public $id;

    public $username;

    public $password;

    public function validation()
    {
        $validator = new Validation();
        $validator->add('username', new Uniqueness([
            'message'      => 'Sorry, this username already taken. Choose another please!'
        ]));
        $validator->setFilters('username', 'trim');

        return $this->validate();
    }
}

P.S. The validation() function in this model (in /app/models/Users.php) return this error:

Exception: Wrong number of parameters
#0 C:\OpenServer\domains\phalcon.test\tutorial\app\models\Users.php(36): Phalcon\Mvc\Model->validate()
#1 [internal function]: Users->validation()
#2 [internal function]: Phalcon\Mvc\Model->fireEventCancel('validation')
#3 [internal function]: Phalcon\Mvc\Model->_preSave(Object(Phalcon\Mvc\Model\MetaData\Memory), false, false)
#4 C:\OpenServer\domains\phalcon.test\tutorial\app\controllers\AccountController.php(34): Phalcon\Mvc\Model->save()
#5 [internal function]: AccountController->createAction()
#6 [internal function]: Phalcon\Dispatcher->callActionMethod(Object(AccountController), 'createAction', Array)
#7 [internal function]: Phalcon\Dispatcher->_dispatch()
#8 [internal function]: Phalcon\Dispatcher->dispatch()
#9 C:\OpenServer\domains\phalcon.test\tutorial\public\index.php(100): Phalcon\Mvc\Application->handle()
#10 {main}

And this is my Controller - RegistrationController.php

<?php
// /app/controller/RegistrationController.php

use Phalcon\Mvc\Controller;

class RegistrationController extends Controller
{
    public function indexAction()
    {
        if ($this->request->isPost()) {
            if ($this->security->checkToken()) {

                $username = $this->request->getPost('username', ['string', 'striptags']);
                $password = $this->request->getPost('password');

                $user = new Users();
                $user->username = $username;
                $user->password = $this->security->hash($password);
                if ($user->save()) {
                    // I don't know what I'll should write here.
                } else {
                    // I don't know what I'll should write here too...
                }
            }
        }
    }
}

How can I transfer the data in the Controller and flash the validation messages in the View?

edited Apr '16

Validation this way

    /**
     * Performs data validation
     * @return  bool
     */
    public function validation()
    {
        $validation = new Validation();

        $validation->add(
            'id', new PresenceOf([
                'message' => 'ID is required'
            ])
        );

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

FlashMessages this way

if ($user->save()) {
    // I don't know what I'll should write here.
} else {
    $messages = $user->getMessages();
    foreach ($messages as $message) {
        $this->flashSession->error($message->getMessage());
    }
}

This works in version 2.1 for me.



11.1k
edited Apr '16

Thank you! Now I think it's obvious decision. Your variant (example) of using PresenceOf works perfectly!

But I have some problems with Uniqueness validator (only with it).

This is the part of my model:

<?php

use Phalcon\Mvc\Model;
use Phalcon\Validation;
use Phalcon\Validation\Validator\Uniqueness;

class Users extends Model
{
    public $username;

    public $password;

    public function validation()
    {
        $validation = new Validation();
        $validation->add('username', new Uniqueness([
            'model'   => $this,
            'message' => 'Sorry, this :field already taken.'
        ]));

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

And this is the part of my controller which responsibles for saving data to the DB:

<?php

// ...

if ($user->save()) {
    return '<h1>Good!</h1>';
} else {
    return '<h1>Bad!</h1>';
}

// ...

All other validators (Regex, StringLength) works right, in construct of Uniqueness (probably because it works with the db). This variant should works right too, but it always returns "Good!". Sometimes I can see an error, which reports about trying to duplicate an unique field in the database.

Exception: SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry 'MyUsername' for key 'PRIMARY'

How can this problem be solved? Did I do something wrong? I can't find the right solution. Help me, please. Tanks alot for your help, David!

edited Apr '16

This works for me in 2.1

// email has to be unique
$validation->add(
    'email', new Uniqueness([
        'model' => $this,
        'message' => 'Email already taken'
    ])
);


11.1k

Thank you:) My problem was in the added PRIMARY KEY to the username field (in the DataBase).