How to Upload and store file to MySQL database in CodeIgniter 4

When you are allowing users to upload files then it is hard to manage when they are huge in numbers.

To resolve it you can store them in a database that makes the retrieving, updating, and deletion process easier.

In this tutorial, I show how you can upload and store file to MySQL database in the CodeIgniter 4 project.

How to Upload and store file to MySQL database in CodeIgniter 4


Contents

  1. Database configuration
  2. Enable CSRF
  3. Create Table
  4. Model
  5. Route
  6. Controller
  7. View
  8. Run
  9. Output
  10. Conclusion

1. Database configuration

  • Open .env file which is available at the project root.

NOTE – If dot (.) not added at the start then rename the file to .env.

  • Remove # from start of database.default.hostname, database.default.database, database.default.username, database.default.password, and database.default.DBDriver.
  • Update the configuration and save it.
database.default.hostname = 127.0.0.1
database.default.database = testdb
database.default.username = root
database.default.password = 
database.default.DBDriver = MySQLi

2. Enable CSRF

  • Again open .env file.
  • Remove # from the start of the security.tokenName,security.headerName, security.cookieName, security.expires,and security.regenerate.
  • I update the security.tokenName value with 'csrf_hash_name'. With this name read CSRF hash. You can update it with any other value.
  • If you don’t want to regenerate CSRF hash after each request then set security.regenerate = false.
security.tokenName = 'csrf_hash_name' 
security.headerName = 'X-CSRF-TOKEN' 
security.cookieName = 'csrf_cookie_name' 
security.expires = 7200 
security.regenerate = true
  • Open app/Config/Filters.php file.
  • Uncomment 'csrf' in 'before' if commented.
// Always applied before every request
public $globals = [
    'before' => [
       //'honeypot'
       'csrf',
    ],
    'after' => [
       'toolbar',
       //'honeypot'
    ],
];

3. Create Table

  • Create a new table images using migration.
php spark migrate:create create_images_table
  • Now, navigate to app/Database/Migrations/ folder from the project root.
  • Find a PHP file that ends with create_images_table and open it.
  • Define the table structure in the up() method.
    • filename – This field is used to store file name.
    • path – This field is used to store the upload file path.
  • Using the down() method delete images table which calls when undoing migration.
<?php namespace App\Database\Migrations;

use CodeIgniter\Database\Migration;

class CreateImagesTable extends Migration
{
    public function up() {
       $this->forge->addField([
             'id' => [
                 'type' => 'INT',
                 'constraint' => 10,
                 'unsigned' => true,
                 'auto_increment' => true,
             ],
             'filename' => [
                 'type' => 'VARCHAR',
                 'constraint' => '100',
             ],
             'path' => [
                 'type' => 'VARCHAR',
                 'constraint' => '255',
             ],
        ]);
        $this->forge->addKey('id', true);
        $this->forge->createTable('images');
    }

    //--------------------------------------------------------------------

    public function down() {
       $this->forge->dropTable('images');
    }
}
  • Run the migration –
php spark migrate

4. Model

  • Create Images Model –
php spark make:model Images
  • Open app/Models/Images.php file.
  • In $allowedFields Array specify field names – ['filename','path'] that can be set during insert and update.

Completed Code

<?php

namespace App\Models;

use CodeIgniter\Model;

class Images extends Model
{
    protected $DBGroup = 'default';
    protected $table = 'images';
    protected $primaryKey = 'id';
    protected $useAutoIncrement = true;
    protected $insertID = 0;
    protected $returnType = 'array';
    protected $useSoftDeletes = false;
    protected $protectFields = true;
    protected $allowedFields = ['filename','path'];

    // Dates
    protected $useTimestamps = false;
    protected $dateFormat = 'datetime';
    protected $createdField = 'created_at';
    protected $updatedField = 'updated_at';
    protected $deletedField = 'deleted_at';

    // Validation
    protected $validationRules = [];
    protected $validationMessages = [];
    protected $skipValidation = false;
    protected $cleanValidationRules = true;

    // Callbacks
    protected $allowCallbacks = true;
    protected $beforeInsert = [];
    protected $afterInsert = [];
    protected $beforeUpdate = [];
    protected $afterUpdate = [];
    protected $beforeFind = [];
    protected $afterFind = [];
    protected $beforeDelete = [];
    protected $afterDelete = [];
}

5. Route

  • Open app/Config/Routes.php file.
  • Define 2 routes –
    • / – Load files from database and display file upload view.
    • page/fileUpload – To upload a file.

Completed Code

$routes->get('/', 'PagesController::index');
$routes->post('page/fileUpload', 'PageController::fileUpload');

6. Controller

  • Create PagesController Controller –
php spark make:controller PagesController
  • Open app/Controllers/PagesController.php file.
  • Import Files Model.
  • Create 2 methods –
    • index() – Fetch all records from files table and assign to $data['files']. Load index view and pass $data.
    • fileUpload() – Using this method upload file and its calls on <form > submit.

