Implement Drag and Drop File Upload in CakePHP with Dropzone.js

November 30, 2023
Written by
Contributor
Opinions expressed by Twilio contributors are their own
Reviewed by
Twilion

In the last article, you learned how to upload files in CakePHP. We'll take things further, in this tutorial, by creating a drag-and-drop file upload in CakePHP using Dropzone.js. Dropzone leverages AJAX to upload files without requiring a page refresh, making it an effective tool for developers and users.

Prerequisites

To follow this tutorial, make sure you have the following:

  • Basic knowledge of PHP and web development concepts
  • PHP 8.2 installed
  • Access to a MySQL server
  • Composer installed globally

Create a CakePHP project

To do this, navigate to the folder you want to install the project and run the following command:

​​composer create-project --prefer-dist cakephp/app:~4.0 drag_upload \
    && cd drag_upload

When you're asked: Set Folder Permissions ? (Default to Y) [Y,n]?, answer with Y. This will install the latest version of CakePHP and give it the name drag_upload as the folder name for the project, and change into the newly created project directory.

Connect the database to the application

To connect the database to the application, open config\app_local.php in your preferred code editor or IDE. In the default section, inside the Datasource section, change the host, username, password, and database properties to match the credentials of your database, like so:

Database configuration process for CakePHP development

From the image above, the host was changed to 127.0.0.1, the username to root, the password was left blank, and the database was set to the one created earlier.

Create the database

To begin, we need a database to store information about uploaded files. Create one; I'll be naming mine drag_file. The next thing is to create a new table in your database called data_and_drop using the migrations feature in CakePHP.  The table needs to contain the following fields:

  • id: This field will serve as the unique identifier for each uploaded file. It should have a type of integer, be the table's primary index, with the not null and auto-increment attributes set.
  • filename: This field will store the name of the data input. It should have a data type of varchar with a size of 255.

To do this, open up the terminal and run this command:

bin/cake bake migration CreateDragAndDrop

This will create a migrations file in config/Migrations/ ending with _CreateDragAndDrop.php. Open it, and replace the body of the change() function with the following code:

$table = $this->table('drag_and_drop');
$table->addColumn('filename', 'string', [
    'default' => null,
    'limit' => 255,
    'null' => false,
]);
$table->create();

Next, run this command to run the migration:

bin/cake migrations migrate

This will create a  table called drag_and_drop in the database. Our database should now look similar to:

Database table Created for file storage in CakePHP using migrations.

Now, start the development server in your terminal, by running this command:

bin/cake server

Now, if you open http://localhost:8675 in your browser of choice, it should look similar to the screenshot below.

The default home page of a CakePHP application running in Firefox on macOS. It shows the top part of the page, where all of the required prerequisites for running CakePHP are met by the installation.

Create a model and entity

To create a model and entity, open up a new terminal and run this command:

bin/cake bake model drag_and_drop --no-validation --no-rules

Running this command will create the model file DragAndDropTable.php inside the /src/Model/Table folder, and the entity file DragAndDrop.php inside the /src/Model/Entity folder.

Create a controller

To create a controller, open up the terminal once again and run this command:

bin/cake bake controller Dropzone --no-actions

Running this command will create a file called the DropzoneController.php file inside the src/Controller folder. Open the file, and inside it, paste this:

<?php

declare(strict_types=1);

namespace App\Controller;

use Cake\Datasource\RepositoryInterface;

class DropzoneController extends AppController
{

    private ?RepositoryInterface $DragAndDrop;

    public function initialize(): void
    {
        parent::initialize();
        $this->loadModel("DragAndDrop");
    }

    public function dropzone()
    {
        $uploadObject = $this->DragAndDrop->newEmptyEntity();

        if ($this->request->is("post")) {
            $image = $this->request->getData('file');
            $hasFileError = $image->getError();

            // no file uploaded
            if ($hasFileError > 0) {
                $data["filename"] = "";
            } else {
                // file uploaded
                $fileName = str_replace(" ", "-", $image->getClientFilename());
                $fileType = $image->getClientMediaType();

                if ($fileType === "image/png" || $fileType === "image/jpeg" || $fileType === "image/jpg") {
                    $imagePath = WWW_ROOT . "img/" . $fileName;
                    $image->moveTo($imagePath);
                    $data["filename"] = "img/" . $fileName;
                }
            }

            $uploadObject = $this->DragAndDrop->patchEntity($uploadObject, $data);

            if ($this->DragAndDrop->save($uploadObject)) {
                echo json_encode(["status" => 1, "message" => "Uploaded"]);
            } else {
                echo json_encode(["status" => 0, "message" => "Failed to upload"]);
            }
        }

        $this->set(compact("uploadObject"));
    }
}

In the code above, DropzoneController manages the file uploads via Dropzone. It initializes the controller, loads the DragAndDrop model, and handles file uploads. It also validates uploaded files, processes valid image files, and saves them to a specific directory,

Create the template

To create a template, navigate to the templates folder and create a folder named Dropzone. Then, in the templates/Dropzone folder, create a file called dropzone.php and paste the following into it:

<!DOCTYPE html>
<html lang="en">

<head>
    <title>CakePHP 4 Drag And Drop File Upload Using Dropzone</title>
    <script src="https://unpkg.com/dropzone@5/dist/min/dropzone.min.js"></script>
    <link rel="stylesheet" href="https://unpkg.com/dropzone@5/dist/min/dropzone.min.css" type="text/css" />
</head>

<body>

    <div class="container section">
        <div class="row">
            <div class="col-md-8 col-md-offset-2">
                <h3 class="text-center">CakePHP 4 Drag And Drop File Upload Using Dropzone</h3>
                <?= $this->Form->create($uploadObject, [
                        "enctype" => "multipart/form-data",
                        "id" => "image-upload",
                        "class" => "dropzone"
                ]) ?>
            <div>
                <h3 class="text-center">Upload Multiple Image By Click On Box</h3>
            </div>
            <?= $this->Form->end() ?>
        </div>
    </div>
</div>
<script type="text/javascript">
    Dropzone.options.imageUpload = {
        maxFilesize: 1,
        acceptedFiles: ".jpeg,.jpg,.png,.gif",
    };
</script>
</body>

</html>

The code above creates a user interface that facilitates file uploads using Dropzone.js. It includes necessary styles and scripts, configures a form for file uploads, and defines settings for the Dropzone component to enable users to drag and drop multiple image files while restricting the file types and sizes.

Add a route

This will be the last thing that needs to be done. Navigate to config/routes.php and inside the call to $routes->scope(), paste this:

$builder->connect(
    '/dropzone',
    ['controller' => 'Dropzone', 'action' => 'dropzone']
);

Restart and test the application

You can now check that the new functionality works as expected by opening http://localhost:8765/dropzone in your preferred browser. The page should look similar to the screenshot below.

implementation of drag-and-drop feature in CakePHP using Dropzone.js for file uploads.

To upload an image, drag the desired image inside the box and it automatically uploads. You can upload as many as you want. When a file is successfully uploaded, it immediately provides a preview, which is helpful. 

After uploading several images, the drag_and_drop table in your  database should look like the screenshot below:

A snapshot of a database table using phpMyAdmin to show 6 entries in a table.

That's how to implement drag and drop file upload in CakePHP with Dropzone.js

In this article, we looked at another way to upload files in CakePHP, a drag-and-drop method using Dropzone.js. Dropzone helps by simplifying the management of file uploads in CakePHP Happy coding!

Temitope Taiwo Oyedele is a software engineer and technical writer. He likes to write about things he’s learned and experienced.