Laravel Livewire Course - File Upload, Component and Blade
In the category model, we have a column for the image which is an optional column since it can be null:
Schema::create('categories', function (Blueprint $table) {
$table->id();
$table->string('title', 255);
$table->string('slug', 255);
$table->string('image', 260)->nullable();
$table->text('text')->nullable();
$table->timestamps();
});
Let's implement the optional upload; in this case, we will want to use Laravel's local disk, we want it to register the images in the public folder; so, let's create a new disk:
config/filesystems.php
'public_upload' => [
'driver' => 'local',
'root' => public_path()
],
And in the component class Save.php; we are going to use the feature that allows us to upload files:
app/Livewire/Dashboard/Category/Save.php
use Livewire\WithFileUploads;
class Save extends Component
{
use WithFileUploads;
***
With it, we create the property for the image and indicate the validations for the image; the typical, that it be of type image, a maximum size and that it is optional:
app/Livewire/Dashboard/Category/Save.php
public $title;
public $text;
public $image;
public $category;
protected $rules = [
'title' => "required|min:2|max:255",
'text' => "nullable",
'image' => "nullable|image|max:1024",
];
***
In the submit() method, we check if the user selects an image (that's what the conditional is for):
- We give a name to the image.
- We move the image to the disk that we created earlier.
- We update in the database.
app/Livewire/Dashboard/Category/Save.php
function submit()
{
$this->validate();
if ($this->category) {
$this->category->update(
[
'title' => $this->title,
'text' => $this->text,
'slug' => str($this->title)->slug(),
]
);
$this->dispatch('updated');
} else {
$this->category = Category::create(
[
'title' => $this->title,
'text' => $this->text,
'slug' => str($this->title)->slug(),
]
);
$this->dispatch('created');
}
// upload
if($this->image){
$imageName = $this->category->slug . '.'.$this->image->getClientOriginalExtension();
$this->image->storeAs('images/category',$imageName,'public_upload');
$this->category->update([
'image' => $imageName
]);
}
}
In order to easily reference the image, we are going to create a method that returns the absolute path to the image:
App/Models
use Illuminate\Support\Facades\URL;
***
class Category extends Model
{
***
public function getImageUrl()
{
return URL::asset("images/category/".$this->image);
}
}
And in the view, we put at the end of everything, the field for the image:
<x-label for="">Image</x-label>
<x-input-error for="image" />
<x-input type="file" wire:model="image" />
And a conditional that asks if we have an image registered for the category, so we display it:
resources/views/livewire/dashboard/category/save.blade.php
@if ($category && $category->image)
<img class="w-40 my-3" src="{{ $category->getImageUrl() }}" />
@endif
Transcipcin del vdeo
Lets start the part that I told you was missing is the category which is the one we are manipulating then down here which is where we do elat here in the implementation you could see that I am using the slot to place it as the name of the image for that reason I think it is a good idea to reload the category here in update it should not be necessary because automatically here in create it would be necessary to assign them but it was to put you in context and here we work with the category So lets go since we are here create the new field here I place it as image According to what we defined image and here the rules I put a comma I put image it can be of type null and here all the considerations the validations that you want to place I put a validation that indicates that it is an image and a maximum length something interesting with the maximum length this is 1024 which is a mega 1024 kb Remember that it is a mega if you published the livewire file here too We have one for the loading phase in this case the temporary ones Note that over here we have a maximum size which is 12 megabytes
Change maximum file size in Livewire
So in case you want to work with images well larger resources in general you would have to define this rule here and here you put the value that you want for example in this case it would be like 120 megabytes not exactly because I put an extra zero but this is where it goes so that you keep it in mind and here well the extensions and so on Eh well this was important Remember that it is in this file that we can publish using the vendor publish command
File upload
Okay back here Here we have the image now Here we more or less have everything We need to create the disk and everything else to be able to continue the implementation here Remember that the disk would be in Field System here in confit here Remember that you can see the route We are going to create a disk starting from an existing one Im going to start from this one that says local Here you can put any name This is the basic lar We also did this in the basic Larabel and Im going to put public One at a time its up to you The Driver is local here Remember that I would put if it is from Amazon that would be the S3 or I think it was the Amazon S3 server or any other but in this case it is local to our project
config/filesystems.php
'public_upload' => [
'driver' => 'local',
'root' => public_path()
],
We put local here would be the location we can place the public_path through this function that Remember that it refers to the public folder which is the only one that can be accessed through the good browser or in general to consume the application what we have here That is the route that it gives us and this would not be necessary for the rest here we have the Driver ready to use then we can close this remember here bring you the name we return here and we do what is the upload process Lets start by generating the name of the image I put image name it will be the same as atis here it depends on you you can also directly place the Time function for a unique name I am going to use here the tis is loot as I told you before category is loot here as this is only a text we have to indicate the extension of the image here we put the point so that it is the image name point which would be the image which is the get client original field My God I dont know what Im writing client original extension with which we get the original extension of the resource
$imageName = $this->category->slug . '.'.$this->image->getClientOriginalExtension();
Here we have the name then we just need to store it We put ts image Remember that this is not an ordinary field then we can print it on the screen This is a load type class with everything that this entails and what it implies And here we have a method called Store as which is to store it in a location that in this case is in the public folder So this asks us for several things This again is the basic r Here it asks us for the name of the resource Here we have already generated it And here it asks us for the name of the disk Remember that it is public_upload
$this->image->storeAs('images/category',$imageName,'public_upload');
At least in my case and here we can place additional folders that are going to be attached to the root or to or from this that is from the public folder which is the route that we indicate here the folder called image category will be attached so that we can have it more organized since when we also want to store the publications they are not all in the same folder and this would be all with this we would be storing the file So we need to update the image that we already have either well from the category Better said from the category that we already have either because it already existed or because we are creating it here so here we put category update because it already exists as mentioned before it was already created or it already existed and we were simply editing it we put image And remember that here we only reference its name since we already have the location fixed there and it is the one we defined previously
$this->category->update([
'image' => $imageName
]);
And this would be all here in the controller we need to go now to the client here in which I will start from this and place image here it will be image which is the name of the Field type property and here we ask if we have any problem with the image and this would be all here the rest of the little things are missing but they are optional around here we have it I will give it here to select Well it went for my courses I come here to downloads here I already have some images and it gives us a nice error that tells us Ah I missed the Trade Sorry there are so many little things well as for the Trade we are going to import it we place useLivewireWith here it is we import it and we use it here we place use LivewireWithFileUploads we save Im going to reload that I like to reload I select And now notice that it no longer gives the section and we give here a and now if it gives us a section how nice here it tells us illuminate validate image does not exist I may have written something wrong here lets see maximum is image in singular that was what told us that this validation does not exist we give an yes and it says that it was updated correctly lets see if it did the load Well here it is in green it looks good image and here we have it with the name that we generated here which is category 11 which is what we have here Well we didnt edit it but there you have the name so nothing is that let me try to create it because H I dont want to leave an incorrect code there create Im going to place here 15 text Although I always place this process when we are there the category is ready when it already exists but category Okay created successfully Okay here we do have it works perfectly I didnt remember if the create method returns the ID or directly the object Then the object is returned and we can already manipulate it there what happened is that we created it here we assign it to the category well it doesnt matter the events here we already had the category and we can access the slot at any other time you can put the Time here if thats what you want I think this got a bit long so were going to leave it here and in the next class well finish the implementation with the remains of the optional operations that we have left so here we go
- Andrés Cruz
This material is part of my complete course and book; You can purchase them from the books and/or courses section, Curso y Libro Laravel 11 con Tailwind Vue 3, introducción a Jetstream Livewire e Inerta desde cero - 2025.
Develop with Laravel, Django, Flask, CodeIgniter, HTML5, CSS3, MySQL, JavaScript, Vue, Android, iOS, Flutter