The Decorable Trait or How To Simply Attach and Upload an Image to a Model

The Decorable Trait or How To Simply Attach and Upload an Image to a Model


Nov 24 2017, 07:33 in Web Development

When developping a web application you are probably working with users, and those users can maybe create content on your plateform by filling forms, etc. Or maybe you're simply building a blog with posts.

Either way you most likely worked with some sort of content on which you can attach an image through an upload form. If that's the case you might enjoy this article.

I'm going to share with you a simple trait that can clean up your controllers and models.

Imagine you have a blog with posts. As an administrator of the website, you can create a post by filling in the "create" form. Along with this form you have a file input type in order to select an image. This way, you'll have a main image for your blog post and you can display it on the post index list. Another example would be users and avatars, but you got the point. I'm speaking about a model that has an image.

In Laravel 5 it is relatively easy to store images sent through a form. In your controller you can simply do

request()->image->store('storage/path')

This will return the filename generated by Laravel. You can now save that in your model attributes like that:

$post = new Post;
$post->title = request('title');
$post->image = request()->image->store('storage/path');
$post->save();

When you have a lot of attributes that you need to save into your model, your controller can become quite big...

Something I personally like to do is to clean things up like this

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

In one line, you can map all request data to your model attributes and save it directly.

Unfortunately when you have an image in your request object, you can't really use that shorthand method.. This is where the Decorable Trait comes into action :)

// App/Traits/Decorable.php

namespace App\Traits;

use Illuminate\Http\UploadedFile;

trait Decorable
{
    public function getImageAttribute()
    {
        return url($this->imageUploadPath . '/' . $this->attributes['image']);
    }

    public function setImageAttribute(UploadedFile $file)
    {
        $this->attributes['image'] = basename($file->store($this->imageUploadPath));
    }
}

And in your Post.php model

// App/Post.php

// ...

protected $imageUploadPath = 'posts';

// ...

With this simple trait you can now use 

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

Without any problem!

Hope this can help you out :)


Share: