Search code examples
phprestvalidationphalconphalcon-orm

What is the best way to return validation messages with Phalcon PHP as json


I'm creating REST API, and I want to return messages from validation.

Here is example with user register:

class Users extends Phalcon\Mvc\Model {
    public function validation() {
        $validator = new Validation();

        $validator->add('email', new PresenceOf([
                    'message' => 'The email is required'
        ]));
        $validator->add('email', new Email([
                    'message' => 'Invalid email given'
        ]));
        $validator->add('email', new Uniqueness([
                    'message' => 'Sorry, The email was registered by another user'
        ]));
        return $this->validate($validator);
}

Here is my current code:

class UserController extends Phalcon\Mvc\Controller {
    public function register() {
        $data = $this->request->getJsonRawBody();
        $user = new Users();
        $user->setEmail($data->email)->setUsername($data->username)->setPassword($data->password);
        if ($user->save() === false) {
            $data = [];
            $messages = $user->getMessages();
            foreach ($messages as $message) {
                $data[] = array(
                    'field' => $message->getField(),
                    'type' => $message->getType(),
                    'message' => $message->getMessage()
                );
            }
            return $this->response->setStatusCode(409, 'Conflict')->setJsonContent(array('error' => $data));
        }
        return $this->response->setStatusCode(201, 'Created')->setJsonContent(array('message' => "User id:" . $user->getId() . " created"));
}

When I change this for loop with something like that I get empty response:

return $this->response->setStatusCode(409, 'Conflict')->setJsonContent(array('error' => $user->getMessages()));

The question is it possible make this code shorter without loop trough messages, but just simple return json object.


Solution

  • You can do it with very little modifications by extending default methods. Here is a working sample of your code:

    // BaseModel class which overwrites default Phalcon methods if needed.
    class BaseModel extends \Phalcon\Mvc\Model
    { 
        public function getMessagesNormalized()
        {
            $messages = parent::getMessages();
            $data = [];
            foreach ($messages as $message) {
                $data[] = array(
                    'field' => $message->getField(),
                    'type' => $message->getType(),
                    'message' => $message->getMessage()
                );
            }
            return $data;
        }
    }
    
    // Note that your models from now on extend BaseModel which extends \Phalcon\Mvc\Model
    class Users extends BaseModel {
        // ...
    }
    
    // Your controller
    class UserController extends Phalcon\Mvc\Controller {
        public function register() {
            $data = $this->request->getJsonRawBody();
            $user = new Users();
            $user->setEmail($data->email)->setUsername($data->username)->setPassword($data->password);
            if ($user->save() === false) {
                $data = [];
                // Get the messages in RESTsuitable format
                $messages = $user->getMessagesNormalized();
                return $this->response->setStatusCode(409, 'Conflict')->setJsonContent(array('error' => $data));
            }
            return $this->response->setStatusCode(201, 'Created')->setJsonContent(array('message' => "User id:" . $user->getId() . " created"));
    }