Laravel 10 Upload Images with Spatie Media Library Tutorial

Last Updated on by in Laravel

In this tutorial, we will explore the process of implementing image uploads using Spatie’s Media Library package in Laravel. This package simplifies the handling of file uploads and attachments within your application.

We will demonstrate how to integrate Spatie’s Media Library with your Laravel project, including the setup, configuration, and usage of the library. By the end of this tutorial, you will know how to upload images, associate them with a model, and manage media files effectively.

We’ll begin with the essentials, including installing the required dependencies and setting up the necessary configurations. Next, we’ll dive into the implementation of a simple form that enables users to upload images, as shown in the provided HTML code.

We will guide you through the process of handling form submissions, storing uploaded images, and associating them with a model using Spatie’s Media Library.

By following this tutorial, you will learn how to leverage Spatie’s Media Library to create a robust and efficient file management system for your Laravel applications. This knowledge will empower you to handle media files with ease, enhance the functionality of your projects, and deliver an improved user experience.

Laravel 10 Upload Avatar Images using Spatie Media Library Example

  • Step 1: Download Laravel App
  • Step 2: Update Database Details
  • Step 3: Install Spatie Medialibrary in Laravel
  • Step 4: Set Up Migration and Model
  • Step 5: Build Controller File
  • Step 6: Build New Routes
  • Step 7: Set Up Blade View Files
  • Step 8: Add App URL
  • Step 9: Run Laravel App

Download Laravel App

Start the first step by using the Composer command to download the latest version of the Laravel app, get to the terminal and execute the command.

composer create-project laravel/laravel my-demo-app --prefer-dist

Update Database Details

Open the .env file and update your database details like database name, username and password as given below.

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=db
DB_USERNAME=root
DB_PASSWORD=

If you are using MAMP local server in macOs; make sure to append UNIX_SOCKET and DB_SOCKET below database credentials in .env file.

UNIX_SOCKET=/Applications/MAMP/tmp/mysql/mysql.sock
DB_SOCKET=/Applications/MAMP/tmp/mysql/mysql.sock

Install Spatie Medialibrary in Laravel

Installing the Media library is easy and can be installed via Composer; if you want to use only the base package, please use the given command.

composer require "spatie/laravel-medialibrary:^9.6.0"

Let us prepare the database; you have to publish migration to create the media table for that.

php artisan vendor:publish --provider="Spatie\MediaLibrary\MediaLibraryServiceProvider" --tag="migrations"

Consequently, you have to execute a command to run migrations.

php artisan migrate

Set Up Migration and Model

Now, you have to generate “Client’s” migration and model files concurrently using the suggested command.

php artisan make:model Client -m

The suggested command generated, app/Models/Client.php, likewise you have to define the table schema into this model file.

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Spatie\MediaLibrary\InteractsWithMedia;
use Spatie\MediaLibrary\HasMedia;

class Client extends Model implements HasMedia
{
    use HasFactory, InteractsWithMedia;
    
    protected $fillable = [
        'name',
        'email',
    ];
}

Make sure to import InteractsWithMedia and HasMedia services, append HasMedia with implements, and define InteractsWithMedia right after HasFactory service in the model file.

Secondly, get into the app/database/migrations/create_clients_table.php, similarly you need to add the table values into this migration file.

<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateClientsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('clients', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->text('email');            
            $table->timestamps();
        });
    }
    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('clients');
    }
}

Build Controller File

Next, go to terminal and execute command to generate a controller.

php artisan make:controller ClientController

After running above command a new controller file created at app/Http/Controllers/ClientController.php path.

In this file, first import the Client model, we will use ClientController class to store client registeration form along with upload image into the database at the same time into the Medialibrary storage using the spatie media library.

<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\Client;

class ClientController extends Controller
{
    public function index()
    {    
        $clients = Client::latest()->get();
        return view('index', compact('clients'));
    }
    public function create()
    {
        return view('create');
    }
    
