Basic Image Management Part 3

Access all tutorials in sprocket icon.

July 29, 2015 from author Bill Keck.

Basic Image Management

Part 1.

Part 2.

Part 3.

The Edit Method

Obviously edit and delete are not going to do anything yet. So let’s work on edit first. We’ll start with the controller method:



public function edit($id)
{

   $marketingImage = Marketingimage::findOrFail($id);

   return view('marketingimage.edit', compact('marketingImage'));
}

Again we’re using the findOrFail method and sending the object along to the view. We need it because we want to pre-populate our form with the appropriate values from the data record.

The Edit View

Now let’s change views/marektingimage/edit.blade.php to the following:

Gist For Edit view

Ok, some things to note about this. We don’t allow the user to edit the image names or paths. The reason for this is that we want them to delete the record and start over. Otherwise, it gets complicated where we have to rename the files that are saved and that’s beyond the scope of this tutorial. So I did this for simplicity.

So what’s different here about the form, besides the fact that we’re using less fields, we’re using form model binding in the form helper:



{!! Form::model($marketingImage, ['route' => ['marketingimage.update', $marketingImage->id],
'method' => 'PATCH',
'class' => 'form',
'files' => true]
) !!}

Our model instance, $marketingImage is bound to the form so the fields will pre-polulate. You can also see that we specify $marketingImage->id, so we can send that to the controller method and edit the correct record.

The method is set to PATCH, and this is automatically converted because PATCH is not supported by HTML. We also set ‘files’ to true so we can send the files along.

Everything else we pretty much covered and is nothing new. We do have a delete button at the bottom, in case the user wants to delete instead of edit.

Everything else, we pretty much covered before.

In workflow, you would probably move onto the update method in the MarketingImagesController. But I’m going to create a request class first to handle the update scenario.

EditImageRequest

The difference between validation on create and update is that when you create an image, the image file is required, whereas when you update, it is not. I decided for simplicity and clarity to create a separate request class named EditImageRequest, rather than put it in one request class.

The problem I ran into was I didn’t know how to make it conditional on which method the class was being injected into, so I went this route. Alternatively, I could have passed along a hidden field which identified the form, and put controlling logic on that, if from the create form, make the image required etc., but I just decided it’s so simple to create the separate class, I would just do that.

So from your command line run:



php artisan make:request EditImageRequest

Then set the authorize method on that class to return true and change the rules method to the following:



public function rules()
{
   return [
       'is_active' => 'boolean',
       'is_featured' => 'boolean',
       'image' => 'mimes:jpeg,jpg,bmp,png | max:1000',
       'mobile_image' => 'mimes:jpeg,jpg,bmp,png | max:1000'
   ];
}

We already covered the rules in the earlier section.

The Update Method

So now let’s move on to our update method on the MarketingImageController:



public function update($id, EditImageRequest $request)
{
   $marketingImage = Marketingimage::findOrFail($id);

   $marketingImage->is_active = $request->get('is_active');
   $marketingImage->is_featured = $request->get('is_featured');

   $this->formatCheckboxValue($marketingImage);
   $marketingImage->save();

   if ( ! empty(Input::file('image'))){

       $destinationFolder = '/imgs/marketing/';
       $destinationThumbnail = '/imgs/marketing/thumbnails/';

       $file = Input::file('image');

       $imageName = $marketingImage->image_name;
       $extension = $request->file('image')->getClientOriginalExtension();

       //create instance of image from temp upload
       $image = Image::make($file->getRealPath());

       //save image with thumbnail
       $image->save(public_path() . $destinationFolder . $imageName . '.' . $extension)
           ->resize(60, 60)
           // ->greyscale()
           ->save(public_path() . $destinationThumbnail . 'thumb-' . $imageName . '.' . $extension);

   }

   if ( ! empty(Input::file('mobile_image'))) {

       $destinationMobile = '/imgs/marketing/mobile/';
       $mobileFile = Input::file('mobile_image');

       $mobileImageName = $marketingImage->mobile_image_name;
       $mobileExtension = $request->file('mobile_image')->getClientOriginalExtension();

       //create instance of image from temp upload
       $mobileImage = Image::make($mobileFile->getRealPath());
       $mobileImage->save(public_path() . $destinationMobile . $mobileImageName . '.' . $mobileExtension);
   }

   flash()->success('image edited!');
   return view('marketingimage.edit', compact('marketingImage'));
}

