I followed this tutorial for spatie Laravel Media Library and it worked for me.

Github Code: https://github.com/edwinaquino/Laravel-With-Spatie-Media-Library

Source: /g/APPS/REACT/OVERIMAGE/V5/LARAVEL/TUTORIAL/Code With Tony/laravel-media-posts

FeIYurxiggU

Laravel Media Library Full Tutorial | Laravel 10 Tutorial

YOU CAN START WITH A NEW PROJECT IF NEEDED:
laravel new DailyLogV3
cd DailyLogV3
code .


https://www.youtube.com/watch?v=FeIYurxiggU
Credit to: Code With Tony
 

$ composer require "spatie/laravel-medialibrary:^10.0.0"
$ php artisan vendor:publish --provider="Spatie\MediaLibrary\MediaLibraryServiceProvider" --tag="migrations"

php artisan migrate
https://youtu.be/FeIYurxiggU?t=204

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


https://youtu.be/FeIYurxiggU?t=294
php artisan make:model Post -m

code database/migrations/2023_06_10_225451_create_posts_table.php
ADD:
            $table->string('title');
            $table->text('body');

php artisan migrate           


code routes/web.php
ADD:
use App\Http\Controllers\PostController;
Route::resource('/posts', PostController::class);

php artisan make:controller PostController -r

code app/Http/Controllers/PostController.php
under create() ADD:
return view('posts.create');

php artisan serve

mkdir resources/views/posts
code resources/views/posts/create.blade.php

php artisan make:component main
main.blade.php:
#####################################################
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">

        <title>Laravel</title>

        <!-- Fonts -->
        <link rel="preconnect" href="https://fonts.bunny.net">
        <link href="https://fonts.bunny.net/css?family=figtree:400,600&display=swap" rel="stylesheet" />
        {{-- <script src="https://cdn.tailwindcss.com"></script> --}}

    </head>
    <body class="antialiased">
{{$slot}}
    </body>
</html>
#####################################################

http://localhost:8000/posts/create

https://youtu.be/FeIYurxiggU?t=604

code resources/views/components/main.blade.php
#####################################################
<x-main>
<div class="max-w-6xl mx-auto mt-12">
    <form action="" enctype="multipart/form-data">
    Post Title: <input type="text" name="title" id="title"><br />
    Post Body: <input type="text" name="body" id="body"><br />
    Post Image: <input type="file" name="image" id="image"><br />
<button type="submit">Create</button>
    </form>
</div>
</x-main>
#####################################################

$ php artisan make:request PostCreateRequest
$ code app/Http/Requests/PostCreateRequest.php
 authorize()
FROM: return false
TO: return true

code app/Http/Controllers/PostController.php
#####################################################
ADD:
use App\Models\Post;
use App\Http\Requests\PostCreateRequest;
//// create()
    public function create()
    {
        return view('posts.create');
    }
//// store()
    public function store(PostCreateRequest $request)
    {
        //https://stackoverflow.com/questions/58450648/too-few-arguments-through-laravel-custom-request-class
        $validated = $request->validated();
        Post::create($validated);
    }
#####################################################

code app/Models/Post.php
#####################################################
ADD after use HasFactory;
    protected $guarded = [];
#####################################################

https://youtu.be/FeIYurxiggU?t=921

code app/Models/Post.php
#####################################################
ADD
use Spatie\MediaLibrary\HasMedia;
use Spatie\MediaLibrary\InteractsWithMedia;

CHANGE:
FROM: class Post extends Model
TO: class Post extends Model implements HasMedia

ADD: InteractsWithMedia to:
 use HasFactory, InteractsWithMedia;

#####################################################
https://youtu.be/FeIYurxiggU?t=1000

code app/Http/Controllers/PostController.php
#####################################################
CHANGE store() TO:
    public function store(PostCreateRequest $request) {
        $validated = $request->validated();
        $post = Post::create($validated);
        if ($request->hasFile('image')) {
            $post->addMediaFromRequest('image')
                ->usingName('Documents')
                ->toMediaCollection();
        }
    }
#####################################################

TRY IT: http://localhost:8000/posts/create
check media table: http://localhost:8080/phpmyadmin/index.php?route=/sql&pos=0&db=laravel_medialib&table=media

