Laravel 8.* + Backpack + Article with image (file upload)

Lyubomir Filipov
4 min readDec 19, 2020

In order to proceed you should have:
- Laravel installed + Backpack admin (teaching purposes)
- Tags CRUD created
- Article CRUD created
- virtual host ready for you
- xampp setup or other web server
- composer installed

Article
- title — 255 symbols
- content — text — RichTextEditor
- tags (many available) — select with multiple options

New tutorial to add file upload to the artilce
- image (one image) — image upload

#STEP 1: Create migration to add image to an article

php artisan make:migration add_image_to_articles_table --table=articles
/**
* Run the migrations.
*
*
@return void
*/
public function up()
{
Schema::table('articles', function (Blueprint $table) {
$table->string('image',255)->nullable();
});
}

/**
* Reverse the migrations.
*
*
@return void
*/
public function down()
{
Schema::table('articles', function (Blueprint $table) {
$table->dropColumn('image');
});
}

We are adding a new column image — which will be used to store the url of the image. Next step is to run the migration.

php artisan migrate

Expected result.

#STEP 2: Alter Article model

We need to add extra items to use:

use Illuminate\Support\Str;
use Intervention\Image\ImageManagerStatic as Image;
use Illuminate\Support\Facades\Storage;

And then add two functions in FUNCTIONS section.

public static function boot()
{
parent::boot();
static::deleting(function($obj) {
Storage::delete(Str::replaceFirst('storage/','public/', $obj->image));
});
}



public function setImageAttribute($value)
{
$attribute_name = "image";
// destination path relative to the disk above
$destination_path = "public/articles";

// if the image was erased
if ($value==null) {
// delete the image from disk
Storage::delete($this->{$attribute_name});

// set null in the database column
$this->attributes[$attribute_name] = null;
}

// if a base64 was sent, store it in the db
if (Str::startsWith($value, 'data:image'))
{
// 0. Make the image
$image = Image::make($value)->encode('jpg', 90);

// 1. Generate a filename.
$filename = md5($value.time()).'.jpg';

// 2. Store the image on disk.
Storage::put($destination_path.'/'.$filename, $image->stream());

// 3. Delete the previous image, if there was one.
Storage::delete(Str::replaceFirst('storage/','public/', $this->{$attribute_name}));

// 4. Save the public path to the database
// but first, remove "public/" from the path, since we're pointing to it
// from the root folder; that way, what gets saved in the db
// is the public URL (everything that comes after the domain name)
$public_destination_path = Str::replaceFirst('public/', 'storage/', $destination_path);
$this->attributes[$attribute_name] = $public_destination_path.'/'.$filename;
}
}

First function will make sure that once we delete an entry — the file will be deleted as well.

Second function is a mutator responsible for the upload the image to the correct folder.

We have logic replacing /public folder with /storage folder due to the fact that images are exposed to end users using /storage folder.

#STEP 3: Install intervention/image

Run

composer require intervention/image

#STEP 4: Adjust Article controller

[
'label' => "Article Image",
'name' => "image",
'type' => 'image',
'crop' => true, // set to true to allow cropping, false to disable
'aspect_ratio' => 1, // omit or set to 0 to allow any aspect ratio
]

We need to adjust getFieldsData function and add the image column.

Our next change is related to setupListOperation method. We need to update it to the following

protected function setupListOperation()
{
$this->crud->set('show.setFromDb', false);
$this->crud->addColumns($this->getFieldsData(TRUE));
}

This will make sure that when we are adding images they will be shown on list as well.

#STEP 5: Make disk public and allow files to be shown

php artisan storage:link

#STEP 6: Time to test

Adding of an item

Edit of an item

List items table

Note: Files are uploaded to storage/app/public/articles

But they are available to the end users by accessing — DOMAIN/storage/articles/{IMAGE_NAME}

Video

--

--

Lyubomir Filipov

Group Architect at FFW, believer, developer, enthusiast