So let’s start with the method signature:



public function update($id, EditImageRequest $request)
{

You can see we’re pulling in an instance of the correct request object.

Then we findOrFail on the model record, so we can set the values from the request instance. We format the checkbox value and save:



   $marketingImage = Marketingimage::findOrFail($id);

   $marketingImage->is_active = $request->get('is_active');
   $marketingImage->is_featured = $request->get('is_featured');

   $this->formatCheckboxValue($marketingImage);
   $marketingImage->save();

If the primary image is not empty, we update it:



if ( ! empty(Input::file('image'))){

   $destinationFolder = '/imgs/marketing/';
   $destinationThumbnail = '/imgs/marketing/thumbnails/';

   $file = Input::file('image');

   $imageName = $marketingImage->image_name;
   $extension = $request->file('image')->getClientOriginalExtension();

   //create instance of image from temp upload
   $image = Image::make($file->getRealPath());

   //save image with thumbnail
   $image->save(public_path() . $destinationFolder . $imageName . '.' . $extension)
       ->resize(60, 60)
       // ->greyscale()
       ->save(public_path() . $destinationThumbnail . 'thumb-' . $imageName . '.' . $extension);

}

Then we do the same check on the mobile image:



if ( ! empty(Input::file('mobile_image'))) {

   $destinationMobile = '/imgs/marketing/mobile/';
   $mobileFile = Input::file('mobile_image');

   $mobileImageName = $marketingImage->mobile_image_name;
   $mobileExtension = $request->file('mobile_image')->getClientOriginalExtension();

   //create instance of image from temp upload
   $mobileImage = Image::make($mobileFile->getRealPath());
   $mobileImage->save(public_path() . $destinationMobile . $mobileImageName . '.' . $mobileExtension);
}

Then we flash success and return, in this case to the edit page, but that’s completely up to you:



flash()->success('image edited!');
return view('marketingimage.edit', compact('marketingImage'));

Please note that if you are doing this for enterprise development, you might want a more robust check to see if the file is actually created, and handle it differently if for some reason it doesn’t happen. But that is beyond the scope of this tutorial.

Ok, we’re almost ready to wrap this up.

The Destroy Method

We just need to write out destroy method to handle deleting the photos:



public function destroy($id)
{
   $marketingImage = Marketingimage::findOrFail($id);
   $thumbPath = $marketingImage->image_path.'thumbnails/';

   File::delete(public_path($marketingImage->image_path).
                            $marketingImage->image_name . '.' .
                            $marketingImage->image_extension);

   File::delete(public_path($marketingImage->mobile_image_path).
                            $marketingImage->mobile_image_name . '.' .
                            $marketingImage->mobile_extension);
   File::delete(public_path($thumbPath). 'thumb-' .
                            $marketingImage->image_name . '.' .
                            $marketingImage->image_extension);

    Marketingimage::destroy($id);

   flash()->success('image deleted!');

   return redirect()->route('marketingimage.index');

}

You can see we findOrFail on the id that is handed in through the signature, then we use laravel’s File helper to delete, so once again we get beautiful syntax to show us what we are doing.

We use the public_path() method and put the components of the image inside of that signature. Then we just repeat for each type of image associated with the record.

Then we use the destroy method to remove the record from the DB. We flash a success method and redirect to the index page. And we’re done!

I hope you have enjoyed this tutorial and found it useful. Click on the sprocket icon at the top of the page to see all tutorials. Please comment, share, and like if you can, thanks.

I don’t have a donate button, but If you would like to support my work and learn more about Laravel, you can do so by buying one of my books, Laraboot: laravel 5* For Beginners, I really appreciate it.

10 thoughts on “Basic Image Management Part 3

      • nicklewis says:

        You are very welcome, sometimes these things are a real time saver. Sure I would have worked it out for myself but you highlighted a number of challenges that you should bear in mind. So very useful indeed. I especially liked the way you just cracked on and kept things as brief as possible. Ideal for people like me who are always short of time in this freelance business.

        Like

  1. This is really an amazing time saver serie.
    I have a question about saving the images in the database.
    Laravel has the datatype Binary. This is equivalent to Blob in mysql. The problem is this type only able to store up to 64kb, Which datatype should I choose?

    Thanks,

    Like

Leave a comment