Planning Image Uploads0:00
Let's take a look at how we can upload images, which is another common thing you might implement in a Laravel app. There are a bunch of different approaches you can take, but in this video, we'll stick to using the native file input and Laravel. In the next video, we'll take a look at making the experience a bit better with a JavaScript library. So how about we add an image that shows in the announcement page here, and we can upload it within the edit announcement page. So we'll add a file upload within here. So let's start with that.
Adding File Input0:25
So we'll add a file upload within here. So let's start with that. Let's add a new one underneath our button link. Let's duplicate this. Let's call it ImageUpload. Let's say ImageUpload, ImageUpload. And the input type is a file, so let's add that. input type equals file, name is ImageUpload, and let's give it a class of MarginTop2. And don't forget to add the enctype on the form for our uploads to work correctly. So on the form tag, we can say enctype, and it has to be a multipart/form-data.
Validating Uploads0:57
And don't forget to add the InkType on the form for our uploads to work correctly. So on the form tag, we can say InkType, and it has to be a multi-part form data. Okay. So let's save that. And we're still hitting this endpoint here, which updates the form. So AnnouncementUpdate. Let's go back to our Routes/web.php. But now we need to accept that ImageUpload or validate it. So let's do that, ImageUpload. It is a file.
So let's do that, ImageUpload. It is a file. It's also an image. And how about we make sure it's max 20 megs. So max in kilobytes is this. That should be 20 megs. Okay. So let's try that out. I actually think I don't have the error message that shows. So let's add that in our Blade view up here.
I actually think I don't have the error message that shows. So let's add that in our Blade view up here. So I do have the success message up here. So let me add the errors. And I believe I do have a snippet here. So we'll just make use of this. So if there are errors, show them here. Let me just change the classes. So say bg-red-200, text-red-700. And let's give it some padding.
Our file is not required. And I didn't add the required validation rule here. So if I just update the form, normally, that should still work. There's our file upload. Let's just hit update. That should still work fine. And it does. But if we try to upload a file here, that's not an image, we should get a error. So let's try this PDF here. Let's open.
So let's try this PDF here. Let's open. Let's upload. And we do get that error. Let me just dd request here. So you can see the type of the uploaded file. So let's say dd request all. And let's upload a file. Let's refresh. Let's upload a file here.
Let's refresh. Let's upload a file here. Let's make it an image this time. So this one is open. And let's update it. And you can see the uploadedFile is of type UploadedFile. And it has all this information, which we can make use of. Okay, so we want to store this file somewhere on our disk. And in this video, we'll just do it locally. But you can do it on a remote disk as well.
Saving Path in Database3:14
And in this video, we'll just do it locally. But you can do it on a remote disk as well. And we also want to store the file name in the database. So let's go ahead and add that field in our database. So for our CreateAnnouncements table, let's add that field here. So I'll put it right here. It is a string. Let's call it imageUpload. And we'll make it nullable. Okay, let's save that.
And we'll make it nullable. Okay, let's save that. Let me just php artisan migrate --seed. Okay, now we should have that field in our database. Double check here. Refresh this. And it should be here, right here. Cool. Now we can make use of Laravel storage methods to store our file on our disk.
Storing Files Locally3:54
Now we can make use of Laravel storage methods to store our file on our disk. So let's go back to our code. Let's go back to our endpoint here. And let's check if there's an image upload. So we'll say if request image upload. So if there is an image upload, then go ahead and store the file and also save it to the database. But if there isn't, just save all the other fields.
and also save it to the database. But if there isn't, just save all the other fields like we have down here. So we can make use of the store method. So we can say $request. Let's grab the file. So $request file(image upload). Let's use the store method here. How about we put it in a folder named images. And I want to use the public disk.
How about we put it in a folder named images. And I want to use the public disk. So if you take a look at our file systems, config, here are our default disks. And there's one for public right here. So that's going to go into the storage/app/public folder. So it's a public here for our disk. And this will return the path of the file. And we want to store this in our database. So we're updating our database with this fields variable.
And we want to store this in our database. So we're updating our database with this fields variable. So if there is an imageUpload, we can update that. So we'll say fields equals, and we'll use array_merge here. So let's merge the current fields with this new array with the imageUpload. So let's say imageUpload is the path. Okay. So hopefully I did that correctly.
Okay. So hopefully I did that correctly. Let's save that. We might have to do php artisan storage:link to link our public folder with the storage folder. I believe it's storage:link. Okay. And let's try that out. Let's go back here. Let's refresh.
Let's check our database. Let's refresh this. The path seems to be correct. Right here. images/, and it's just a hash name. It's a .png. And let's make sure that file actually exists. So let's check that in storage/app/public,
Displaying Uploaded Images6:07
app, public, images. And there it is. Cool. And now we can show this image within our announcement page. So let's close this. Let's go to our announcement blade, right above our content. Let's add our image here.
right above our content. Let's add our image here. Put a margin-top on this actually. Four maybe. Add our image here. Let's say image. Let's use the asset helper. So say asset. And that should be within the announcement, image upload field.
And that should be within the announcement, image upload field. Okay. Let's add a class. Let's just say mx-auto. To center it. And let's see if that shows. So in our announcement page, there is our image along with our content. How about we show the image as well
there is our image along with our content. How about we show the image as well within the actual edit page? So we know what's currently there. So down here, let's show the image. So we can pretty much just copy what we have here. You actually might have to wrap this in an if because there might not be an image uploaded. So let's do that first. if.
Let's put it underneath our file upload. So right here, let's just duplicate this. Let's get rid of this stuff. Let's paste this in. Save that. Actually, this should be outside of the div. Okay, save that. And I'll change the class to just make it a smaller size. So max-width: extra-small. Okay, save that.
then I'd be fine with what we have here. So let's try uploading a different file here. Let's choose a file. And actually, you can limit it to images if you add an accept attribute. So let's do that. So back here for our file upload, we can add accept equals, and we can say only images. So image/*.
and we can say only images. So image/*. Or you can specify certain file names like image.png, and you can have multiple as well, separated by commas like this, and then image/jpeg, but I'll just stick with *. And now if we use that input, so let me just refresh here, you'll see that it grays out non-images.
Resizing with Intervention Image9:06
And even if we have validation on, we want to make sure to optimize that image. So let's pull in intervention/image. Let's resize the image after it's uploaded and use that one instead. So let's quickly install intervention/image. Pretty straightforward. composer require intervention/image. So composer require, okay. And now we have to take our uploaded file
So composer require, okay. And now we have to take our uploaded file and change it to an Intervention Image instance so we can make use of its methods. So let's go back to our routes file. So let me just comment this out for now. So let's grab our image coming in. We'll name it $requestImage and we'll say $request->file('image_upload'). And now we'll make another variable named $image
and we'll say request file image upload. And now we'll make another variable named image which we'll use InterventionImage. So image::make is how you make an instance of it. And that would be the request image. Make sure to import InterventionImage here and it's this one here. And let me just dd that so you can see it is an instance of InterventionImage.
And let me just die and dump that so you can see it is an instance of InterventionImage. So let's say dd $image. Let's try that out. So back here, back to our edit. Let's upload a file. This one, open, update. And you can see it is InterventionImage here. So now we can make use of the resize method. So that should be within the docs here.
So now we can make use of the resize method. So that should be within the docs here. Let's look for a resize here. There it is. And you can do a bunch of different things in regards to images using this package but we just need to resize it so we can make use of this method. So we're gonna use the constrain method or the constraint option to maintain the aspect ratio.
So we're gonna use the constraint method or the constraint option to maintain the aspect ratio and also prevent possible upsizing. So let's grab this, put it in our code. Let's paste it right here. Save that, should be image. How about we make it 600 pixels wide, max. We can leave the height to null and that will resize accordingly based on the width and constraining the aspect ratio.
And let's see if it's resized at this point. And I believe there's information about the image here somewhere, right there. The size is now 600 by 338. And originally it was much bigger at 3840 pixels wide. So now we just have to store this image in our file system. And we can no longer make use of the store method because it's an Intervention Image now. But Intervention Image does have a save method and we can save it as a file.
But InterventionImage does have a save method and we can save it as a file. InterventionImage does have a save method that we can make use of. So image, save to the path. So let's grab the path here. So path equals, and we want the actual path name here. So again, let's go back to our file system. The path name is actually right here. So we can say config/filesystems.php, disks, public, root.
The path name is actually right here. So we can say config/filesystems.php, disks, public, root. So let's go ahead and do that. So say config/filesystems.php.disks.public.root. Okay, let's just add it to the root. So that's gonna go within this public folder right here. You can put it within a folder as well, but I think that folder has to exist so you can create it manually because this method won't create the folder.
so you can create it manually because this method won't create the folder if it doesn't already exist. So for us, we'll just store it in the root folder. So let's add a slash here for the root folder and let's make use of the file name. So we can just say request image and we can make use of the hashName method. So that would be the file name similar to this hash in these images here, okay?
So that would be the file name similar to this hash in these images here, okay? So now it's gonna save it to this location after we call the save method. And now we have to update our fields. So this path won't work anymore because it's actually a path on my actual computer and we sort of just want the relative path. So let's grab this and we'll just make use of the hashName method as well.
So let's grab this and we'll just make use of the hashName method as well. So let's comment this back in. The image upload is going to be this same method here. Okay, let's replace that. And hopefully I did everything correctly. Let's upload an image and let's see if it goes into this folder here and hopefully it's resized to 600 pixels. So let's try that.
Okay, update it. The thumbnail shows correctly. Let's see if it's 600 pixels within here. And it is, cool. So that means it is saving to the database correctly. Let's just double check the database. Let's refresh this. And you'll see it's within the root here and that's the file name, cool. So yeah, like I said,
and that's the file name, cool. So yeah, like I said, the native file input is already a pretty decent experience in my opinion. If only a few people are going to use this, say within an admin dashboard, then I'm okay with just using this. However, if it was user-facing, I would consider making the experience a bit better using some sort of JavaScript library.
Wrapping Up and Commit14:22
I would consider making the experience a bit better using some sort of JavaScript library to have support for things like image previews and automatic uploads right when you choose the file. So we'll take a look at that in the next video. But for now, let's make a commit for this. This is episode five. Let's say, Laravel file uploads.
