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

Why do Model Error messages not have public members?

Working on an API, and when a model save/create/update fails I'd like to output the reason why - and I intended to do this via outputting the error messages returned from $model->getMessages() if the save is not successful. I can't do this because none of the members are public. Is there a standard way to do this or do I have to manually build the error messages myself?

Shouldn't the properties of Phalcon\Mvc\Model\Message be public anyway?

fwiw, here's what I'm doing currently $errors = array_map(function($el){return $el->__toString();}, $model->getMessages());



93.7k
Accepted
answer

Hmmm, this should not be a problem at all? I have overwritten getMessages() in my base model in order to translate them to different languages.

    public function getMessages()
    {
        $messages = parent::getMessages();
        $translations = \Phalcon\DI::getDefault()->getTranslations()->public;

        $result = [];
        foreach ($messages as $item) {
            $type = strtolower($item->getType());
            $fieldName = $item->getField();
            $field = $fieldsTranslation->{$fieldName} ?? $fieldName;
            $validation = $translations->validation->{$type} ?? $type;
            $result[] = '<b>'. $field .'</b> '. $validation .'<br/>';
        }
        return $result;
    }

I've created an Exception helper for this:


use Phalcon\Mvc\ModelInterface;

class ModelSaveException extends Exception
{
    public function __construct(ModelInterface $model)
    {
        $message = '';
        foreach($model->getMessages() as $m) {
            $message.= $m->getField() . '(' . $m->getType() . '): ' . $m->getMessage() . PHP_EOL;
        }
        $name = (new \ReflectionClass($model))->getShortName();
        $message = trim($message);
        parent::__construct('Error while saving model '.$name.': '.PHP_EOL.$message);
    }
}
$robot = new Robot();
$robot->setField('value');
if(!$robot->save()) {
    throw new ModelSaveException($robot);
}

Why I like the ideas of both - I've just added a getMessages method to my base class with the code from my reply as it solves the problem as quickly and simply as possible. Thanks for the suggestions!

That's more KISS to me, so vote up for that solution.

Nice thing in OOP, if you need to resolve visibility w/o refactoring - you simply add facade method in base controller / class and declare it as public (actually you don't declare visibility and will revert to default public).

Why I like the ideas of both - I've just added a getMessages method to my base class with the code from my reply as it solves the problem as quickly and simply as possible. Thanks for the suggestions!