Laravel E-Commerce Application Development – Products Section Part 3

Laravel E-Commerce Application Development – Products Section Part 3

Laravel E-Commerce Application Development ( 27 Lessons )

In this course, you’ll learn how to create an E-Commerce Website from scratch in Laravel. The process has never been easier I’ll take you from the very beginning stages of setting up Laravel till the last steps of adding products to the cart. If you’ve good understanding & experience in PHP & MySQL then this course is for you.

see full series
  1. Laravel E-Commerce Application Development – Introduction
  2. Laravel E-Commerce Application Development – Initial Project Setup
  3. Laravel E-Commerce Application Development – Assets Setup Using Laravel Mix
  4. Laravel E-Commerce Application Development – Admin Model and Migration
  5. Laravel E-Commerce Application Development – Backend Admin Authentication
  6. Laravel E-Commerce Application Development – Base Controller and Repository
  7. Laravel E-Commerce Application Development – Settings Section Part 1
  8. Laravel E-Commerce Application Development – Settings Section Part 2
  9. Laravel E-Commerce Application Development – Categories Section Part 1
  10. Laravel E-Commerce Application Development – Categories Section Part 2
  11. Laravel E-Commerce Application Development – Attributes Section Part 1
  12. Laravel E-Commerce Application Development – Attributes Section Part 2
  13. Laravel E-Commerce Application Development – Attributes Section Part 3
  14. Laravel E-Commerce Application Development – Brands Section
  15. Laravel E-Commerce Application Development – Products Section Part 1
  16. Laravel E-Commerce Application Development – Products Section Part 2
  17. Laravel E-Commerce Application Development – Products Section Part 3
  18. Laravel E-Commerce Application Development – Products Section Part 4
  19. Laravel E-Commerce Application Development – Frontend Login & Registration
  20. Laravel E-Commerce Application Development – Categories Navigation
  21. Laravel E-Commerce Application Development – Catalog Listing
  22. Laravel E-Commerce Application Development – Product Details Page
  23. Laravel E-Commerce Application Development – Shopping Cart
  24. Laravel E-Commerce Application Development – Checkout
  25. Laravel E-Commerce Application Development – Payment Processing
  26. Laravel E-Commerce Application Development – Order Management
  27. Laravel E-Commerce Application Development – Wrap Up

This is part 16 of the Laravel E-Commerce Application Development series. In this part, we will add the product images tab to our product edit view.

Adding Product Images Tab

First of all, we will add the required tab to our product edit view. So head over to resouces/views/admin/products and open the edit.blade.php view file which we created in our previous post.

In this view, we will add a list item in our tabs navigation block. Add the below HTML markup right after the General‘s link.

<li class="nav-item"><a class="nav-link" href="#images" data-toggle="tab">Images</a></li>

Next we will add the tab area for this link. Within the tab-content div, after the general section add below markup.

<div class="tab-pane" id="images">
    <div class="tile">
        <h3 class="tile-title">Upload Image</h3>
        <hr>
        <div class="tile-body">
            <div class="row">
                <div class="col-md-12">
                    <form action="" class="dropzone" id="dropzone" style="border: 2px dashed rgba(0,0,0,0.3)">
                        <input type="hidden" name="product_id" value="{{ $product->id }}">
                        {{ csrf_field() }}
                    </form>
                </div>
            </div>
            <div class="row d-print-none mt-2">
                <div class="col-12 text-right">
                    <button class="btn btn-success" type="button" id="uploadButton">
                        <i class="fa fa-fw fa-lg fa-upload"></i>Upload Images
                    </button>
                </div>
            </div>
            @if ($product->images)
                <hr>
                <div class="row">
                    @foreach($product->images as $image)
                        <div class="col-md-3">
                            <div class="card">
                                <div class="card-body">
                                    <img src="{{ asset('storage/'.$image->full) }}" id="brandLogo" class="img-fluid" alt="img">
                                    <a class="card-link float-right text-danger" href="{{ route('admin.products.images.delete', $image->id) }}">
                                        <i class="fa fa-fw fa-lg fa-trash"></i>
                                    </a>
                                </div>
                            </div>
                        </div>
                    @endforeach
                </div>
            @endif
        </div>
    </div>
</div>

In this markup, we have two sections. First one is a form which we will bind it to a Dropzone instance. This form also contains a hidden field for product id, as we want to send the product id to our controller so we can attach the uploaded images to the current product.

In the second section, we are looping over all product images and showing the image with a link to delete the image.

Injecting CSS and JavaScript for Plugins

Now we need to inject the Dropzone’s required CSS and JavaScript. Firstly we will add the dropzone CSS file to our view. Right on the top of this page add the below code block.

@section('styles')
    <link rel="stylesheet" type="text/css" href="{{ asset('backend/js/plugins/dropzone/dist/min/dropzone.min.css') }}"/>
