dwightwatson / validating

Automatically validating Eloquent models for Laravel
MIT License
968 stars 76 forks source link

[Proposal] add newOrFail(), createOrFail() and updateOrFail() methods #179

Open Evertt opened 7 years ago

Evertt commented 7 years ago

It would be nice if I could do the following with my models that use the ValidatingTrait:

function store(Request $request)
{
    return Post::createOrFail($request->all());
}

function update(Request $request, Post $post)
{
    return $post->updateOrFail($request->all());
}

Which would then be equivalent to:

function store(Request $request)
{
    $post = new Post($request->all());

    $post->saveOrFail()

    return $post;
}

function update(Request $request, Post $post)
{
    $post->fill($request->all())->saveOrFail();

    return $post;
}

And just to be complete, this:

$post = Post::newOrFail($request->all());

would be equivalent to:

$post = new Post($request->all());

$post->isValidOrFail();
dwightwatson commented 7 years ago

Hey, thanks for the suggestions. I don't mind the idea of adding createOrFail and updateOrFail but I don't feel the same about newOrFail. I feel like "newing up" an instance never fails. It might instantiate an invalid model, but that's not really something to fail for.

Open to pull requests for the functionality, or I'll have a crack at it when I've got some free time.

Evertt commented 7 years ago

I feel like "newing up" an instance never fails. It might instantiate an invalid model, but that's not really something to fail for.

I almost agree. I can imagine that there are times that a developer does want to new up an instance and immediately validate it (and throw an exception if that fails) before continuing to do stuff with that instance. In any case, why not give developers more options anyway? If a developer thinks newing up an instance shouldn't fail then they'll just use the normal construction method.

By the way, I already made my own trait which extends yours, so you can copy-paste that code if you want:

namespace App\Validation;

/**
 * @mixin \Eloquent
 */
trait ValidatingTrait
{
    use \Watson\Validating\ValidatingTrait;

    /**
     * @param  array  $attributes
     * @return static
     */
    public static function newOrFail(array $attributes = [])
    {
        $model = new static($attributes);

        $model->isValidOrFail();

        return $model;
    }

    /**
     * @param  array  $attributes
     * @param  array  $options
     * @return static
     */
    public static function createOrFail(array $attributes = [], array $options = [])
    {
        $model = static::newOrFail($attributes);

        $model->save($options);

        return $model;
    }

    /**
     * @param  array  $attributes
     * @return static
     */
    public static function firstOrNewOrFail(array $attributes = [])
    {
        $model = static::firstOrNew($attributes);

        if (!$model->exists) $model->isValidOrFail();

        return $model;
    }

    /**
     * @param  array  $attributes
     * @param  array  $options
     * @return static
     */
    public static function firstOrCreateOrFail(array $attributes = [], array $options = [])
    {
        $model = static::firstOrNewOrFail($attributes);

        $model->save($options);

        return $model;
    }

    /**
     * @param  array  $attributes
     * @param  array  $options
     * @return $this
     */
    public function updateOrFail(array $attributes = [], array $options = [])
    {
        $this->fill($attributes)->saveOrFail($options);

        return $this;
    }
}