laravel-ardent / ardent

Self-validating, secure and smart models for Laravel's Eloquent ORM
BSD 3-Clause "New" or "Revised" License
1.39k stars 211 forks source link

$this->errors() is empty, but not $this->validationErrors #274

Open simplenotezy opened 9 years ago

simplenotezy commented 9 years ago

I am trying to figure out why ->errors() is empty, while calling -> validationErrors directly, is not.

I am extending the validate() method on my User model.

This is how it looks. I have added some comments around $this->validationErrors = $validator->messages(); to explain the error.

class User {
    public function validate(array $rules = array(), array $customMessages = array()) {
        if ($this->fireModelEvent('validating') === false) {
            if ($this->throwOnValidation) {
                throw new InvalidModelException($this);
            } else {
                return false;
            }
        }

        // check for overrides, then remove any empty rules
        $rules = (empty($rules))? static::$rules : $rules;

        // make sure primary key is validated
        if (!isset($rules[$this->primaryKey])) {
            $rules[$this->primaryKey] = 'unique:'.$this->table;
        }

        foreach ($rules as $field => $rls) {

            // check if unique fields have been modified or not, if not, exclude them from validation
            $uPos = strpos($rls, 'unique');

            if ($uPos !== false) {
                // didnt change
                if ($this->$field == $this->getOriginal($field)) {
                    // remove the unique rule as field didnt change
                    $uEPos = strpos($rls, '|', $uPos);
                    $uEPos = $uEPos ? $uEPos : strlen($rls);
                    $rules[$field] = substr($rls, 0, $uPos) . substr($rls, $uEPos);
                }
            }

            if ($rls == '') {
                unset($rules[$field]);
            }
        }

          if (empty($rules)) {
                $success = true;
            } else {
                $customMessages = (empty($customMessages))? static::$customMessages : $customMessages;

                if ($this->forceEntityHydrationFromInput || (empty($this->attributes) && $this->autoHydrateEntityFromInput)) {
                    $this->fill(Input::all());
                }

                $data = $this->getAttributes(); // the data under validation

                // perform validation
                $validator = static::makeValidator($data, $rules, $customMessages);
                $success   = $validator->passes();

                if ($success) {
                    // if the model is valid, unset old errors
                    if ($this->validationErrors->count() > 0) {
                        $this->validationErrors = new MessageBag;
                    }
                } else {
                    // otherwise set the new ones
                    $this->validationErrors = $validator->messages();

                    // if validation failed, $this->validationErrors will have the correct errors
                    // however, if I call $this->errors(), which should do the exact same thing, I get an empty MessageBag

                    // conclusion:
                    // $this->validationErrors -> works
                    // $this->errors() -> empty

                    // stash the input to the current session
                    if (!self::$externalValidator && Input::hasSession()) {
                        Input::flash();
                    }
                }
            }

            $this->fireModelEvent('validated', false);

            if (!$success && $this->throwOnValidation) {
                throw new InvalidModelException($this);
            }

            return $success;
    }
}

In my UserController.php, where I experience the issue, this is how it looks:

<?php

class UserController extends \Dingo\Api\Routing\Controller {

    /**
     * Constructor
     * @param Item $item [description]
     */

    public function __construct(User $user) {
        $this->user = $user;
    }
    /**
     * Update the specified resource in storage.
     * PUT /users/{id}
     *
     * @param  int  $id
     * @return Response
     */
    public function update($id = null)
    {

        $this->user->fill(Input::all());

        /**
         * Fill and check if valid
         */

            if(!$this->user->validate()) {
                // $this->user->errors() will be empty
                // $this->user->validationErrors will NOT be empty

                throw new Dingo\Api\Exception\UpdateResourceFailedException('Could not update user', $this->user->errors());
            }
    }
}

Any suggestions? I'm lost.