@endsection

Next right at the end of edit.blade.php file add the required scripts in our scripts section.

<script type="text/javascript" src="{{ asset('backend/js/plugins/dropzone/dist/min/dropzone.min.js') }}"></script>
<script type="text/javascript" src="{{ asset('backend/js/plugins/bootstrap-notify.min.js') }}"></script>

Adding Dropzone File Uploader

Now we will add another script tag and instantiate the dropzone instance to bind it with our form.

<script>
    Dropzone.autoDiscover = false;

    $( document ).ready(function() {
        $('#categories').select2();

        let myDropzone = new Dropzone("#dropzone", {
            paramName: "image",
            addRemoveLinks: false,
            maxFilesize: 4,
            parallelUploads: 2,
            uploadMultiple: false,
            url: "{{ route('admin.products.images.upload') }}",
            autoProcessQueue: false,
        });
        myDropzone.on("queuecomplete", function (file) {
            window.location.reload();
            showNotification('Completed', 'All product images uploaded', 'success', 'fa-check');
        });
        $('#uploadButton').click(function(){
            if (myDropzone.files.length === 0) {
                showNotification('Error', 'Please select files to upload.', 'danger', 'fa-close');
            } else {
                myDropzone.processQueue();
            }
        });
        function showNotification(title, message, type, icon)
        {
            $.notify({
                title: title + ' : ',
                message: message,
                icon: 'fa ' + icon
            },{
                type: type,
                allow_dismiss: true,
                placement: {
                    from: "top",
                    align: "right"
                },
            });
        }
    });
</script>

In this code example, we have added a new Dropzone instance and binding it with #dropzone. Also, we have added some other propertied which are self-explanatory.
The most important part in the dropzone object is the url property which is pointing to a route named admin.products.images.upload.

Next, on dropzone’s queuecomplete event we are reloading the window and showing the success notification.

This form will be submitted when we hit the button with id #uploadButton.

To learn more about Dropzone, visit their documentation page.

In the last, we have a showNotification() which simply trigger the bootstap notify alerts.

Creating Route to Store Product Images

Now we will create the required routes which we are using in our dropzone and on the delete image link.

Within the products, route group adds the below routes.

Route::post('images/upload', 'Admin\ProductImageController@upload')->name('admin.products.images.upload');
Route::get('images/{id}/delete', 'Admin\ProductImageController@delete')->name('admin.products.images.delete');

Storing Product Images

As we are dealing with the product images, I opt for creating a new controller to handle the product images functions.

Important

Previously we added the two fields to our product_images table thumbnail and full. Before proceeding to saving images, you have to delete the thumbnail field from the database table. You can achieve this in two ways, either create a new migration file to remove this field, or you can simply update the current migration and run the php artisan migrate:refresh --seed command to re migrate all tables and run all seeders.

Open you terminal and run the below command to generate the ProductImage controller.

php artisan make:controller Admin\ProductImageController

Now, open the new generated controller and inject the product repository in it.

namespace App\Http\Controllers\Admin;

use App\Traits\UploadAble;
use App\Models\ProductImage;
use Illuminate\Http\Request;
use App\Contracts\ProductContract;
use App\Http\Controllers\Controller;

class ProductImageController extends Controller
{
    use UploadAble;

    protected $productRepository;

    public function __construct(ProductContract $productRepository)
    {
        $this->productRepository = $productRepository;
    }
}

Next, we will add the upload() method to save our product images.

public function upload(Request $request)
{
    $product = $this->productRepository->findProductById($request->product_id);

    if ($request->has('image')) {

        $image = $this->uploadOne($request->image, 'products');

        $productImage = new ProductImage([
            'full'      =>  $image,
        ]);

        $product->images()->save($productImage);
    }

    return response()->json(['status' => 'Success']);
}

In this, method we are loading the current product by id and then checking if the incoming request has the image in it. Then we are uploading the image using our UploadAble trait.

Next, we are saving the newly uploaded image path to our product_images table by creating a new instance of ProductImage model and then passing it back to the product’s images() relationship by calling the save() method on it.

Deleting a Product Image

Next, we will add the delete() method to handle the delete action for product images.

public function delete($id)
{
    $image = ProductImage::findOrFail($id);

    if ($image->full != '') {
        $this->deleteOne($image->full);
    }
    $image->delete();

    return redirect()->back();
}

In this method, we find the product image by id and then checking if there is an image path exist in database delete the image first.

Finally, we are deleting the current image record and redirecting the user back to the product edit view.

What’s Next

In this post, we completed the product images for the Products Section. In the next post, we will add the product attributes section.

Code Repository

You can find the code base of this series on Laravel eCommerce Application repository.

If you have any question about this post, please leave a comment in the comment box below.

Your little help will keep this site alive and help us to produce quality content for you.