Laravel 5.8 – From The Ground Up
Lección 52 de 52 · Laravel 5.8 Tutorial From Scratch – e52 – Multi Image File Upload & Gallery · Educación
Laravel 5.8 Tutorial From Scratch – e52 – Multi Image File Upload & Gallery
welcome in this episode we're going to be tackling probably the most requested thing in coders tape and that is how to do multiple image upload and create a
gallery using level and view so let me show you what we're actually going to be building and this is it right here this is the finished product now the first thing you'll notice is just drop images
here now this is gonna allow us to grab some images here are some sample images that I have and simply just drag them into here and this will upload them for us automatically
now we'll also create a thumbnail for us so what we're actually seeing here is a thumbnail so 250 pixel by 250 pixel thumbnail if we click on the image then we do get the full resolution image so
that's pretty cool furthermore from that we can hit the delete button and that goes away and of course we are deleting the record from the database but we're also cleaning up
our files we're actually deleting the thumbnail and the original file with that single click so stick around we have a lot to cover and we're gonna do it from scratch
100% using level and view I'll see you on the other side [Music] okay so let's start from the very beginning
let's run laravel new image – upload so a completely fresh level installation so let's let it do its thing we'll be right back okay and now that's finished let's visit in the browser I
hit refresh and there we go so we have a fresh level installation okay a couple more setup things that we need to do so let me CD into our image of load
project and let's go ahead and run npm install of course we're gonna use view to make the drag-and-drop functionality work so let's go ahead and run all the npm installation and then we'll add drop
zone that's the package that's gonna let us drop files into the browser and upload them for us okay so now let's run npm i and the package that we're looking for is drop zone and let's go ahead and
save that to our dependencies so now we can run npm run watch and because this is the first time it's gonna need to install a couple more things all right so we are all compiled and ready to go
let me go ahead and open this up in phpstorm so now that it's open in phpstorm one thing i do want to note is that i'm going to try to use everything that
level ships with and nothing out of the ordinary that way the setup is very very simple and we're really focused around the functionality that we are trying to get so i will actually even reuse the
example component that ships with level so if we go inside resources j/s components here's the example component so of course we know that we're going to need that drop zone so let's go ahead
and delete everything from this component and let's go ahead and import that drop zone so right after the script tag will say import drop zone from drop zone so this will bring in this package
that we need so now when our component is mounted i want to go ahead and new up drop zone so – new up drop zone let's make a new data property so say data it's a function that returns an object
and instead of here let's have drop zone and initially we'll set that equal to null so again when the component is mounted let's go ahead and grab this dot drop
zone and then let's go ahead a new up drop zone now drop zone to new it up you're going to need two things the first thing is our drag and drop area the area that we want our application to
go ahead and designate as the drag and drop area so typically for this you could do it as an ID but the nice thing with using view is that we have this reference so let me show you how
something like that would work instead let's go ahead and create a div and inside the diff we'll add this ref attribute again ref is just a reference to a particular tag using view so let's
call it image upload so now how do we access this particular div well inside of here we can say this dot dollar sign refs as in references dot image upload so now we are passing this particular
div into our drop zone and like I said it needs a second thing and what that is is just simply an object that has some settings or options for this particular drop zone plugin now there are a ton of
setting but the only thing that is actually required is a URL and the URL that is required is the URL that it's actually going to send the pictures to now of course we don't have that yet but
let's go ahead and add one anyway we'll add it eventually but right now it doesn't exist yet so we'll say the URL is gonna be slash images so it's gonna perform
a post request to slash images and that's it that's really all we need I did forget the common air let's add it back in so now that we have this going that's basically it in terms of setup
for drop zone let's go ahead and style this a little bit so we can actually see what's inside of it so let's add some classes here now level of course ships with bootstrap so that's what we're
gonna be using for this so let's make this a row and we'll justified content Center a margin bottom of three so now inside of here let's add some instruction for our users so we'll add a
new div and we'll say drop image and then we'll put an S in parenthesis here so drop your images right here and this one let's also a little bit so we'll give it a glass of
cold 12 that way it takes up the whole entire screen I will say BG dark so we give it a nice dark background with some white text so text white rounded corners let's give it some top and bottom
padding of three as well as some margin top and bottom of two that way it gets separated and finally let's go ahead and Center this text so now through all of this we are actually not using this
component so let's jump to the Welcome that blade that PHP file I'll delete all these styles here as we don't really need them but what I do need to do is go ahead and import our compiled file so to
do that let's add a new link and the href is gonna be using mix so we will say slash CSS slash app that CSS again this is all set up stuff level related not quite related to this particular
lesson but it's always good to review all of the steps necessary all right so let me go ahead and clear all of this out I don't need any of it and so inside of here this is where we're actually
gonna use our component so let's go ahead and use example component now this comes registered for us right out of the box so this will really just work but the last thing I do need to do is go
ahead and add a reference to our actual JavaScript file so to do that we'll say script and script will have a source of we could use mix again and we could say alright mix grab our /j s slash app dot
j s and finally because we are using view of course we need to designate this as an ID of app so we'll say ID okay so with any luck this should all be working in Chrome I'll hit refresh and there we
go so we have our drop images here and we are basically done for the JavaScript side of this so let me actually pull open the network tab so notice how there is no network activity right now so
let's go ahead and drop some images in here and let's see what kind of activity we get in the network tab so I actually have some sample images that we can use to drop in this area and checking out
the network tab again I want to show you what it surely does so let me get out a full-screen mode and down here there it is so these are
the sample images that I have to work with they're just simple images you can use any images you can google for some images or take your own images alright so I will drag just the first one and
drop it in there and the first thing you'll notice is we do get a preview as well as how big it is and the name of the file but over here on the network tab we see this images and of course
it's red because level actually said not found HTTP exception so it actually did try to add that image using that post route so let's go ahead and make that actually work so let's take the fastest
path there I'll close everything up and let's open up web dot PHP so we know that we are hitting a post route of slash images and then this needs to go to some sort of controller so let's go
ahead and create and uploads controller and what is the correct action for this well we are going to be storing so let's hit the store method so let's jump back to the terminal and let me open up a new
tab and CD into that same project so it's called image upload and then let's go ahead and run PHP artisan make controller uploads controller and let's go ahead and visit that in phpstorm
so back to PHP uploads controller and let's go ahead and create that store method okay so inside this store method what do we actually need to do well if you actually watch the lesson on how to
upload a single image this is actually going to be very very similar but of course we're going to be handling multiple images so let's go ahead and grab all of our images so how do we do
that reach into the request and then we can use this file method that level provides for us and then all we have to pass in is the key and the key that dropzone actually uses is simply just a
file so this images now contains all the images that were dropped into drop zone and what they are wrapped around is an upload file so let me go ahead and just
die and dump images just to show you what is actually being saved under images because I think it's important for you to see that so I will go ahead and refresh this page so
everything clears out and let me drop that same file back in there and now this time when I go over here we see that we get an error of CSRF token mismatch all right so this is going to
be something that you're going to run into as you're doing a lot of level development so you've got two choices here you can either go ahead and submit a full form where you can actually pass
in a CSRF token or you can use the API instead because we really don't need a CSRF token for this particular example so the easiest fix for this would be to actually go to my web dot PHP file and
grab this route out of here and let's actually put it in the API route so if you ever run into this issue of a CSRF token that's because we're trying to submit really an API call but using the
web so now that we've changed this any routes inside of API as you may know actually get a prefix of API so we're going to have to change our example component and now our address is not
gonna be slash images but it's gonna be slash API slash images okay so with that change let's go ahead and do this one more time I'll grab the same one drop it in and now under images we get this
uploaded file class which is really what we were looking for from the beginning now because our file is wrapped up in this upload file we've got some leverage in terms of how to move the file and
things like that so this is actually something that level does for us out of the box and it makes it very simple to handle file uploads so back in my uploads controller all we really need to
do is grab each one and move them into place now this right here is really going to be returning either a single item or an array of items so what I can actually do is go ahead and wrap the
whole thing in a collection as a side note if you are not familiar with collections definitely check out the whole series that we have here on coders tape in collections they are extremely
powerful you're going to get to see a little bit of that right now so I will actually do the following there's a collection method and that's inside illuminate support
collection notice that it got imported up here at the top and there is a wrap method inside of them and what rap actually does is it will wrap anything that you put in a collection now if that
item is already a collection then it doesn't re rap it it's smart enough to know not to do that but now images is actually a collection and this is gonna allow us to do something like this
collections have special methods and one of them is each and each is very useful whenever you need to iterate through each of the items and perform certain actions so this will accept a callback
and in each one will have a particular image so instead of having a collection of images inside of this callback will actually have one single image and now the fastest path to get this working is
just just simply take our image and then move it and where we're gonna move it to what if we just move it to our public path just straight into the public path we can change this but for now that will
work so let me go ahead and just give it some sort of name here we'll just say ABC and then we need the extension of our file so I know in this particular case is going to be a JPEG file but we
don't know that so how can we possibly get that well because it is wrapped in a file upload class we actually have access to a very cool method which gives us the extension of the file that the
user uploaded so in the case they uploaded a PNG or a JPEG or any other format that we accept this will still work it doesn't matter what the format is and that method is the following so
let's go ahead and put a period at the end of this and then let's go ahead and concatenate the following we'll say image get clients original extension I know that that's quite a big method name
but it really does explain what it actually does it simply returns the original extension that the client provided for us so with that we are basically good to go at this point we've
moved our file into the right place so let me go ahead and open up my public directory and as you see here these are the files that are currently less sit in there so with any luck if we run
chrome now I'll refresh I'll move this file in here and then let's go ahead and go back to phpstorm and now if we come back here it should have appeared here under public we must
have made a mistake here on the code so what it is is oh I see it so one of these parentheses actually have to be right after this so public path is a single and then as a second argument
then we pass that it all right no big deal let's go ahead and try this one more time I'll pull that in and now we'll head back to phpstorm there we go ABC dot jpg was saved and there is our
actual image so just like that technically we are good to go that would work now of course you probably wouldn't want to put them straight into the public path so why don't we create our
own directory now you can create a directory on the fly but I'm going to show you the more dynamic way of doing it the thing about move is that the directory has to already exist you can't
just simply designate a directory name and not have a directory name it will fail so you need to create the directory but then there's another problem if the directory already exists then you can't
create the same directory with the same name that will also give you an error so we actually have to check does this directory exist and then if it doesn't then we create it otherwise we can move
on so we can say that quite simply what have we said if so there is a PHP function called is underscore dir for it is directory but we don't want to find out if it is a directory we want to find
out if it's not so we can negate that with just an exclamation so what is the path that we are looking for well we know we're going to be looking inside public path and how about if we save all
of our images in a subdirectory of images so if that is not a directory then let's go ahead and use mkdir to actually make this directory so we'll go back into our public path and we'll make
that directory now for permissions on this let's go ahead and give it a permission of 0 7 7 7 that way we can save into that same directory that we just created if you don't put that mode
in there you won't have read right access into this new created directory so it's important that you put the mode of zero seven seven seven so now let's go ahead and do the exact same
thing but of course I don't want to just go to slash public path I actually want to go to images all right so let's give that a go now back to Chrome hit refresh one more time we'll drop that image in
back to phpstorm and sure enough now we have this new images directory and inside of there we have ABC dot jpg okay so so far so good but of course what would happen if we put two files right
now well they would have the same name and so they would basically replace each other so that's definitely not what we want to do we don't want a hard code ABC but rather we actually want to have a
unique name now we can't trust a user's name of the actual file as a unique name because well we don't know what they're actually going to name their and the odds of two people naming two
different files the exact same name aren't actually quite high so we don't want to run into any issues with duplicate names because that would replace images so all of a sudden John's
images are the same as Mary's images so we don't want that to happen so to do that let's go ahead and establish a base name so we'll say alright my base name is gonna be we're gonna use STR let's
eliminate support STR random and then let's just go ahead and keep the defaults for random now do note that STR did get imported up here at the top alright so we have a base name and then
to this base name let's go ahead and create our actual name original and this is gonna be the file name that we're going to use so let's start with base name and then we'll go ahead and add the
period so we need a period that way we can actually add the images original client name so this will basically give us a random name with the correct extension so now the second parameter
here we can replace that with simply original alright so let's give that another go hit refresh drop the same image in back to phpstorm now notice that we have a random name
with JPEG and of course our image is still inside so pretty cool so now we're actually uploaded bunch of images and the names won't actually conflict so you may have already been thinking it
doesn't matter how many images we upload if we don't keep track of that in our database then it's gonna be hard for us to create any sort of gallery so let's go ahead and take care of that very
simple to do let's go ahead and create a model and a migration so we'll say PHP artisan make model we'll call it image upload and go ahead and give me a migration at the same time so back to
phpstorm so let's go ahead and find that create image uploads table and let's add a new field here as a string and this is gonna be for original that way we can actually
save the original file name so that'll work for now but as I've done many times before I want to go ahead and turn off mass assignment so we'll say guarded equals an empty array and if you add
this line again that turns off mass assignment because I just want to create a record so right after we move the file let's go ahead and call that image upload and then let's go ahead and
create a new record and the record is gonna be something like original and that's gonna be set equal to original now notice that image upload did get imported up here at the top very
important otherwise it won't find that class all right so let's go ahead and set up a very quick database so to do that I'm gonna use SQLite so we can do touch database directory database dot
SQLite but if you are in Windows this is not gonna work so don't use touch instead you can use something like vim or VI or anything like that we just need to create an empty file called database
dot SQLite inside the database directory so I'll actually use vim and I'm not gonna type anything I'm just gonna hit escape : WQ and now that file is created for us so back in phpstorm the only
thing we need to do is go ahead and change our environment so that instead of using MySQL we're gonna use SQLite and then we'll delete everything else from there and now let's run PHP artisan
migrate and there we go we have a database in place so let me jump over into PHP artisan tinker and right now if we pull open image upload all nothing there
totally empty all right so I'm gonna exit out of that let's go back to Chrome and let's upload our image one more time I'll drop it in there and now let's go back in to tinker again and let's run
the same command and now we do have an image so pretty cool so now we have an original name right here but we know that this is only the name of the file it is still inside our images directory
so I do like to save those sub directories inside the database so simple fix for that all we need to do is make sure that when we save our original we actually do tag on this images so
we'll say images and then original and we will need a slash right there so that way now we have a nice full path that we can use to retrieve these images so this is it I mean this is the basic
implementation of doing that if you wanted to add multiple images at the same time let's go ahead and grab five of these images I'll drop them all in at the same time notice that they all
showed up and now we go back to phpstorm notice that all of my images are there and of course in tinker if we do that one more time we've got all of our images in there so this is it this is
the basic implementation of how to actually get multiple images uploaded at the same time now if you stick around with me for a little longer we're gonna take this to the next level and kind of
turn it into a very simple gallery so let's go ahead and tackle that now the first thing about galleries is of course we're going to need to resize these images we're going to need to create
thumbnails so we can do all that on the fly but we're going to need a special library now the library that I like to use is intervention image library and it is fantastic I've actually talked about
it already during the other image uploading lesson that we did so let's go ahead and just use it again if you want a little bit more review on this particular topic definitely check out
that other lesson because we go into a lot of details of the intervention image package but to pull it in all we need to do is go ahead and run composer require intervention slash image and this is the
de-facto PHP package for image manipulation I think just about everybody uses the same package and now it is complete so let's jump back to phpstorm and so yes we're
going to move our file but before we do that let's go ahead and create a thumbnail so the first thing we're going to need is of course we're gonna need a name for our thumbnail now I do want to
reuse our base name so I will actually copy this line and let's go ahead and call this thumbnail and we'll still use our base name but let's go ahead and slap on underscore some that way the
images get sorted equally but we have this underscore thumb and the original file so we'll have both files in place so to use the image intervention package we're going to go ahead and call image
now this is the one that you want you want intervention image façades so that's the one that you're looking for now that did get imported up here at the top right here so make sure that that
line is up there otherwise again it won't find the image library so using the image library let's go ahead and make an image and so what is the data for our image well of course our actual
image so we can take the entire image and just pass it straight into image so then to create our thumbnail I like to use the method fit now there are literally about 50 or so methods that
you can use but fit will actually crop and resize at the same time it's quite useful for things like thumbnails because you're gonna want to make probably a square image and in this case
we're gonna make a square image that's 250 pixels by 250 pixels now I don't care what aspect ratio my user uploaded I still want it to be a perfect square so fit is perfect for that
so we'll say fit and as a first argument will be the width and as a second argument would be the height so 250 and 250 as I said and then we'll go ahead and save this new image so let's go
ahead and save it to our public path again under slash images slash and then our thumbnail so as you may have noticed we've reused this slash images quite a bit at times so good refactor here would
be to extract this into its own variable a little bit outside of the scope of this particular tutorial but definitely a good thing to note so that way when you're actually doing
for a production code make sure you don't repeat this over and over but rather extract it to its own variable we'll leave it like that for now that way it's really explicit so that's it
now we're gonna make two images whenever we upload so I'll actually do is I will go ahead and delete all of these images from my images directory and then on top of that we now need to save this new
thumbnail into our database so back in the migration we're going to have this original strength but let's also create a new one for thumbnail so now that we have that of course our migration is out
of sync with the database so let's go ahead and flush our entire database right now we can do that by saying PHP artisan migrate fresh so that will drop all the tables and then migrate the
database for us so now we can go back to phpstorm and we need to add that into our actual create function so we're gonna have the original but on top of that of course we're gonna have the
thumbnail so that way they're both saved alright let's give this a go I will hit refresh here I'll throw in two images this time throw both of those in and now let's visit tinker again and then let's
run the same command again and there we go so now we've got our original image and then we've got the thumbnail which has the same file name except that it ends in underscore thumb now let's check
out this file that way you see what fit did for us back to phpstorm open images so we have our original file which looks like this and then we have our thumbnail so our thumbnail is perfectly square and
it's 250 pixels by 250 pixels so it's perfect for us to actually show this as a gallery so let's take care of that right now let's go back to the Welcome and we're going to need our actual
images so up until this point welcome actually gets loaded automatically if we go to the web dot PHP file notice how a view is simply returned out of here but we do have this uploads controller so
what are we reuse all of that so what I'll actually want to do is instead of a call back let's go ahead and use the uploads controller and then let's hit the index method so in my uploads
controller let's add a new function public function index and so we need to fetch all of our images at this point so say images equals image upload but what I want here
is I want them to be in reverse chronological order that way the latest upload is up front so to do that we can call latest and then we can call get so this will get us
all of the images available in our database so then all we need to do is return the same view that's gonna be the welcome view but now we do need to pass in this data we need images to be in
there so let's go ahead and pass in images as a data property so now if we go back to Chrome and we refresh everything should work exactly the same because we haven't made any changes but
now in our welcome view we now have access to all of our images so we can say for each images as image and then we'll say end for each so for each of these images of course I'm going to want
to have an image tag so let me actually wrap all of this inside of a row that way they're nice and grouped together and then each of the images will be a column of two so we'll add a new div
with column of two and this is given some margin bottom of four just to separate them a little bit so inside of here we'll have our image and the source is going to be image thumbnail and then
as a class let's go ahead and just give it a class of width of 100 so with 100 that way it gets resized perfectly to our browser okay back to Chrome hit refresh and there we
go so we have our nice gallery going on let me go ahead and close this so notice that everything is bumped to the left that's because this needs to be wrapped in a container
this is bootstrap stuff nothing to do with this actual project but now you see that our images are inside if we were to upload some more images I'm gonna add this one I'll hit refresh and there we
go so we have our images the nice thing would be if we can click them and view the full resolution file so we could do that by just wrapping all this in another anchor tag so say anchor and
where are we going to go let's just go to image original and then inside of here we'll actually have the image so now we can click on them and sure we can go to each one now of course you
can get super fancy with this and have some sort of modal that way the image doesn't leave the page but again we're focused around just uploading images resizing them and getting them into a
gallery style so this is pretty much working at this stage just as a finishing touch I want to add a delete button I want a way for us to actually delete each of these images now to
delete our images we cannot simply just create a link and the reason for this is because due to restful controllers we actually need to submit a delete request to our server
that way we can reuse that same exact you arrived but to do that we actually need to submit a form so let's go ahead and create a form and the action is going to be to slash emerges and then
the method is going to be post but we're going to override that because we actually want the method to be a delete request so if you've been around kotor state long enough you know at this stage
that you can only submit and get or post requests so a delete request actually needs to be faked it's not part of the spec so we're gonna actually submit a post request but if we add this method
of delete in that case letter what's gonna know that this is a delete request the other thing we're going to need is of course a CSRF token because we're not hitting that API so let's go ahead and
use that CSRF token and then let's add a button my button will say delete and for classes on this one as you say it's small it's gonna be a button with a button outline of danger all right let's
see what that looks like there we go yeah it's gonna need a little bit of margin let's try margin top two there we go so when we hit our button of course I want to delete the image but I also want
to delete the thumbnail the original and everything from our database so it is a little bit more involved in just deleting the record from the database so whenever this happens of course we're
going to need that route so back in my web dot PHP I'll create a new delete route for slash images and this is gonna hit the uploads controller at the destroy method alright so let's go to
the uploads controller and then down here at the very end I actually don't want to die and dump that anymore that's from a previous section go ahead and delete that and let's add a new
public function here for destroy so how do we destroy all of this well it would be a lot simpler if we actually had our image which we can so let me show you how instead of just hitting slash images
let's actually hit slash images slash and then the ID that we're trying to delete so we can grab that by saying image ID and then on top of that in our routes of course we are not just slash
images but we are slash images and then in curly brackets we'll say image upload this is route model binding it's one of those magical things with level that I use all the time so now simply by type
hinting image upload in our controller Lehrer will actually give us the instance of image upload so we'll go into the database and fetch the correct image upload for us and give it to us
right inside this we don't have to fetch anything it's all done for us magically pretty awesome stuff so now what do we need to do in here sometimes when I'm not sure exactly how
the code is gonna go a good place to go is to go ahead and add comments for each of the steps that you need to do so the first step is we know we need to delete the files write both the original and
the thumbnail then we know we're going to need to delete the record from the database and lastly we're gonna need to redirect we need to send the user back somewhere so the redirect part that's
actually quite simple because all we need to do is return a redirect and let's just send them back to our home page so this will actually work at this point if we hit refresh
here and I just hit delete notice that it actually goes but it comes right back because of course we're not deleting the record but at least we know that that last step is done that's the easy one so
how do we delete the files well we can use the file facade so we'll say file that's going to be under illuminate support facades and make sure that that gets imported up here at the top and
here it is make sure you add that line to your code otherwise file will not be found so we add that line and then we can say delete and to delete we can actually pass an array of files
that we're looking to delete we're luckily for us we can use public path again and then the first public path is going to be image upload at original and then the same thing but it's gonna be
thumbnail okay so that takes care of our files and finally we need to delete the record from the database so that's simple enough as well we just say image upload delete and that would
delete that record from the database so alright so take a look down here obviously we have six images three originals and three thumbnails so let me go into Chrome and I will delete this
last one right here I'll hit the delete button notice that it went completely away and then if we check back to phpstorm now we're down to just four images let's go ahead and delete another
one and if we come back here we're down to just the thumbnail and the original file but of course all the other functionality still works let me bring in a couple more images bring all these
drop them in there so we have all of these images now if we check back with phpstorm check out the list over here everything's working and of course we can delete and then we can click on one
image and actually check out the full resolution image so that's it that's going to complete this lesson I know it's a little bit lengthy but good job sticking around because now you know
exactly how to make a gallery from scratch using view and levo great job I'll catch you on the next one
As one of the most requested tutorials, in this lesson, we are tackling an example of multiple image uploads. We will also resize them to generate thumbnails and build a very basic image gallery where you can preview the full resolution images.
For the best experience, follow along in our interactive school at https://www.coderstape.com
Other Related Video
DigitalOcean Referral
https://m.do.co/c/7dce5364ef4d
Hit us up on Twitter with any questions or comments @codertape (https://twitter.com/CodersTape)
About This Course
Ready to get started on your path to Laravel Artisan? In this series, we are breaking down all of the basics of Laravel to get you comfortable using the world’s most popular PHP framework. Let’s get started!