Laravel 8.* + Backpack + Article with image (file upload)
By: Lyubomir Filipov
Tags: Image, Laravel8

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