Now we need to create a photo upload form. We’ll upload the photos and assign them to the albums. Let’s first set the routes; open the routes.php
file in the app
folder and add the following code:
Route::get('/addimage/{id}', array('as' => 'add_image','uses' => 'ImagesController@getForm')); Route::post('/addimage', array('as' => 'add_image_to_album','uses' => 'ImagesController@postAdd')); Route::get('/deleteimage/{id}', array('as' => 'delete_image','uses' => 'ImagesController@getDelete'));
We need a template for the photo upload form. To create that, save the following code asaddimage.blade.php
in the app/views/
directory:
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width,initial-scale=1.0"> <title>Laravel PHP Framework</title> <!-- Latest compiled and minified CSS --> <link href="//netdna.bootstrapcdn.com/bootstrap/3.0.0-rc1/css/bootstrap.min.css" rel="stylesheet"> <!-- Latest compiled and minified JavaScript --> <script src="//netdna.bootstrapcdn.com/bootstrap/3.0.0-rc1/js/bootstrap.min.js"></script> </head> <body> <div class="container" style="text-align: center;"> <div class="span4" style="display: inline-block;margin-top:100px;"> @if($errors->has()) <div class="alert alert-block alert-error fade in"id="error-block"> <?php $messages = $errors->all('<li>:message</li>'); ?> <button type="button" class="close"data-dismiss="alert">×</button> <h4>Warning!</h4> <ul> @foreach($messages as $message) {{$message}} @endforeach </ul> </div> @endif <form name="addimagetoalbum" method="POST"action="{{URL::route('add_image_to_album')}}"enctype="multipart/form-data"> <input type="hidden" name="album_id"value="{{$album->id}}" /> <fieldset> <legend>Add an Image to {{$album->name}}</legend> <div class="form-group"> <label for="description">Image Description</label> <textarea name="description" type="text"class="form-control" placeholder="Imagedescription"></textarea> </div> <div class="form-group"> <label for="image">Select an Image</label> {{Form::file('image')}} </div> <button type="submit" class="btnbtn-default">Add Image!</button> </fieldset> </form> </div> </div> <!-- /container --> </body> </html>
Before creating the template, we need to code our controller. So, save the following code asImageController.php
in the app/controllers/
directory:
<?php class ImagesController extends BaseController{ public function getForm($id) { $album = Album::find($id); return View::make('addimage') ->with('album',$album); } public function postAdd() { $rules = array( 'album_id' => 'required|numeric|exists:albums,id', 'image'=>'required|image' ); $validator = Validator::make(Input::all(), $rules); if($validator->fails()){ return Redirect::route('add_image',array('id' =>Input::get('album_id'))) ->withErrors($validator) ->withInput(); } $file = Input::file('image'); $random_name = str_random(8); $destinationPath = 'albums/'; $extension = $file->getClientOriginalExtension(); $filename=$random_name.'_album_image.'.$extension; $uploadSuccess = Input::file('image')->move($destinationPath, $filename); Image::create(array( 'description' => Input::get('description'), 'image' => $filename, 'album_id'=> Input::get('album_id') )); return Redirect::route('show_album',array('id'=>Input::get('album_id'))); } public function getDelete($id) { $image = Image::find($id); $image->delete(); return Redirect::route('show_album',array('id'=>$image->album_id)); } }
The controller has three functions; the first one is the getForm()
function. This function basicallyshows our photo upload form. The second one validates and inserts the data into the database. We’ll explain the validating and inserting functions in the next section. The third one is the getDelete()
function. This function basically deletes the image records from the database.
Validating the photo
Laravel has a powerful validation library, which has been mentioned in this book many times. We validate the data in controllers as follows:
$rules = array( 'album_id' => 'required|numeric|exists:albums,id', 'image'=>'required|image' ); $validator = Validator::make(Input::all(), $rules); if($validator->fails()){ return Redirect::route('add_image',array('id' =>Input::get('album_id'))) ->withErrors($validator) ->withInput(); }
Let’s examine the code. We defined some rules in array
. We have two validation rules in the rules
array. The first rule is as follows:
'album_id' => 'required|numeric|exists:albums,id'
The preceding rule means that the album_id
field is required (must be posted in the form), it must be a numeric value, and must exist in the id
column of the albums
table as we want to assign images toalbums
. The second rule is as follows:
'image'=>'required|image'
The preceding rule means that the image
field is required (must be posted in the form) and its content must be an image. Then we check the posted form data using the following code:
$validator = Validator::make(Input::all(), $rules);
The validation function needs two variables. The first one is the data that we need to validate. In this case, we set that using the Input::all()
method, which means we need to validate the posted form data. The second one is the rules
variable. The rules
variable must be set as an array as shown in the following code:
$rules = array( 'album_id' => 'required|numeric|exists:albums,id', 'image'=>'required|image' );
Laravel’s validation class comes with many predefined rules. You can see the updated list of all available validation rules at http://laravel.com/docs/validation#available-validation-rules.
Sometimes, we need to validate only specific MIME types, such as JPEG, BMP, ORG, and PNG
. You can easily set the validation rule for this kind of validation as shown in the following code:
'image' =>'required|mimes:jpeg,bmp,png'
Then we check the validation process using the following code:
if($validator->fails()){ return Redirect::route('add_image',array('id' =>Input::get('album_id'))) ->withErrors($validator) ->withInput(); }
If validation fails, we redirect the browser to the image upload form. Then, we show the rules in the template file using the following code:
@if($errors->has()) <div class="alert alert-block alert-error fade in"id="error-block"> <?php $messages = $errors->all('<li>:message</li>'); ?> <button type="button" class="close"data-dismiss="alert">×</button> <h4>Warning!</h4> <ul> @foreach($messages as $message) {{$message}} @endforeach </ul> </div> @endif
Assigning a photo to an album
The postAdd( )
function is used for processing the request to create a new image record in the database. We get the author’s ID using the following previously mentioned method:
Auth::user()->id
Using the following method, we assign the current user with the blog post. We have a new method in the query as shown in the following code:
Posts::with('Author')->…
We’ve defined a public Photos ()
function in our Album model using the following code:
public function Photos(){ return $this->hasMany('images','album_id'); }
The hasMany()
method is an Eloquent function for creating relations between tables. Basically, the function has one required
variable and one optional variable. The first variable (required
) is for defining the target model. The second, which is the optional variable, is for defining the source column of the current model’s table. In this case, we store the albums’ IDs in the album_id
column in theimages
table. Because of that, we need to define the second variable as album_id
in the function. The second parameter is only required if your ID doesn’t follow the convention. Using this method, we can pass our albums’ information and assigned images’ data to the template at the same time.
ALet’s have a quick look at the image-listing section of code in our template file, which is located in resources/views/ album.blade.php
:
@foreach($album->Photos as $photo) <div class="col-lg-3"> <div class="thumbnail" style="max-height: 350px;min-height: 350px;"> <img alt="{{$album->name}}" src="/albums/{{$photo->image}}"> <div class="caption"> <p>{{$photo->description}}</p> <p><p>Created date: {{ date("d F Y",strtotime($photo->created_at)) }} at {{ date("g:ha",strtotime($photo->created_at)) }}</p></p> <a href="{{URL::route('delete_image',array('id'=>$photo->id))}}" onclick="return confirm('Are yousure?')"><button type="button" class="btnbtn-danger btn-small">Delete Image</button></a> </div> </div> </div> @endforeach
the syntax highlighting is not showing correctly
sorry for late reply ! can you please tell me where is not showing correctly ?
may be this ” & gt; ” it showing instead of ” > “
ok thanks i will fix it
thanks i have fixed that ! i am now just using pre tag simple solution :)
Hello
I have gone with the creation of this project one line at a time, I chose to name the model (Image) rather than (Photos) to be consistent, and I get this error
BadMethodCallException in Builder.php line 1999:
Call to undefined method IlluminateDatabaseQueryBuilder::Image()
when I try to track it, it ends in this line:
$albums = Album::with(‘Photos’)->get();
return View::make(‘index’)
->with(‘albums’,$albums);
I tried to name it with(appImage) but no luck, can you help me out please?
by the way, you’re doing an excellent job there, thanks so much.
Hello, thanks for this fine tutorial. However, it seems not to fit to the Laravel 5.1 directory structure. Is there an update ?
i will upadate it as soon as possible ! now busy in projects :(
Command will generate a migration file underapp/database/migrations CMD:php artisan make:migration create_albums_table –create=albums –table
sorry but what’s your point here ?
Over all its the good tutorial for beginners… I think you have to double check your commands before posting…Thats the point …
ok thanks ! will be doing from next time !
agree it does not say how to create a migration, beginners won’t understand how to create a migration
thanks for the album gallery laravel project. I think there is Albums Object missing in :
Albumscontroller::getAlbum($id)
and view: album.blade.php where you foreach through the object albums as others.
you are not providing the obj. albums in Albumscontroller::getAlbum($id).
let me see that btw ! thanks 4 pointing it out
How did you solve that ?
public function getAlbum($id)
{
$data[‘album’] = $this->album->with(‘Photos’)->find($id);
$data[‘albums’] = $this->album->all();
return view(‘album’)->with($data);
}
Obs. I’m using depency injection on __construct(). if u dont replace $this->album to Album::
open up your terminal, navigate through your project folder, and run the following command: “where is the command ?”
you are missing this command “php artisan make:migration create_albums_table”
Please, can you send me the source code? [email protected]
The code is included in the tutorial.
I have this error when I want to create an album
TokenMismatchException in VerifyCsrfToken.php line 67:
Add this to your form..
Great tutorial. Have you uploaded the code anywhere?
So many derelict Laravel tutorials out there.
It would be faster just to make a pivot table from albums and photos.
Second thing, if you are talking about albums and photos in plural, than update this tutorial to show people how to upload multiple images, not just one.
And third thing… we have Laravel 5.3 now ;)
i have an error
ErrorException in d17e4d0327979a8a446079b4be560aa37d15c74a.php line 66:
Undefined variable: albums (View: album.blade.php)
Please Help. Class ‘BaseController’ not found
Thank you very much!
I could adapt it to laravel 5.4 without problems
Can you to published in version 5.4?
Sure, Here: https://github.com/YouDevs/Gallery-System-Laravel-5.4
Hello everyone,
I am looking to create a Photo Gallery in the employer I already installed and that works well.
For this gallery I followed the following tutorial:
https://dunebook.com/tutorial-creating-a-photo-gallery-system-with-laravel/
But I find myself with a mistake and also can not open the link of the function.
“Whoops, looks like something went wrong. 1/1 FatalErrorException in Handler.php line 25: Uncaught TypeError: Argument 1 passed to AppExceptionsHandler::report() must be an instance of Exception, instance of Error given, called in /home/www/test.com/laravel/vendor/compiled.php on line 1720 and defined in /home/www/test.com/laravel/app/Exceptions/Handler.php:25 Stack trace: #0 /home/www/test.com/laravel/vendor/compiled.php(1720): AppExceptionsHandler->report(Object(Error)) #1 [internal function]: IlluminateFoundationBootstrapHandleExceptions->handleException(Object(Error)) #2 {main} thrown 1. in Handler.php line 25”
And I do not understand how to correct that.
Thanks to your helpers,
You say to put the first controller in:
app/http/controllers/
and the second one in:
app/controllers/
shouldn’t the controllers go in one place?
On the second page you write to out the ImageController (singular) to app/controler, then oon the third page you write to “Open the ImagesController.php file which is located in app/http/controllers/” but firstly there’s no controller there, and secondly is that supposed to be ImageControler (singular) or ImagesControler (plural)?