How to Upload File in CakePHP 4, Part-5

CakePHP 4 Moving the uploaded file from the its temporary location to the desire target location to using CakePHP 4 library to upload files. We need to use PHP’s  moveTo method upload file  to the server. In this tutorial you will learn how to upload a file in CakePHP.

Table of Contents

Create MySQL Database and Table

In the first step we need to create a database and tables, so here I have created a database of tables “webscodex” and ”posts” with identifiers and columns with names. You simply create a Users table as described in the SQL query.

--
-- Database: `webscodex`

-- Table structure for table `posts`
--

CREATE TABLE `posts` (
  `id` int(100) NOT NULL PRIMARY KEY AUTO_INCREATMENT,
  `title` varchar(100) NOT NULL,
  `description` varchar(100) NOT NULL,
  `post_image` varchar(100) NOT NULL,
  `created` datetime NOT NULL,
  `updated` datetime NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

File Upload Directory

Create the directory (webroot/img/post_image) where you want to upload or store images the upload directory using $targetPath

$targetPath = WWW_ROOT. 'img'. DS . 'post_image'. DS.;

Controller

In this post we will use the src/controller/PostsController.php  controller to create a add function to upload file in database.

src/controller/PostsController.php

<?php

// src/Controller/PostsController.php

namespace App\Controller;
use App\Controller\AppController;
use Cake\Event\EventInterface;
use Cake\Datasource\FactoryLocator;

class PostsController extends AppController{

	public $postsTableObj;

	public function beforefilter(EventInterface $event){
	    parent::beforefilter($event);
	    $this->postsTableObj = FactoryLocator::get('Table')->get('Posts');
	}


    public function add(){
    	$postEnt = $this->postsTableObj->newEmptyEntity();
    	if ($this->request->is('post')) {
    	    $postData = $this->request->getData();
            $postImage = $this->request->getData('post_image');
            $name = $postImage->getClientFilename();
            $type = $postImage->getClientMediaType();
            $targetPath = WWW_ROOT. 'img'. DS . 'post_image'. DS. $name;
            if ($type == 'image/jpeg' || $type == 'image/jpg' || $type == 'image/png') {
                if (!empty($name)) {
                    if ($postImage->getSize() > 0 && $postImage->getError() == 0) {
                        $postImage->moveTo($targetPath); 
                        $postData['post_image'] = $name;
                    }
                }
            }
    	    $posts = $this->postsTableObj->patchEntity($postEnt, $postData);
    	if ($this->postsTableObj->save($posts)) {
    	    $this->Flash->success(__('Your post has been saved.'));
            return $this->redirect(['controller'=>'Posts','action' => 'index']);
    	}else{
    	    $this->Flash->error(__('Unable to add your post.'));
            return $this->redirect(['controller'=>'Posts','action' => 'add']);
    	    }
    	}
    	$this->set(compact('postEnt', $postEnt));
    }
}

Model

In Model src/Model/Table/PostsTable.php  to validate form and insert date time value in created and updated using addBehavior function with Timestamp.

src/Model/Table/PostsTable.php

<?php

namespace App\Model\Table;
use Cake\ORM\Table;
use Cake\Validation\Validator;


class PostsTable extends Table
{
    public function initialize(array $config): void
    {
        $this->addBehavior('Timestamp', [
            'events' => [
                'Model.beforeSave' => [
                    'created' => 'new',
                    'updated' => 'always'
                ]
            ]
        ]);
    }



    public function validationDefault(Validator $validator): Validator 
    {

    $validator
        ->notEmptyString('title')
        ->notEmptyString('description')
        ->notEmptyString('post_image');
        return $validator;
	}

}

View

In view Templates/Posts/add.php view is responsible for creating the upload form and display the uploaded file list.

Templates/Posts/add.php 

<div class="text-center" style="margin-top: 50px;">
  <h4>Add Post</h4>
</div>
<div class="container">
  <div class="row">
    <div class="col-sm-3"></div>
    <div class="col-sm-6">
      <?php echo $this->Form->create($postEnt, ['name'=>'add_post', 'class'=>'was-validated',
       'enctype'=>'multipart/form-data']) ?>
      <div class="form-group">
        <?php echo $this->Form->control('title', ['type'=>'text', 'class'=>'form-control','placeholder'=>'Enter title','required'=>true]);?>
      </div>
      <div class="form-group">
        <?php echo $this->Form->control('description', ['type'=>'text', 'class'=>'form-control','placeholder'=>'Enter description','required'=>true]);?>
      </div>
      <div class="form-group">
        <?= $this->Form->control('post_image', ['type'=>'file', 'class'=>'form-control','required'=>true]); ?>
      </div>
      <button type="submit" class="btn btn-success" style="float: right;">Save</button>
      <?php echo $this->Form->end() ?>
    </div>
  </div>
</div>

You can always support by sharing on social media or recommending my blog to your friends and colleagues. If you have any suggestions / problems about this tutorial, please comment on the  form below.😊

4 Comments

Leave a Reply

Your email address will not be published. Required fields are marked *

  1. Hey, thanks for this – it worked well! My only question is – on edit if I don't choose a file, it gives an error "cannot be blank". Essentially, I don't want to update the field if a new file isn't selected (just keep the file that is already there). Any recommendations on how to approach this? Thanks!