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' => '[email protected]'));
Route::post('/addimage', array('as' => 'add_image_to_album','uses' => '[email protected]'));
Route::get('/deleteimage/{id}', array('as' => 'delete_image','uses' => '[email protected]'));

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 rulesarray. 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