    public function store(Request $request)
    {
        $input = $request->all();
        $client = Client::create($input);
        if($request->hasFile('avatar') && $request->file('avatar')->isValid()){
            $client->addMediaFromRequest('avatar')->toMediaCollection('avatar');
        }
        return redirect()->route('client');
    }
}

Build New Routes

Now, the controller has been set, its time to build new routes to handle the controller’s functions; get inside the routes/web.php and define the three routes with Get and Post methods altogether.

<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\ClientController;

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
*/

Route::get('client',[ClientController::class,'index'])->name('client');
Route::get('client/create',[ClientController::class,'create'])->name('client.create');
Route::post('client/store',[ClientController::class,'store'])->name('client.store');

Set Up Blade View Files

Now, we are ready to create view files; create two view these files, we will build a form for user registration and create a file to show clients data after fetching from the database.

Import bootstrap 5, create the form tag, pass the action tag along with the route, which stores the name, email and avatar profile image into the database.

After that, make create.php and update code in the app/resources/views/create.blade.php file.

<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Add Spatie Medialibrary in Laravel</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body class="bg-info">
    <div class="container">
        <div class="d-flex p-2 bd-highlight mb-3">
            <a href="{{ route('client') }}" class="btn btn-outline-danger btn-sm">Go Back</a>
        </div>
        <div>
            <form action="{{ route('client.store') }}" enctype="multipart/form-data" method="post">
                @csrf
                <div class="mb-3">
                    <label>Name</label>
                    <input type="text" name="name" class="form-control">
                </div>
                <div class="mb-3">
                    <label>Email</label>
                    <input type="email" name="email" class="form-control">
                </div>
                <div class="mb-3">
                    <label>Image:</label>
                    <input type="file" name="avatar" class="form-control">
                </div>
                <div class="d-grid">
                    <button class="btn btn-primary">Store</button>
                </div>
            </form>
        </div>
    </div>
</body>
</html>

Create index.php and update code in the app/resources/views/index.blade.php file.

<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Integrate Spatie Medialibrary in Laravel</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
    <div class="container">
        <div class="d-flex p-2 bd-highlight mb-3">
            <a href="{{ route('client.create') }}" class="btn btn-dark">Add</a>
        </div>
        <table class="table">
            <thead>
                <tr>
                    <th>#</th>
                    <th>Name</th>
                    <th>Email</th>
                    <th width="30%">Avatar</th>
                </tr>
            </thead>
            <tbody>
                @foreach($clients as $key=>$item)
                <tr>
                    <td>{{ ++$key }}</td>
                    <td>{{ $item->name }}</td>
                    <td>{{ $item->email }}</td>
                    <td><img src="{{$item->getFirstMediaUrl('avatar', 'thumb')}}" / width="120px"></td>
                </tr>
                @endforeach
            </tbody>
        </table>
    </div>
</body>
</html>

Add App URL

In this step, you have to open the .env configuration file and look for the APP_URL variable and append the given url in-front.

...
...
...
APP_URL = http://localhost:8000
...
...
...

Run Laravel App

By default, the public disk utilizes the local driver and stores its files in storage/app/public.

To make these files accessible from the web, you should create a symbolic link from public/storage to storage/app/public.

So, we can create the symbolic link to access the storage directory using the artisan command publicly.

php artisan storage:link

You have reached final at the end of the tutorial, now start the app using the php artisan command:

php artisan serve

Here is the link which will help you open the app on the browser and test.

http://localhost:8000/client

Laravel Upload Images with Spatie Media Library Example

Conclusion

Now you have successfully integrated Spatie’s Media Library with your Laravel 10 project, allowing you to handle image uploads effortlessly.

This extensive how-to guide will enhance your application by providing a streamlined approach to file management, making your development process smoother and more efficient.

Age calculator tool

🎂✨ Discover your age in detail and with countdown to your next birthday with fun facts! 🎈🎉

Calculate your age now!
Digamber - Author positronX.io

Hi, I'm Digamber Singh, a New Delhi-based full-stack developer, tech author, and open-source contributor with 10+ years' experience in HTML, CSS, JavaScript, PHP, and WordPress.