Upload multiple images at once helps to reduce the time taking for uploading a large number of images to the server. It also provides a user-friendly way to upload multiple images to the server at once instead of one-by-one. Multiple image upload functionality is very useful for the dynamic gallery management section on the web application. It is also very useful for product management section where multiple images need to be uploaded for each product.
The multiple images can be uploaded on a single click using PHP. Not only the images but also you can upload data with images to the server using PHP and MySQL. In this tutorial, we will show you how to upload multiple images and manage (view, edit, and delete) data with PHP and MySQL.
In the example script, we will implement a gallery management system with multiple images using PHP and MySQL.
Before getting started, take a look at the files structure of the multiple images upload management script.
multiple_image_upload_crud/ ├── index.php ├── view.php ├── addEdit.php ├── postAction.php ├── DB.class.php ├── uploads/ │ └── images/ ├── js/ │ └── jquery.min.js ├── bootstrap/ │ └── bootstrap.min.css ├── css/ │ └── style.css └── images/
To store the gallery and image files information two tables need to be created in the database.
1. The following SQL creates a gallery
table with some basic fields in the MySQL database.
CREATE TABLE `gallery` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`created` datetime NOT NULL,
`modified` datetime NOT NULL,
`status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '1=Active | 0=Inactive',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
2. The following SQL creates a gallery_images
table with parent gallery identifier field (gallery_id) in the MySQL database.
CREATE TABLE `gallery_images` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`gallery_id` int(11) NOT NULL,
`file_name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`uploaded_on` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
The DB class handles all the database related operations (connect, insert, update, and delete). Specify the database host ($dbHost
), username ($dbUsername
), password ($dbPassword
), and name ($dbName
) as per your MySQL database credentials.
<?php
/*
* DB Class
* This class is used for database related (connect, insert, update, and delete) operations
* @author CodexWorld.com
* @url http://www.codexworld.com
* @license http://www.codexworld.com/license
*/
class DB{
private $dbHost = "localhost";
private $dbUsername = "root";
private $dbPassword = "root";
private $dbName = "codexworld";
private $galleryTbl = "gallery";
private $imgTbl = "gallery_images";
public function __construct(){
if(!isset($this->db)){
// Connect to the database
$conn = new mysqli($this->dbHost, $this->dbUsername, $this->dbPassword, $this->dbName);
if($conn->connect_error){
die("Failed to connect with MySQL: " . $conn->connect_error);
}else{
$this->db = $conn;
}
}
}
/*
* Returns rows from the database based on the conditions
* @param string name of the table
* @param array select, where, order_by, limit and return_type conditions
*/
public function getRows($conditions = array()){
$sql = 'SELECT ';
$sql .= '*, (SELECT file_name FROM '.$this->imgTbl.' WHERE gallery_id = '.$this->galleryTbl.'.id ORDER BY id DESC LIMIT 1) as default_image';
$sql .= ' FROM '.$this->galleryTbl;
if(array_key_exists("where",$conditions)){
$sql .= ' WHERE ';
$i = 0;
foreach($conditions['where'] as $key => $value){
$pre = ($i > 0)?' AND ':'';
$sql .= $pre.$key." = '".$value."'";
$i++;
}
}
if(array_key_exists("order_by",$conditions)){
$sql .= ' ORDER BY '.$conditions['order_by'];
}else{
$sql .= ' ORDER BY id DESC ';
}
if(array_key_exists("start",$conditions) && array_key_exists("limit",$conditions)){
$sql .= ' LIMIT '.$conditions['start'].','.$conditions['limit'];
}elseif(!array_key_exists("start",$conditions) && array_key_exists("limit",$conditions)){
$sql .= ' LIMIT '.$conditions['limit'];
}
$result = $this->db->query($sql);
if(array_key_exists("return_type",$conditions) && $conditions['return_type'] != 'all'){
switch($conditions['return_type']){
case 'count':
$data = $result->num_rows;
break;
case 'single':
$data = $result->fetch_assoc();
if(!empty($data)){
$sql = 'SELECT * FROM '.$this->imgTbl.' WHERE gallery_id = '.$data['id'];
$result = $this->db->query($sql);
$imgData = array();
if($result->num_rows > 0){
while($row = $result->fetch_assoc()){
$imgData[] = $row;
}
}
$data['images'] = $imgData;
}
break;
default:
$data = '';
}
}else{
if($result->num_rows > 0){
while($row = $result->fetch_assoc()){
$data[] = $row;
}
}
}
return !empty($data)?$data:false;
}
public function getImgRow($id){
$sql = 'SELECT * FROM '.$this->imgTbl.' WHERE id = '.$id;
$result = $this->db->query($sql);
return ($result->num_rows > 0)?$result->fetch_assoc():false;
}
/*
* Insert data into the database
* @param string name of the table
* @param array the data for inserting into the table
*/
public function insert($data){
if(!empty($data) && is_array($data)){
$columns = '';
$values = '';
$i = 0;
if(!array_key_exists('created',$data)){
$data['created'] = date("Y-m-d H:i:s");
}
if(!array_key_exists('modified',$data)){
$data['modified'] = date("Y-m-d H:i:s");
}
foreach($data as $key=>$val){
$pre = ($i > 0)?', ':'';
$columns .= $pre.$key;
$values .= $pre."'".$this->db->real_escape_string($val)."'";
$i++;
}
$query = "INSERT INTO ".$this->galleryTbl." (".$columns.") VALUES (".$values.")";
$insert = $this->db->query($query);
return $insert?$this->db->insert_id:false;
}else{
return false;
}
}
public function insertImage($data){
if(!empty($data) && is_array($data)){
$columns = '';
$values = '';
$i = 0;
if(!array_key_exists('uploaded_on',$data)){
$data['uploaded_on'] = date("Y-m-d H:i:s");
}
foreach($data as $key=>$val){
$pre = ($i > 0)?', ':'';
$columns .= $pre.$key;
$values .= $pre."'".$this->db->real_escape_string($val)."'";
$i++;
}
$query = "INSERT INTO ".$this->imgTbl." (".$columns.") VALUES (".$values.")";
$insert = $this->db->query($query);
return $insert?$this->db->insert_id:false;
}else{
return false;
}
}
/*
* Update data into the database
* @param string name of the table
* @param array the data for updating into the table
* @param array where condition on updating data
*/
public function update($data, $conditions){
if(!empty($data) && is_array($data)){
$colvalSet = '';
$whereSql = '';
$i = 0;
if(!array_key_exists('modified',$data)){
$data['modified'] = date("Y-m-d H:i:s");
}
foreach($data as $key=>$val){
$pre = ($i > 0)?', ':'';
$colvalSet .= $pre.$key."='".$this->db->real_escape_string($val)."'";
$i++;
}
if(!empty($conditions)&& is_array($conditions)){
$whereSql .= ' WHERE ';
$i = 0;
foreach($conditions as $key => $value){
$pre = ($i > 0)?' AND ':'';
$whereSql .= $pre.$key." = '".$value."'";
$i++;
}
}
$query = "UPDATE ".$this->galleryTbl." SET ".$colvalSet.$whereSql;
$update = $this->db->query($query);
return $update?$this->db->affected_rows:false;
}else{
return false;
}
}
/*
* Delete data from the database
* @param string name of the table
* @param array where condition on deleting data
*/
public function delete($conditions){
$whereSql = '';
if(!empty($conditions)&& is_array($conditions)){
$whereSql .= ' WHERE ';
$i = 0;
foreach($conditions as $key => $value){
$pre = ($i > 0)?' AND ':'';
$whereSql .= $pre.$key." = '".$value."'";
$i++;
}
}
$query = "DELETE FROM ".$this->galleryTbl.$whereSql;
$delete = $this->db->query($query);
return $delete?true:false;
}
public function deleteImage($conditions){
$whereSql = '';
if(!empty($conditions)&& is_array($conditions)){
$whereSql .= ' WHERE ';
$i = 0;
foreach($conditions as $key => $value){
$pre = ($i > 0)?' AND ':'';
$whereSql .= $pre.$key." = '".$value."'";
$i++;
}
}
$query = "DELETE FROM ".$this->imgTbl.$whereSql;
$delete = $this->db->query($query);
return $delete?true:false;
}
}
The Bootstrap 4 library is used to design the table, list, form fields, and links. So, include the CSS file of the Bootstrap library. If you don’t want to use Bootstrap, omit it from include.
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css">
Initially, all the gallery data is retrieved from the database and listed in a tabular view with the view, add, edit, and delete buttons.
<?php
// Start session
session_start();
// Include and initialize DB class
require_once 'DB.class.php';
$db = new DB();
// Fetch the gallery data
$images = $db->getRows();
// Get session data
$sessData = !empty($_SESSION['sessData'])?$_SESSION['sessData']:'';
// Get status message from session
if(!empty($sessData['status']['msg'])){
$statusMsg = $sessData['status']['msg'];
$statusMsgType = $sessData['status']['type'];
unset($_SESSION['sessData']['status']);
}
?>
<!-- Display status message -->
<?php if(!empty($statusMsg)){ ?>
<div class="col-xs-12">
<div class="alert alert-<?php echo $statusMsgType; ?>"><?php echo $statusMsg; ?></div>
</div>
<?php } ?>
<div class="row">
<div class="col-md-12 head">
<h5>Images</h5>
<!-- Add link -->
<div class="float-right">
<a href="addEdit.php" class="btn btn-success"><i class="plus"></i> New Gallery</a>
</div>
</div>
<!-- List the images -->
<table class="table table-striped table-bordered">
<thead class="thead-dark">
<tr>
<th width="5%">#</th>
<th width="10%"></th>
<th width="40%">Title</th>
<th width="19%">Created</th>
<th width="8%">Status</th>
<th width="18%">Action</th>
</tr>
</thead>
<tbody>
<?php
if(!empty($images)){ $i=0;
foreach($images as $row){ $i++;
$defaultImage = !empty($row['default_image'])?'<img src="uploads/images/'.$row['default_image'].'" alt="" />':'';
$statusLink = ($row['status'] == 1)?'postAction.php?action_type=block&id='.$row['id']:'postAction.php?action_type=unblock&id='.$row['id'];
$statusTooltip = ($row['status'] == 1)?'Click to Inactive':'Click to Active';
?>
<tr>
<td><?php echo $i; ?></td>
<td><?php echo $defaultImage; ?></td>
<td><?php echo $row['title']; ?></td>
<td><?php echo $row['created']; ?></td>
<td><a href="<?php echo $statusLink; ?>" title="<?php echo $statusTooltip; ?>"><span class="badge <?php echo ($row['status'] == 1)?'badge-success':'badge-danger'; ?>"><?php echo ($row['status'] == 1)?'Active':'Inactive'; ?></span></a></td>
<td>
<a href="view.php?id=<?php echo $row['id']; ?>" class="btn btn-primary">view</a>
<a href="addEdit.php?id=<?php echo $row['id']; ?>" class="btn btn-warning">edit</a>
<a href="postAction.php?action_type=delete&id=<?php echo $row['id']; ?>" class="btn btn-danger" onclick="return confirm('Are you sure to delete data?')?true:false;">delete</a>
</td>
</tr>
<?php } }else{ ?>
<tr><td colspan="6">No gallery found...</td></tr>
<?php } ?>
</tbody>
</table>
</div>
In the view.php
and addEdit.php
files, the image deletes functionality is integrated. The jQuery is used to delete images from the gallery via Ajax.
Include the jQuery library where the gallery images delete functionality is used.
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
The deleteImage() function initiate AJAX request to delete image from gallery.
postAction.php
file. <script>
function deleteImage(id){
var result = confirm("Are you sure to delete?");
if(result){
$.post( "postAction.php", {action_type:"img_delete",id:id}, function(resp) {
if(resp == 'ok'){
$('#imgb_'+id).remove();
alert('The image has been removed from the gallery');
}else{
alert('Some problem occurred, please try again.');
}
});
}
}
</script>
In the view.php
file, the gallery information is displayed.
deleteImage()
function is triggered and the respective image is removed from the gallery through jQuery Ajax using PHP.<?php
if(empty($_GET['id'])){
header("Location: manage.php");
}
// Include and initialize DB class
require_once 'DB.class.php';
$db = new DB();
$conditions['where'] = array(
'id' => $_GET['id'],
);
$conditions['return_type'] = 'single';
$galData = $db->getRows($conditions);
?>
<div class="row">
<div class="col-md-12">
<h5><?php echo !empty($galData['title'])?$galData['title']:''; ?></h5>
<?php if(!empty($galData['images'])){ ?>
<div class="gallery-img">
<?php foreach($galData['images'] as $imgRow){ ?>
<div class="img-box" id="imgb_<?php echo $imgRow['id']; ?>">
<img src="uploads/images/<?php echo $imgRow['file_name']; ?>">
<a href="javascript:void(0);" class="badge badge-danger" onclick="deleteImage('<?php echo $imgRow['id']; ?>')">delete</a>
</div>
<?php } ?>
</div>
<?php } ?>
</div>
<a href="index.php" class="btn btn-primary">Back to List</a>
</div>
The addEdit.php
file holds the HTML form that allows the user to select multiple image files and provide the gallery name.
postAction.php
) to upload multiple images and insert form data in the database.postAction.php
) to update the existing record in the database and upload new images to the server.<?php
// Start session
session_start();
$postData = $galData = array();
// Get session data
$sessData = !empty($_SESSION['sessData'])?$_SESSION['sessData']:'';
// Get status message from session
if(!empty($sessData['status']['msg'])){
$statusMsg = $sessData['status']['msg'];
$statusMsgType = $sessData['status']['type'];
unset($_SESSION['sessData']['status']);
}
// Get posted data from session
if(!empty($sessData['postData'])){
$postData = $sessData['postData'];
unset($_SESSION['sessData']['postData']);
}
// Get gallery data
if(!empty($_GET['id'])){
// Include and initialize DB class
require_once 'DB.class.php';
$db = new DB();
$conditions['where'] = array(
'id' => $_GET['id'],
);
$conditions['return_type'] = 'single';
$galData = $db->getRows($conditions);
}
// Pre-filled data
$galData = !empty($postData)?$postData:$galData;
// Define action
$actionLabel = !empty($_GET['id'])?'Edit':'Add';
?>
<div class="container">
<h1><?php echo $actionLabel; ?> Gallery</h1>
<hr>
<!-- Display status message -->
<?php if(!empty($statusMsg)){ ?>
<div class="col-xs-12">
<div class="alert alert-<?php echo $statusMsgType; ?>"><?php echo $statusMsg; ?></div>
</div>
<?php } ?>
<div class="row">
<div class="col-md-6">
<form method="post" action="postAction.php" enctype="multipart/form-data">
<div class="form-group">
<label>Images:</label>
<input type="file" name="images[]" class="form-control" multiple>
<?php if(!empty($galData['images'])){ ?>
<div class="gallery-img">
<?php foreach($galData['images'] as $imgRow){ ?>
<div class="img-box" id="imgb_<?php echo $imgRow['id']; ?>">
<img src="uploads/images/<?php echo $imgRow['file_name']; ?>">
<a href="javascript:void(0);" class="badge badge-danger" onclick="deleteImage('<?php echo $imgRow['id']; ?>')">delete</a>
</div>
<?php } ?>
</div>
<?php } ?>
</div>
<div class="form-group">
<label>Title:</label>
<input type="text" name="title" class="form-control" placeholder="Enter title" value="<?php echo !empty($galData['title'])?$galData['title']:''; ?>" >
</div>
<a href="index.php" class="btn btn-secondary">Back</a>
<input type="hidden" name="id" value="<?php echo !empty($galData['id'])?$galData['id']:''; ?>">
<input type="submit" name="imgSubmit" class="btn btn-success" value="SUBMIT">
</form>
</div>
</div>
</div>
This file handles the multiple files upload and add, edit, & delete operations using PHP and MySQL.
1. Add / Edit Form Submit:
insert()
and update()
methods of the DB class is used to add/update gallery data in the database.insertImage()
method of the DB class.2. Inactive Gallery (action_type => block):
update()
method of the DB class is used to update status field value in the database.3. Activate Gallery (action_type => unblock):
update()
method of the DB class is used to update status field value in the database.4. Delete Gallery (action_type => delete):
delete()
and deleteImage()
methods of the DB class is used to delete gallery and images data from the database.5. Delete Image (action_type => img_delete):
deleteImage()
method of the DB class is used to delete image data from the database.After the data manipulation, the status is stored in PHP SESSION and redirect to the respective page.
<?php
// Start session
session_start();
// Include and initialize DB class
require_once 'DB.class.php';
$db = new DB();
// File upload path
$uploadDir = "uploads/images/";
// Allow file formats
$allowTypes = array('jpg','png','jpeg','gif');
// Set default redirect url
$redirectURL = 'index.php';
$statusMsg = $errorMsg = '';
$sessData = array();
$statusType = 'danger';
if(isset($_POST['imgSubmit'])){
// Set redirect url
$redirectURL = 'addEdit.php';
// Get submitted data
$title = $_POST['title'];
$id = $_POST['id'];
// Submitted user data
$galData = array(
'title' => $title
);
// Store submitted data into session
$sessData['postData'] = $galData;
$sessData['postData']['id'] = $id;
// ID query string
$idStr = !empty($id)?'?id='.$id:'';
if(empty($title)){
$error = '<br/>Enter the gallery title.';
}
if(!empty($error)){
$statusMsg = 'Please fill all the mandatory fields.'.$error;
}else{
if(!empty($id)){
// Update data
$condition = array('id' => $id);
$update = $db->update($galData, $condition);
$galleryID = $id;
}else{
// Insert data
$insert = $db->insert($galData);
$galleryID = $insert;
}
$fileImages = array_filter($_FILES['images']['name']);
if(!empty($galleryID)){
if(!empty($fileImages)){
foreach($fileImages as $key=>$val){
// File upload path
$fileName = $galleryID.'_'.basename($fileImages[$key]);
$targetFilePath = $uploadDir . $fileName;
// Check whether file type is valid
$fileType = pathinfo($targetFilePath,PATHINFO_EXTENSION);
if(in_array($fileType, $allowTypes)){
// Upload file to server
if(move_uploaded_file($_FILES["images"]["tmp_name"][$key], $targetFilePath)){
// Image db insert
$imgData = array(
'gallery_id' => $galleryID,
'file_name' => $fileName
);
$insert = $db->insertImage($imgData);
}else{
$errorUpload .= $fileImages[$key].' | ';
}
}else{
$errorUploadType .= $fileImages[$key].' | ';
}
}
$errorUpload = !empty($errorUpload)?'Upload Error: '.trim($errorUpload, ' | '):'';
$errorUploadType = !empty($errorUploadType)?'File Type Error: '.trim($errorUploadType, ' | '):'';
$errorMsg = !empty($errorUpload)?'<br/>'.$errorUpload.'<br/>'.$errorUploadType:'<br/>'.$errorUploadType;
}
$statusType = 'success';
$statusMsg = 'Gallery images has been uploaded successfully.'.$errorMsg;
$sessData['postData'] = '';
$redirectURL = 'index.php';
}else{
$statusMsg = 'Some problem occurred, please try again.';
// Set redirect url
$redirectURL .= $idStr;
}
}
// Status message
$sessData['status']['type'] = $statusType;
$sessData['status']['msg'] = $statusMsg;
}elseif(($_REQUEST['action_type'] == 'block') && !empty($_GET['id'])){
// Update data
$galData = array('status' => 0);
$condition = array('id' => $_GET['id']);
$update = $db->update($galData, $condition);
if($update){
$statusType = 'success';
$statusMsg = 'Gallery data has been blocked successfully.';
}else{
$statusMsg = 'Some problem occurred, please try again.';
}
// Status message
$sessData['status']['type'] = $statusType;
$sessData['status']['msg'] = $statusMsg;
}elseif(($_REQUEST['action_type'] == 'unblock') && !empty($_GET['id'])){
// Update data
$galData = array('status' => 1);
$condition = array('id' => $_GET['id']);
$update = $db->update($galData, $condition);
if($update){
$statusType = 'success';
$statusMsg = 'Gallery data has been activated successfully.';
}else{
$statusMsg = 'Some problem occurred, please try again.';
}
// Status message
$sessData['status']['type'] = $statusType;
$sessData['status']['msg'] = $statusMsg;
}elseif(($_REQUEST['action_type'] == 'delete') && !empty($_GET['id'])){
// Previous image files
$conditions['where'] = array(
'id' => $_GET['id'],
);
$conditions['return_type'] = 'single';
$prevData = $db->getRows($conditions);
// Delete gallery data
$condition = array('id' => $_GET['id']);
$delete = $db->delete($condition);
if($delete){
// Delete images data
$condition = array('gallery_id' => $_GET['id']);
$delete = $db->deleteImage($condition);
// Remove files from server
if(!empty($prevData['images'])){
foreach($prevData['images'] as $img){
@unlink($uploadDir.$img['file_name']);
}
}
$statusType = 'success';
$statusMsg = 'Gallery has been deleted successfully.';
}else{
$statusMsg = 'Some problem occurred, please try again.';
}
// Status message
$sessData['status']['type'] = $statusType;
$sessData['status']['msg'] = $statusMsg;
}elseif(($_POST['action_type'] == 'img_delete') && !empty($_POST['id'])){
// Previous image data
$prevData = $db->getImgRow($_POST['id']);
// Delete gallery data
$condition = array('id' => $_POST['id']);
$delete = $db->deleteImage($condition);
if($delete){
@unlink($uploadDir.$prevData['file_name']);
$status = 'ok';
}else{
$status = 'err';
}
echo $status;die;
}
// Store status into the session
$_SESSION['sessData'] = $sessData;
// Redirect the user
header("Location: ".$redirectURL);
exit();
?>
PHP CRUD Operations with Search and Pagination
This multiple images upload management script is very useful for dynamic data management section in the web application. This script can be used for many purposes, like products management with multiple images using PHP and MySQL. You can easily enhance the functionality of this script and use in any data management section where multiple image upload functionality is needed.
Do you want to get implementation help, or enhance the functionality of this script? Click here to Submit Service Request