CakePHP 4 Upload Image Using Ajax with Form Data Tutorial

Reading Time: 9 minutes
2,964 Views

Inside this article we will see the concept of CakePHP 4 Upload image using ajax with form data. Article contains classified information about image upload in CakePHP using ajax request.

If you are looking for any article which helps you to learn Image upload process in CakePHP using ajax request, then you are at right place to learn and easy steps to implement in your application.

Here, we will assume a CakePHP form in which we will have form input fields along with image field. We will see the implementation of upload image in this article.

Learn More –

Let’s get started.

CakePHP 4 Installation

To create a CakePHP project, run this command into your shell or terminal. Make sure composer should be installed in your system.

$ composer create-project --prefer-dist cakephp/app:~4.0 mycakephp

Above command will creates a project with the name called mycakephp.

Create Database

To create a database, either we can create via Manual tool of PhpMyadmin or by means of a mysql command.

CREATE DATABASE mydatabase;

Successfully, we have created a database.

Database Connection

Open app_local.php file from /config folder. Search for Datasources. Go to default array of it.

You can add your connection details here to connect with your database. It will be like this –

//...

'Datasources' => [
        'default' => [
            'host' => 'localhost',
            /*
             * CakePHP will use the default DB port based on the driver selected
             * MySQL on MAMP uses port 8889, MAMP users will want to uncomment
             * the following line and set the port accordingly
             */
            //'port' => 'non_standard_port_number',

            'username' => 'root',
            'password' => 'sample@123',

            'database' => 'mydatabase',
            /*
             * If not using the default 'public' schema with the PostgreSQL driver
             * set it here.
             */
            //'schema' => 'myapp',

            /*
             * You can use a DSN string to set the entire configuration
             */
            'url' => env('DATABASE_URL', null),
        ],
  
     //...

//...

You can pass host, username, password and database.

Successfully, you are now connected with the database.

Create Migration

Open project into terminal and run this command to create migration file.

$ bin/cake bake migration CreateProducts

It will create 20220330143909_CreateProducts.php file inside /config/Migrations folder. Open migration file and write this following code into it.

The code is all about for the schema of products table.

<?php
declare(strict_types=1);

use Migrations\AbstractMigration;

class CreateProducts extends AbstractMigration
{
    public function change()
    {
        $table = $this->table('products');
      
        $table->addColumn("name", "string", [
            "limit" => 150
        ]);
        $table->addColumn("description", "text", [
            "null" => true
        ]);
        $table->addColumn("image", "string", [
            "limit" => 250,
            "null" => true
        ]);
        $table->addColumn("cost", "integer", [
            "limit" => 5
        ]);
        $table->create();
    }
}

Run Migration

Back to terminal and run this command.

$ bin/cake migrations migrate

It will create products table inside database.

Create Model & Entity

Next,

We will create model and entity. Back to terminal and run this command.

$ bin/cake bake model Products --no-validation --no-rules

It will create model file ProductsTable.php inside /src/Model/Table folder. Also we should see the entity file Product.php inside /src/Model/Entity folder.

Create Controller

Again,

Back to terminal and run this command into it.

$ bin/cake bake controller Product --no-actions

It will create ProductController.php file inside /src/Controller folder. Open controller file and write this code into it.

<?php

declare(strict_types=1);

namespace App\Controller;

class ProductController extends AppController
{
    public function initialize(): void
    {
        parent::initialize();
        $this->loadModel("Products");
    }

    public function createProduct()
    {
        // layout for create product form
    }

    public function submitProduct()
    {
        $this->autoRender = false;

        if ($this->request->is("ajax")) {

            $product = $this->Products->newEmptyEntity();

            $data = $this->request->getData();
            $productImage = $this->request->getData("image");

            $hasFileError = $productImage->getError();

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

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

            $product = $this->Products->patchEntity($product, $data);

            if ($this->Products->save($product)) {
                $this->Flash->success("Product created successfully");
            } else {
                $this->Flash->error("Failed to create product");
            }
        }

        echo json_encode(array(
            "response" => 1
        ));
        exit;
    }
}

Concept of Image Upload

Here, is the code snippet of image upload in above code of controller.

$productImage = $this->request->getData("image");

$hasFileError = $productImage->getError();

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

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

WWW_ROOT . “img/” returns the path upto of /img folder of webroot.

Above following code will save form data once we submit with form values. Also it will upload the product image into /webroot/img folder.

Create Template

Create Product folder inside /templates folder. Next, needs to create create_product.php file inside /templates/Product folder.

Open create_product.php file and write this following code into it. This will give the frontend layout for form.

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

<head>
    <title>CakePHP 4 Image Upload Using Ajax With Form Data</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
</head>

<body>

    <div class="container">
        <h2 style="text-align: center;">CakePHP 4 Image Upload Using Ajax With Form Data</h2>
        <div class="panel panel-primary">
            <div class="panel-heading">CakePHP 4 Image Upload Using Ajax With Form Data</div>
            <div class="panel-body">

                <?= $this->Flash->render() ?>

                <form action="javascript:void(0)" id="frm-add-product" enctype="multipart/form-data">
                    <div class="form-group">
                        <input type="text" name="name" class="form-control" placeholder="Name">
                    </div>
                    <div class="form-group">
                        <textarea name="description" class="form-control" placeholder="Description"></textarea>
                    </div>
                    <div class="form-group">
                        <input type="file" name="image" class="form-control" class="image">
                    </div>
                    <div class="form-group">
                        <input type="number" min="0" name="cost" class="form-control" placeholder="Cost">
                    </div>
                    <div class="form-group">
                        <button type="submit" class="btn btn-success">Save</button>
                    </div>
                </form>
            </div>
        </div>
    </div>

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>

    <script>
        $(function() {

            // Ajax form submission with image
            $('#frm-add-product').on('submit', function(e) {

                e.preventDefault();

                var formData = new FormData(this);

                //We can add more values to form data
                //formData.append("key", "value");

                $.ajax({
                    url: "/submit-product",
                    type: "POST",
                    cache: false,
                    data: formData,
                    processData: false,
                    contentType: false,
                    dataType: "JSON",
                    success: function(data) {
                        window.location.reload();
                    },
                    error: function(jqXHR, textStatus, errorThrown) {
                        alert('Error at add data');
                    }
                });
            });
        });
    </script>

</body>

</html>

Disable CSRF Token

When we submit a cakephp form, it needs a CSRF token should be submitted with form submission request.

We are not interested to send CSRF token with form data. To disable it, Open Application.php from /src folder.

Remove these lines of code from middleware() method.

->add(new CsrfProtectionMiddleware([
    'httponly' => true,
]))

Add Route

Open routes.php file from /config folder. Add these routes into it.

//...

$routes->connect(
    '/create-product',
    ['controller' => 'Product', 'action' => 'createProduct']
);

$routes->connect(
    '/submit-product',
    ['controller' => 'Product', 'action' => 'submitProduct']
);

//...

Application Testing

Open terminal and run this command to start development server.

$ bin/cake server

URL: http://localhost:8765/create-product

Submit form data values

Once form data will be submitted to server and render back to page with flash message.

Check database table for saved data

We hope this article helped you to learn about CakePHP 4 Upload Image Using Ajax with Form Data Tutorial in a very detailed way.

Online Web Tutor invites you to try Skillshike! Learn CakePHP, Laravel, CodeIgniter, Node Js, MySQL, Authentication, RESTful Web Services, etc into a depth level. Master the Coding Skills to Become an Expert in PHP Web Development. So, Search your favourite course and enroll now.

If you liked this article, then please subscribe to our YouTube Channel for PHP & it’s framework, WordPress, Node Js video tutorials. You can also find us on Twitter and Facebook.

Sanjay KumarHello friends, I am Sanjay Kumar a Web Developer by profession. Additionally I'm also a Blogger, Youtuber by Passion. I founded Online Web Tutor and Skillshike platforms. By using these platforms I am sharing the valuable knowledge of Programming, Tips and Tricks, Programming Standards and more what I have with you all. Read more