IF YOU WANT TO CHANGE THE colunm "name" to 'Documents' NAME IN THE DATABASE: https://youtu.be/FeIYurxiggU?t=1205
->usingName('Documents')
code app/Http/Controllers/PostController.php
#####################################################
CHANGE store() TO:
    public function store(PostCreateRequest $request)
    {
        $validated = $request->validated();
        $post = Post::create($validated);
        $post->addMediaFromRequest('image')
        ->usingName('Documents') // or  ->usingName($post->title)
        ->toMediaCollection();

    }
#####################################################
TRY IT: http://localhost:8000/posts/create
check media table: http://localhost:8080/phpmyadmin/index.php?route=/sql&pos=0&db=laravel_medialib&table=media


https://youtu.be/FeIYurxiggU?t=1362


https://www.webune.com/forums/solution-laravel-spatie-image-lirbary-unable-to-view-images-with-href.html
https://www.webune.com/forums/laravel-spatie-image-lirbary-error-call-to-a-member-function-geturl-on-null.html
code resources/views/posts/index.blade.php
#####################################################
<x-main>
    <div class="max-w-6xl mx-auto mt-12">

<table class="table table-bordered">
    <thead>
        <tr>
            <th>Id</th>
            <th>Title</th>
            <th>Image</th>
            <th>Edit</th>
            <th>Delete</th>
        </tr>
    </thead>
    <tbody>

@foreach ($posts as $post)
<tr>
    <td>{{ $post->id }}</td>
    <td>{{ $post->title }}</td>
    {{-- <td> <img src="{{ $post->getFirstMedia()->getUrl() }}" alt="image{{ $post->id }}" class="img-thumbnail" style="width:250px" /></td> --}}
    <!--OR use getFirstMediaUrl-->

    <td><img src="{{ $post->getFirstMediaUrl() }}" alt="image{{ $post->id }}" class="img-thumbnail" style="width:250px" /></td>
    <td><a href="{{ route('posts.edit', $post->id) }}" class="btn btn-success">Edit</a></td>
    <td><form action="{{ route('posts.destroy', $post->id) }}" onsubmit="return confirm('Are you sure?');">
    @csrf
    @method('DELETE')
    <button type="submit" class="btn btn-danger">Delete</button>
</form></td>
</tr>
@endforeach
</x-main>
#####################################################

E D I T
https://youtu.be/FeIYurxiggU?t=1477
code app/Http/Controllers/PostController.php
#####################################################
    public function edit(Post $post)
    {
        return view('posts.edit', compact('post'));
    }
#####################################################

code resources/views/posts/edit.blade.php
#####################################################
<x-main>
    <div class="max-w-6xl mx-auto mt-12">
        <h1>Edit Post Id: {{$post->id}}</h1>
        <form method="POST" action="{{ route('posts.update', $post->id) }}" enctype="multipart/form-data">
            @csrf
            @method('PUT')
        Post Title: <input type="text" name="title" id="title" value="{{$post->title}}">><br />
        Post Body: <input type="text" name="body" id="body" value="{{$post->body}}"><br />
        Post Image: <input type="file" name="image" id="image"><br />
    <button type="submit">Create</button>
        </form>
    </div>
    </x-main>

#####################################################

https://youtu.be/FeIYurxiggU?t=1708
code app/Http/Controllers/PostController.php
#####################################################
    public function update(PostCreateRequest $request, Post $post)
    {
        // UPDATE DATABASE
        $validated = $request->validated();
        $post->update($validated);
        if($request->hasFile('image')){

            // delete the previous image
            $post->clearMediaCollection();
            // UPDATE the new image
            $post->addMediaFromRequest('image')
            ->usingName('Documents')
            ->toMediaCollection();
        }
        return to_route('posts.index');
    }
#####################################################
https://youtu.be/FeIYurxiggU?t=1946

UPDATE index.blade.php
code resources/views/posts/index.blade.php
#####################################################
<x-main>
    <div class="max-w-6xl mx-auto mt-12">

<table class="table table-bordered">
    <thead>
        <tr>
            <th>Id</th>
            <th>Title</th>
            <th>Image</th>
            <th>Edit</th>
            <th>Delete</th>
        </tr>
    </thead>
    <tbody>

