Basic Image Management Part 1

Access all tutorials in sprocket icon.

July 29, 2015 from author Bill Keck.

Basic Image Management

Part 1.

Introduction

One thing I’ve always found a little tricky is image management, lot’s of little gotchas that make it a bit of pain. I’m so used to dealing with models and database tables, that dealing with physical files isn’t as intuitive for me. So if you are just starting out with Laravel and tripping over this, I feel your pain.

Luckily, basic image management in Laravel is not that tough, once you get a few of the basics down. If you are really new to Laravel, this is not a good first tutorial. I recommend working through some of my other tutorials first before proceeding.

Just a couple of notes on this tutorial. It’s a long one. I’m going to break it up into several parts.

Also note that I’m not much of a frontend designer, so the views we make are not especially pretty, it will be up to you to decorate them how you wish. The main point here is to learn about image management.

So anyway, what are the basics? I thought about the typical requirements you might see on an application and came up with this list:

  • create images
  • store images
  • edit images
  • update images
  • create thumbnails
  • edit thumbnails
  • create and edit separate mobile images

For those of you who are familiar with restful controller actions, you know that create and edit actions show forms, and that store and update actually creates and updates the records and files.

With images, we are dealing with two things, the model, which operates on the data, things like the name of the image and its path, and then the other thing is the image file itself, which is stored in the folder that we are going to assign it to.

install Intervention

We are going to start by installing the Intervention/image package. If you have not already done so, add the following to the require section of your composer.json file:



"intervention/image": "~2.2"

Next we are going to add the following to the providers array in app\config\app.php:



Intervention\Image\ImageServiceProvider::class,

And then in the aliases array:



Intervention\Image\ImageServiceProvider::class,

I recommend that you check out the intervention page to make sure these instructions are the latest version.

Note that last time I checked, the Intervention instructions were using the old style way of referencing the provider:



'Intervention\Image\ImageServiceProvider'

You can see above, in both cases we have used ::class, which is a neat tip I picked up from Laracasts.com. It’s a better way to do it because if you are using PHP Storm for example, you click right through to the underlying class.

The intervention package gives us a simpler syntax and an easy way to make thumbnails, which is primarily what we’re going to use in this tutorial. They have a bunch of other cool methods, so check out the documentation for that.

Also note, we will be using the laravelcollective/html package and the patricktalmadge/bootstrapper package. If you followed my Top Ten Must-Have Laravel 5.1 tutorial, you have these installed already. If not, please install them before proceeding.

Ok, moving on.

Creating the Model

To give ourselves something to work with, we’re going to create a Marketingimage model. We can do that by using artisan from the commandline as follows:



php artisan make:model Marketingimage -m

You’ll notice the -m flag which tells Laravel that you also want to create a migration at the same time, so this is a handy feature.

Ok run that and you should have a model file, Marketingimage.php directly under your app directory and a migration file in the database/migrations folder. Let’s modify the up on the migration file method to the following:



public function up()
{
    Schema::create('marketing_images', function(Blueprint $table)
    {
        $table->increments('id');
        $table->boolean('is_active')->default(false);
        $table->boolean('is_featured')->default(false);
        $table->string('image_name')->unique();
        $table->string('image_path');
        $table->string('image_extension', 10);
        $table->string('mobile_image_name')->unique();
        $table->string('mobile_image_path');
        $table->string('mobile_extension', 10);
        $table->timestamps();
    });
}

First thing you can see is that I changed the table name. I prefer separation of words in my table names by underscore. You are free to follow your own convention, however note that we must use plural to follow Laravel’s conventions correctly. In Laravel, the model is singular and the table name is plural.

After the id column, we have two boolean columns that let us know if the image is active or featured, useful constraints to help us work with the images later on.

Then we follow that with name, path, extension columns for both image and mobile image. This will give us enough flexibility so that if we want to save a different image as the mobile image, we can. This is often necessary because simply scaling the photo may not produce the desired results.

Since we are going to create the thumbnail from the primary image, we don’t need to save any data for that.

By saving the path and extension of the image, we have an easy reference that we can use to show the image in our application and also for managing the images in a list of images.

We will of course also need to modify the down method:




public function down()
{
   Schema::drop('marketing_images');
}

Once that’s done, go ahead and run php artisan migrate from the command line, then check to make sure the table has been created.

Next we are going to make a modification to our Marketingimage model. Change it to the following:



 <?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Marketingimage extends Model
{
    protected $table = 'marketing_images';

    protected $fillable = ['is_active',
                                     'is_featured',
                                    'image_name',
                                    'image_path',
                                    'image_extension',
                                    'mobile_image_name',
                                    'mobile_image_path',
                                    'mobile_extension'
    ];
}

You can see that are telling the model which table to reference, as well as providing the fillable columns, so we don’t run into a mass-assignment problem.

The Controller

Ok, cool, we are ready to move on, things are zipping along that this point. So next we’ll create the controller by using artisan:



php artisan make:controller MarketingImageController

