Laravel 9.x + Backpack + Article with image (file upload)

Lyubomir Filipov
4 min readDec 11, 2022

In order to proceed you should have:
- Laravel installed + Backpack admin (teaching purposes)
- Tags CRUD created
- Article CRUD created

Note: There is an older version of this tutorial before Backpack was split on FREE vs PRO field types.

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

php artisan make:migration add_image_to_articles_table --table=articles

The new file is created. Open the file and edit it

    /**
* 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 to the articles table. In the down method, we are removing the column. The new column will hold information about the image name.

#STEP 2: Run migration

php artisan migrate

Expected result

#STEP 3: Alter the Articles model

We need to add extra items to use:

use Illuminate\Support\Str;
use Illuminate\Support\Facades\Storage;

And then add two functions in the 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 = "articles";

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

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

$disk = "public";
// filename is generated - md5($file->getClientOriginalName().random_int(1, 9999).time()).'.'.$file->getClientOriginalExtension()
$this->uploadFileToDisk($value, $attribute_name, $disk, $destination_path, $fileName = null);
$this->attributes[$attribute_name] = 'storage/' . $this->attributes[$attribute_name];

}

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

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

We have logic replacing /storage folder with /public folder due to the fact that images are exposed to end users using /storage folder but if we need to delete them then they are living in public/articles/{image}.

#STEP 4: Adjust Articles controller

Edit getFieldsData method and add a new entry

[
'label' => "Article Image",
'name' => "image",
'type' => ($show ? 'view' : 'upload'),
'view' => 'partials/image',
'upload' => true,
]

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

/**
* Define what happens when the List operation is loaded.
*
* @see https://backpackforlaravel.com/docs/crud-operation-list-entries
* @return void
*/
protected function setupListOperation()
{
$this->crud->set('show.setFromDb', false);
$this->crud->addColumns($this->getFieldsData(TRUE));

/**
* Columns can be defined using the fluent syntax or array syntax:
* - CRUD::column('price')->type('number');
* - CRUD::addColumn(['name' => 'price', 'type' => 'number']);
*/
}

#STEP 5: Create new view for the image

Create a new view file in /resources/views/partials/image.blade.php

Note: You are probably missing the ‘partials’ folder as well, so please create it.

Content of the view file:

@if(isset($entry->image))
<img src="/{{ $entry->image }}" width="120" alt="Article image" />
@endif

We are checking whether the image is set and if so we are showing it.

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

php artisan storage:link

Test everything :)

--

--

Lyubomir Filipov

Group Architect at FFW, believer, developer, enthusiast