@foreach ($posts as $post)
<tr>
    <td>{{ $post->id }}</td>
    <td>{{ $post->title }}</td>
    {{-- <td> <img src="{{ $post->getFirstMedia()->getUrl() }}" alt="image{{ $post->id }}" class="img-thumbnail" style="width:250px" /></td> --}}
    <!--OR use getFirstMediaUrl-->

    <td><img src="{{ $post->getFirstMediaUrl() }}" alt="image{{ $post->id }}" class="img-thumbnail" style="width:250px" /></td>
    <td><a href="{{ route('posts.edit', $post->id) }}" class="btn btn-success">Edit</a></td>
    <td><form
        method="POST"
        action="{{ route('posts.destroy', $post->id) }}"
        onsubmit="return confirm('Are you sure?');"

        >
    @csrf
    @method('DELETE')
    <button type="submit" class="btn btn-danger">Delete</button>
</form></td>
</tr>
@endforeach
</x-main>


#####################################################
DELETE
https://youtu.be/FeIYurxiggU?t=1948

code app/Http/Controllers/PostController.php
ADD function destroy()
#####################################################
    public function destroy($id)
    {
        $post= Post::findOrFail($id);
        $post->delete();
        return to_route('posts.index');
    }
    /*
    // ANOTHER WAY TO DELETE
    public function destroy(Post $post)
    {
        $post->delete();
        return to_route('posts.index');
    }
    */

#####################################################
IMAGE COLLECTIONS: 'images' - this will add 'images' to the 'collection' column in the media database table
https://youtu.be/FeIYurxiggU?t=2011
code app/Http/Controllers/PostController.php
#####################################################
UPDATE FROM: ->toMediaCollection();
TO: ->toMediaCollection('images');
#####################################################

code resources/views/posts/index.blade.php
#####################################################
UPDATE FROM:img src="{{ $post->getFirstMediaUrl() }}"
TO: img src="{{ $post->getFirstMediaUrl('images') }}"

UPDATE FROM: $post->clearMediaCollection();
to: $post->clearMediaCollection('image');
#####################################################

https://youtu.be/FeIYurxiggU?t=2280


ADD ANOTHER IMAGE COLLECTION:
https://youtu.be/FeIYurxiggU?t=2433
code app/Http/Controllers/PostController.php
#####################################################
Add to update and create methods:
        if ($request->hasFile('download')) {

            // delete the previous image
            $post->clearMediaCollection('downloads');
            // UPDATE the new image
            $post->addMediaFromRequest('download')
                ->usingName('Documents')
                ->toMediaCollection('downloads');
        }

#####################################################


CREATE A DOWNLOAD LINK FOR IMAGES:
https://youtu.be/FeIYurxiggU?t=2600

code routes/web.php
ADD:
#####################################################
Route::get('/downloads/{id}', [PostController::class, 'download']);
#####################################################

code app/Http/Controllers/PostController.php
#####################################################
    public function download($id) {
        $post = Post::findOrFail($id);
        $media = $post->getFirstMedia('donloads');
        return $media;
    }
#####################################################
TEST THE DOWNLOA IN BROWSER:  http://127.0.0.1:8000/downloads/5
WORKS!!!!!!!!!!!

DOWNLOAD ALL COLLECTION FILES:
code routes/web.php
ADD:
#####################################################
Route::get('/downloads', [PostController::class, 'downloads']);
#####################################################

code app/Http/Controllers/PostController.php
#####################################################
    public function downloads() {

        $media = Media::where('collection_name','downloads')->get();

        return MediaStream::create('donwloads.zip')->addMedia($media);
    }
#####################################################
https://youtu.be/FeIYurxiggU?t=2895
TEST THE DOWNLOA IN BROWSER:  http://127.0.0.1:8000/downloads
WORKS!!!!!!!!!!!

DOWNLOAD ALL FILES:
code routes/web.php
ADD:
#####################################################
Route::get('/downloadsall', [PostController::class, 'downloadsall']); //DOWNLOAD ALL FILES:

#####################################################

code app/Http/Controllers/PostController.php
#####################################################
    public function downloadsall() {
        return MediaStream::create('donwloads.zip')->addMedia(Media::all());
    }
#####################################################
TEST THE DOWNLOA IN BROWSER:  http://127.0.0.1:8000/downloadsall
WORKS!!!!!!!!!!!


BETTER WAY TO REMOVE/UPDATE MEDIA COLLECTIONS:
https://youtu.be/FeIYurxiggU?t=3063

code app/Http/Controllers/PostController.php
#####################################################
in update()
REMOVE or COMMENTOUT: $post->clearMediaCollection('images');
#####################################################