Validate the file. If file is not validated then return to index view and pass error response.

If file is validated successfully then read file name and extension and assign to the variables. Upload the file to public/uploads folder and assign file path to $filepath variable.

Insert a record to files table where pass $insertdata Array. Specify $name to $insertdata['filename'] and $filepath to $insertdata['path'].

Store the success message in session()->setFlashdata('message') and class name in session()->setFlashdata('alert-class') and redirect to route("/").

Completed Code

<?php 
namespace App\Controllers;
use App\Models\Files;

class PageController extends BaseController{

   public function index(){

      // Fetch data 
      $files = new Files();
      $data['files'] = $files->findAll();

      return view('index',$data); 
   }

   // Upload file
   public function fileUpload(){

      // Validation
      $input = $this->validate([
          'file' => 'uploaded[file]|max_size[file,1024]|ext_in[file,jpg,jpeg,docx,pdf],'
      ]);

      if (!$input) { // Not valid
          $data['validation'] = $this->validator; 
          return view('index',$data); 
      }else{ // Valid

          if($file = $this->request->getFile('file')) {
              if ($file->isValid() && ! $file->hasMoved()) {

                 // Get file name and extension
                 $name = $file->getName();
                 $ext = $file->getClientExtension();

                 // Get random file name
                 //$newName = $file->getRandomName();

                 // Store file in public/uploads/ folder
                 $file->move('../public/uploads', $name);

                 // File path to display preview
                 $filepath = base_url()."/uploads/".$name;

                 // Insert Record 
                 $files = new Files();

                 $insertdata['filename'] = $name;
                 $insertdata['path'] = $filepath;

                 $files->insert($insertdata);

                 // Set Session
                 session()->setFlashdata('message', 'Uploaded Successfully!');
                 session()->setFlashdata('alert-class', 'alert-success');

              }else{
                 // Set Session
                 session()->setFlashdata('message', 'File not uploaded.');
                 session()->setFlashdata('alert-class', 'alert-danger');
              }
          }

      }

      return redirect()->route('/'); 
   }

}

7. View

Create index.php file in app/Views/.

Display bootstrap alert message if SESSION message variable is set.

Loop on $files Array to display file. If file is an image then display preview using <img > tag where pass $path in src attribute. If it is not an image file then display link using <a > tag where pass $path in href attribute.

Create <form method="post" action="<?=site_url('page/fileUpload')?>" enctype="multipart/form-data"> to upload file.

Completed Code

<!doctype html>
<html>
<head>
   <meta name="viewport" content="width=device-width, initial-scale=1.0">

   <title>How to Upload and store file to MySQL database in CodeIgniter 4</title>
   <link rel="stylesheet" type="text/css" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
</head>
<body>

   <div class="container">

      <div class="row mt-5">
         <div class="col-md-12">
             <?php 
             // Display Response
             if(session()->has('message')){
             ?>
                <div class="alert <?= session()->getFlashdata('alert-class') ?>">
                   <?= session()->getFlashdata('message') ?>
                </div>
             <?php
             }
             ?>

             <div class='row'>
             <?php 
             // Display existing files
             $imageext_arr = array("png","jpg","jpeg");
             foreach($files as $file){
                 $filename = $file['filename'];
                 $path = $file['path'];
                 $ext = strtolower(pathinfo($path, PATHINFO_EXTENSION));

                 $isImage = false;
                 if(in_array($ext,$imageext_arr)){
                    $isImage = true;
                 }
              ?>
                 <div class="col-md-3">
                     <?php 
                     if($isImage){
                         echo "<img src='".$path."' width='200px'>";
                     }else{
                         echo "<a href='".$path."' target='_blank'>".$filename."</a>";
                     }
                     ?>

                 </div>
              <?php
              } 
              ?>
              </div>
              <?php $validation = \Config\Services::validation(); ?>

              <form method="post" action="<?=site_url('page/fileUpload')?>" enctype="multipart/form-data">

                  <?= csrf_field(); ?>
                  <div class="form-group">
                     <label for="file">File:</label>

                     <input type="file" class="form-control" id="file" name="file" />
                     <!-- Error -->
                     <?php if( $validation->getError('file') ) {?>
                        <div class='alert alert-danger mt-2'>
                             <?= $validation->getError('file'); ?>
                        </div>
                     <?php }?>

                  </div>

                  <input type="submit" class="btn btn-success" name="submit" value="Upload">
              </form>
         </div>
      </div>
   </div>

</body>
</html>

8. Run

  • Navigate to the project using Command Prompt if you are on Windows or terminal if you are on Mac or Linux, and
  • Execute “php spark serve” command.
php spark serve
  • Run http://localhost:8080 in the web browser.

9. Output

View Output


10. Conclusion

For managing uploaded files in more better way you can store them in MySQL database using above script.

To store data userwise create a new field to store userid.

If you found this tutorial helpful then don't forget to share.

Leave a Comment