This will get you a restful controller in app/Http/Controllers with stubs for the following:

  • index
  • create
  • store
  • show
  • edit
  • update
  • destroy

We will be using each of these methods.

Now a handy tip for beginners is to put in the index method, something like the following:



return 'Here is the index method.';

This will give you a chance to test this route. More advanced users can skip that if they want.

Next we’ll setup our routes. Let’s modify app/Http/routes.php and add the following:



Route::resource('marketingimage', 'MarketingImageController');

You can see we are adding a resource, which gives us routes to all of our actions, all in one go, a very convenient way to do it.

So now, with that in place, you should be able to go to yourproject.com/marketingimage and get the following result:



Here is the index method.

So the next logical step is to setup our views. Let create a marketingimage folder under resources/views. Then go ahead and create the following empty files inside of the marketingimages folder:

  • create.blade.php
  • edit.blade.php
  • index.blade.php
  • show.blade.php

Setting up the Folders

We will return to those files in a bit, but for now let’s create a place to store our actual images. I’m keeping this very simple for this tutorial. Let’s create a folder named imgs directly under your public folder. Inside of the imgs folder, create a folder named marketing, and inside that marketing folder, create a folder named mobile and a folder named thumbnails.

So this gives us the folders for the image files.

The Create View

Ok, next let’s tackle the create view. Place the following inside of create.blade.php:



@extends('layouts.master')

@section('content')

    {!! Breadcrumb::withLinks(['Home' => '/', 'marketing images' => '/marketingimage', 'create']) !!}

     <h1>Upload a Photo </h1>


     <hr/>

     @if (count($errors) > 0)
	 <div class="alert alert-danger">
	 <strong>Whoops! </strong> There were some problems with your input. <br> <br>
	 <ul>
	     @foreach ($errors->all() as $error)
		 <li>{{ $error }} </li>
	     @endforeach

         </ul>
         </div>

    @endif


    {!! Form::open(array('route' => 'marketingimage.store', 'class' => 'form', 'files' => true)) !!}

     <!-- image name Form Input -->
     <div class="form-group">
        {!! Form::label('image name', 'Image name:') !!}
        {!! Form::text('image_name', null, ['class' => 'form-control']) !!}
     </div>


     <!-- mobile_image_name Form Input -->
     <div class="form-group">
        {!! Form::label('mobile_image_name', 'Mobile Image Name:') !!}
        {!! Form::text('mobile_image_name', null, ['class' => 'form-control']) !!}
     </div>


     <!-- is_something Form Input -->
     <div class="form-group">
        {!! Form::label('is_active', 'Is Active:') !!}
        {!! Form::checkbox('is_active') !!}
     </div>

     <!-- is_featured Form Input -->
     <div class="form-group">
        {!! Form::label('is_featured', 'Is Featured:') !!}
        {!! Form::checkbox('is_featured') !!}
     </div>

    <!-- form field for file -->
    <div class="form-group">
       {!! Form::label('image', 'Primary Image') !!}
       {!! Form::file('image', null, array('required', 'class'=>'form-control')) !!}
    </div>

     <!-- form field for file -->
     <div class="form-group">
        {!! Form::label('mobile_image', 'Mobile Image') !!}
        {!! Form::file('mobile_image', null, array('required', 'class'=>'form-control')) !!}
     </div>

     <div class="form-group">

        {!! Form::submit('Upload Photo', array('class'=>'btn btn-primary')) !!}

     </div>

    {!! Form::close() !!}

@endsection

Ok, nothing too crazy here.

Note that we are extending the master page, which is the layouts folder in the views folder. We call it like so:



@extends('layouts.master')

If you have a different master page or it’s in a different location, adjust that as needed. If you are unfamiliar with the concept of master page, find a tutorial on that and learn it before proceeding.

If you are not using the Bootstrapper package, eliminate the following:



{!! Breadcrumb::withLinks(['Home' => '/', 'marketing images' => '/marketingimage', 'create']) !!}

Also note, for this tutorial, I am including the if statement to print out form input errors, but in almost all cases, this would actually be extracted out to a view partial and then be referenced by something like:



@include('errors.errors')

You can also see that we are using the Form helper from the laravelcollective/html package quite a bit. I find the form helper very useful and it’s great for things like opening the form:



{!! Form::open(array('route' => 'marketingimage.store', 'class' => 'form', 'files' => true)) !!}

You can see we included ‘files’ => true, which allows us to upload multiple files.

If you are new to using this form helper, you can obviously see that we don’t need to specify POST and we don’t need to call the CSFR token because it does it for you automatically.

Then we have the various form inputs, nothing too crazy there. We also have the Form::submit which we use for the button and finally Form::close().

You can see from our form helper that the route is set to marketingimage.store, so we know from our route resource in routes.php that this will take us to the store method on MarketingImageController.php, which is in our Controllers directory.

This tutorial is continued in Part 2.

5 thoughts on “Basic Image Management Part 1

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s