code app/Models/Post.php
#####################################################
ADD
    public function registerMediaCollections(): void
    {
        $this->addMediaCollection('images')
        ->singleFile();
    }
#####################################################
TRY IN BROWSER:  http://127.0.0.1:8000/posts
WORKS!!!!!!!!!!!


https://youtu.be/FeIYurxiggU?t=3345

https://spatie.be/docs/laravel-medialibrary/v10/converting-images/defining-conversions
 MEDIA CONVERSIONS - CREATE A THUMB

code app/Models/Post.php
#####################################################
ADD
use Spatie\MediaLibrary\MediaCollections\Models\Media;

    public function registerMediaConversions(Media $media = null): void
    {
        $this->addMediaConversion('thumb')
              ->width(368)
              ->height(232)
              ->sharpen(10);
    }
#####################################################
TRY IN BROWSER:  http://127.0.0.1:8000/posts/create
Look in the public/storage/[ID] folder and you will see a Conversions folder where you can find the thumb image: storage/app/public/[id]
$ ls storage/app/public/20/conversions

USAGE:
code resources/views/posts/index.blade.php
#####################################################
CHANGE:

    {{-- FULL IMAGE --}}
    {{-- <td><img src="{{ $post->getFirstMediaUrl('images') }}" alt="image{{ $post->id }}" class="img-thumbnail" style="width:250px" /></td> --}}

    {{-- // THUMB IMAGE --}}
    <td><img src="{{ $post->getFirstMedia('images')->getUrl('thumb') }}" alt="image{{ $post->id }}" class="img-thumbnail" style="width:250px" /></td>

    {{-- FULL IMAGE --}}
    {{-- <td><img src="{{ $post->getFirstMediaUrl('downloads') }}" alt="download{{ $post->id }}" class="img-thumbnail" style="width:250px" /></td> --}}

    {{-- // THUMB DOWNLOA --}}
    <td><img src="{{ $post->getFirstMedia('downloads')->getUrl('thumb') }}" alt="download{{ $post->id }}" class="img-thumbnail" style="width:250px" /></td>

#####################################################
https://youtu.be/FeIYurxiggU?t=3536
TRY IN BROWSER:  http://127.0.0.1:8000/posts

RESPONSIVE IMAGES
https://spatie.be/docs/laravel-medialibrary/v10/responsive-images/getting-started-with-responsive-images


code app/Http/Controllers/PostController.php
#####################################################
REPLACE ALL: ->usingName('Documents')
WITH: ->withResponsiveImages()
#####################################################
TRY IN BROWSER:  http://127.0.0.1:8000/posts/create
(TAKES A WHILE TO LOAD)
SEE THE NEWLY CREATED folder: responsive_images
$ ls storage/app/public/22/responsive-images

laravel-no-gd-extension-missing___media_library_original_1074_449.jpg
laravel-no-gd-extension-missing___media_library_original_1283_537.jpg
laravel-no-gd-extension-missing___media_library_original_1534_642.jpg
laravel-no-gd-extension-missing___media_library_original_1834_767.jpg
laravel-no-gd-extension-missing___media_library_original_526_220.jpg
laravel-no-gd-extension-missing___media_library_original_629_263.jpg
laravel-no-gd-extension-missing___media_library_original_751_314.jpg
laravel-no-gd-extension-missing___media_library_original_898_376.jpg

APPLY TO VIEW REPONSIVE IMAGES:

code routes/web.php
#####################################################
Route::get('/res-image/{id}', [PostController::class, 'resImage']); // RESPONIVE IMAGES
#####################################################

code app/Http/Controllers/PostController.php
#####################################################
    public function resImage($id) {
        //return $id;
        $post = Post::findOrFail($id);
        return view('posts.show', compact('post'));
    }
#####################################################


code resources/views/posts/show.blade.php
#####################################################
<x-main>
    <div class="container">
        <div class="row">
            <h1>{{$post->title}}</h1>
            {{$post->getFirstMedia('downloads')}}
        </div>
    </div>
</x-main>
#####################################################

TRY IN BROWSER:  http://127.0.0.1:8000/resimage/7
WORKS!!!!!!!!!!!
try with different browser window size and in the network tab you will see diferent size images downloading.

https://youtu.be/FeIYurxiggU?t=4005