Tạo chức năng CRUD (Thêm, Sửa, Xóa, Xem) upload hình Sản phẩm (upload đơn, mỗi lần 1 file)
- Để upload file lên Server thì chúng ta phải sử dụng form có thuộc tính
enctype="multipart/form-data" và phương thức POST , thẻ input sẽ có type="file" .
- Khi chúng ta upload một file lên thì trên Server sẽ nhận được 5 thông số cho một file, và PHP sẽ dựa vào các thông số đó để tiến hành upload, các thông số đó là:
name : Tên của file chúng ta upload
type : Kiểu file mà chúng ta upload (hình ảnh, word, …)
tmp_name : Đường dẫn đến file tạm trên web server
error : Trạng thái của file chúng ta upload, 0 => không có lỗi
size : Kích thước của file chúng ta upload
Lưu đồ hoạt động của quá trình Upload file từ Client lên Server
Step 1: tạo cấu trúc thư mục cho chức năng CRUD Hình Sản phẩm
- Để tiện cho việc quản lý, ta sẽ tạo cấu trúc thư mục tương ứng với tên của từng chức năng
- Tạo thư mục
/backend/functions/hinhsanpham dùng để quản lý các chức năng CRUD của danh mục Hình sản phẩm
Step 2: tạo chức năng create dùng để hiển thị FORM thêm mới Hình Sản phẩm
- Tạo file
/backend/functions/hinhsanpham/create.php để xử lý logic/nghiệp vụ
- Nội dung file:
<!-- Nhúng file cấu hình để xác định được Tên và Tiêu đề của trang hiện tại người dùng đang truy cập -->
<?php include_once(__DIR__ . '/../../layouts/config.php'); ?>
<!DOCTYPE html>
<html>
<head>
<!-- Nhúng file quản lý phần HEAD -->
<?php include_once(__DIR__ . '/../../layouts/head.php'); ?>
</head>
<body class="d-flex flex-column h-100">
<!-- header -->
<?php include_once(__DIR__ . '/../../layouts/partials/header.php'); ?>
<!-- end header -->
<div class="container-fluid">
<div class="row">
<!-- sidebar -->
<?php include_once(__DIR__ . '/../../layouts/partials/sidebar.php'); ?>
<!-- end sidebar -->
<main role="main" class="col-md-10 ml-sm-auto px-4 mb-2">
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
<h1 class="h2">Thêm mới</h1>
</div>
<!-- Block content -->
<?php
// Hiển thị tất cả lỗi trong PHP
// Chỉ nên hiển thị lỗi khi đang trong môi trường Phát triển (Development)
// Không nên hiển thị lỗi trên môi trường Triển khai (Production)
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
// Truy vấn database
// 1. Include file cấu hình kết nối đến database, khởi tạo kết nối $conn
include_once(__DIR__ . '/../../../dbconnect.php');
/* ---
--- 2.Truy vấn dữ liệu sản phẩm
---
*/
// Chuẩn bị câu truy vấn sản phẩm
$sqlSanPham = "select * from `sanpham`";
// Thực thi câu truy vấn SQL để lấy về dữ liệu
$resultSanPham = mysqli_query($conn, $sqlSanPham);
// Khi thực thi các truy vấn dạng SELECT, dữ liệu lấy về cần phải phân tích để sử dụng
// Thông thường, chúng ta sẽ sử dụng vòng lặp while để duyệt danh sách các dòng dữ liệu được SELECT
// Ta sẽ tạo 1 mảng array để chứa các dữ liệu được trả về
$dataSanPham = [];
while ($rowSanPham = mysqli_fetch_array($resultSanPham, MYSQLI_ASSOC)) {
// Sử dụng hàm sprintf() để chuẩn bị mẫu câu với các giá trị truyền vào tương ứng từng vị trí placeholder
$sp_tomtat = sprintf(
"Sản phẩm %s, giá: %s",
$rowSanPham['sp_ten'],
number_format($rowSanPham['sp_gia'], 2, ".", ",") . ' vnđ'
);
$dataSanPham[] = array(
'sp_ma' => $rowSanPham['sp_ma'],
'sp_tomtat' => $sp_tomtat,
);
}
// var_dump($dataSanPham);die;
/* --- End Truy vấn dữ liệu sản phẩm --- */
?>
<!-- Form cho phép người dùng upload file lên Server bắt buộc phải có thuộc tính enctype="multipart/form-data" -->
<form name="frmhinhsanpham" id="frmhinhanpham" method="post" action="" enctype="multipart/form-data">
<div class="form-group">
<label for="sp_ma">Sản phẩm</label>
<select class="form-control" id="sp_ma" name="sp_ma">
<?php foreach ($dataSanPham as $sanpham) : ?>
<option value="<?= $sanpham['sp_ma'] ?>"><?= $sanpham['sp_tomtat'] ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="form-group">
<label for="hsp_tentaptin">Tập tin ảnh</label>
<!-- Tạo khung div hiển thị ảnh cho người dùng Xem trước khi upload file lên Server -->
<div class="preview-img-container">
<img src="/php/myhand/assets/shared/img/default-image_600.png" id="preview-img" width="200px" />
</div>
<!-- Input cho phép người dùng chọn FILE -->
<input type="file" class="form-control" id="hsp_tentaptin" name="hsp_tentaptin">
</div>
<button class="btn btn-primary" name="btnSave">Lưu</button>
<a href="index.php" class="btn btn-outline-secondary" name="btnBack" id="btnBack">Quay về</a>
</form>
<?php
// 3. Nếu người dùng có bấm nút Đăng ký thì thực thi câu lệnh UPDATE
if (isset($_POST['btnSave'])) {
// Lấy dữ liệu người dùng hiệu chỉnh gởi từ REQUEST POST
$sp_ma = $_POST['sp_ma'];
// Nếu người dùng có chọn file để upload
if (isset($_FILES['hsp_tentaptin'])) {
// Đường dẫn để chứa thư mục upload trên ứng dụng web của chúng ta. Các bạn có thể tùy chỉnh theo ý các bạn.
// Ví dụ: các file upload sẽ được lưu vào thư mục ../../../assets/uploads
$upload_dir = __DIR__ . "/../../../assets/uploads/";
// Các hình ảnh sẽ được lưu trong thư mục con `products` để tiện quản lý
$subdir = 'products/';
// Đối với mỗi file, sẽ có các thuộc tính như sau:
// $_FILES['hsp_tentaptin']['name'] : Tên của file chúng ta upload
// $_FILES['hsp_tentaptin']['type'] : Kiểu file mà chúng ta upload (hình ảnh, word, excel, pdf, txt, ...)
// $_FILES['hsp_tentaptin']['tmp_name'] : Đường dẫn đến file tạm trên web server
// $_FILES['hsp_tentaptin']['error'] : Trạng thái của file chúng ta upload, 0 => không có lỗi
// $_FILES['hsp_tentaptin']['size'] : Kích thước của file chúng ta upload
// 3.1. Chuyển file từ thư mục tạm vào thư mục Uploads
// Nếu file upload bị lỗi, tức là thuộc tính error > 0
if ($_FILES['hsp_tentaptin']['error'] > 0) {
echo 'File Upload Bị Lỗi'; die;
} else {
// Để tránh trường hợp có 2 người dùng cùng lúc upload tập tin trùng tên nhau
// Ví dụ:
// - Người 1: upload tập tin hình ảnh tên `hoahong.jpg`
// - Người 2: cũng upload tập tin hình ảnh tên `hoahong.jpg`
// => dẫn đến tên tin trong thư mục chỉ còn lại tập tin người dùng upload cuối cùng
// Cách giải quyết đơn giản là chúng ta sẽ ghép thêm ngày giờ vào tên file
$hsp_tentaptin = $_FILES['hsp_tentaptin']['name'];
$tentaptin = date('YmdHis') . '_' . $hsp_tentaptin; //20200530154922_hoahong.jpg
// Tiến hành di chuyển file từ thư mục tạm trên server vào thư mục chúng ta muốn chứa các file uploads
// Ví dụ: move file từ C:\xampp\tmp\php6091.tmp -> C:/xampp/htdocs/learning.nentang.vn/php/twig/assets/uploads/hoahong.jpg
// var_dump($_FILES['hsp_tentaptin']['tmp_name']);
// var_dump($upload_dir . $subdir . $tentaptin);
move_uploaded_file($_FILES['hsp_tentaptin']['tmp_name'], $upload_dir . $subdir . $tentaptin);
}
// 3.2. Lưu thông tin file upload vào database
// Câu lệnh INSERT
$sql = "INSERT INTO `hinhsanpham` (hsp_tentaptin, sp_ma) VALUES ('$tentaptin', $sp_ma);";
// print_r($sql); die;
// Thực thi INSERT
mysqli_query($conn, $sql);
// Đóng kết nối
mysqli_close($conn);
// Sau khi cập nhật dữ liệu, tự động điều hướng về trang Danh sách
echo '<script>location.href = "index.php";</script>';
}
}
?>
<!-- End block content -->
</main>
</div>
</div>
<!-- footer -->
<?php include_once(__DIR__ . '/../../layouts/partials/footer.php'); ?>
<!-- end footer -->
<!-- Nhúng file quản lý phần SCRIPT JAVASCRIPT -->
<?php include_once(__DIR__ . '/../../layouts/scripts.php'); ?>
<!-- Các file Javascript sử dụng riêng cho trang này, liên kết tại đây -->
<script>
// Hiển thị ảnh preview (xem trước) khi người dùng chọn Ảnh
const reader = new FileReader();
const fileInput = document.getElementById("hsp_tentaptin");
const img = document.getElementById("preview-img");
reader.onload = e => {
img.src = e.target.result;
}
fileInput.addEventListener('change', e => {
const f = e.target.files[0];
reader.readAsDataURL(f);
})
</script>
</body>
</html>
Step 3: tạo chức năng index dùng để hiển thị màn hình danh sách các Hình Sản phẩm có trong database
- Tạo file
/backend/functions/hinhsanpham/index.php để xử lý logic/nghiệp vụ
- Nội dung file:
<!-- Nhúng file cấu hình để xác định được Tên và Tiêu đề của trang hiện tại người dùng đang truy cập -->
<?php include_once(__DIR__ . '/../../layouts/config.php'); ?>
<!DOCTYPE html>
<html>
<head>
<!-- Nhúng file quản lý phần HEAD -->
<?php include_once(__DIR__ . '/../../layouts/head.php'); ?>
</head>
<body class="d-flex flex-column h-100">
<!-- header -->
<?php include_once(__DIR__ . '/../../layouts/partials/header.php'); ?>
<!-- end header -->
<div class="container-fluid">
<div class="row">
<!-- sidebar -->
<?php include_once(__DIR__ . '/../../layouts/partials/sidebar.php'); ?>
<!-- end sidebar -->
<main role="main" class="col-md-10 ml-sm-auto px-4 mb-2">
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
<h1 class="h2">Danh sách</h1>
</div>
<!-- Block content -->
<?php
// Hiển thị tất cả lỗi trong PHP
// Chỉ nên hiển thị lỗi khi đang trong môi trường Phát triển (Development)
// Không nên hiển thị lỗi trên môi trường Triển khai (Production)
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
// Truy vấn database
// 1. Include file cấu hình kết nối đến database, khởi tạo kết nối $conn
include_once(__DIR__ . '/../../../dbconnect.php');
// 2. Chuẩn bị câu truy vấn $sql
// Sử dụng HEREDOC của PHP để tạo câu truy vấn SQL với dạng dễ đọc, thân thiện với việc bảo trì code
$sql = <<<EOT
SELECT *
FROM `hinhsanpham` hsp
JOIN `sanpham` sp on hsp.sp_ma = sp.sp_ma
EOT;
// 3. Thực thi câu truy vấn SQL để lấy về dữ liệu
$result = mysqli_query($conn, $sql);
// 4. Khi thực thi các truy vấn dạng SELECT, dữ liệu lấy về cần phải phân tích để sử dụng
// Thông thường, chúng ta sẽ sử dụng vòng lặp while để duyệt danh sách các dòng dữ liệu được SELECT
// Ta sẽ tạo 1 mảng array để chứa các dữ liệu được trả về
$data = [];
while ($row = mysqli_fetch_array($result, MYSQLI_ASSOC)) {
// Sử dụng hàm sprintf() để chuẩn bị mẫu câu với các giá trị truyền vào tương ứng từng vị trí placeholder
$sp_tomtat = sprintf(
"Sản phẩm %s, giá: %d",
$row['sp_ten'],
number_format($row['sp_gia'], 2, ".", ",") . ' vnđ'
);
$data[] = array(
'hsp_ma' => $row['hsp_ma'],
'hsp_tentaptin' => $row['hsp_tentaptin'],
'sp_tomtat' => $sp_tomtat,
);
}
/* --- End Truy vấn dữ liệu sản phẩm --- */
?>
<!-- Nút thêm mới, bấm vào sẽ hiển thị form nhập thông tin Thêm mới -->
<a href="create.php" class="btn btn-primary">
Thêm mới
</a>
<table class="table table-bordered table-hover mt-2">
<thead class="thead-dark">
<tr>
<th>Mã Hình Sản phẩm</th>
<th>Hình ảnh</th>
<th>Sản phẩm</th>
<th>Hành động</th>
</tr>
</thead>
<tbody>
<?php foreach($data as $hinhsanpham): ?>
<tr>
<td><?= $hinhsanpham['hsp_ma'] ?></td>
<td>
<img src="/php/myhand/assets/uploads/products/<?= $hinhsanpham['hsp_tentaptin'] ?>" class="img-fluid" width="100px" />
</td>
<td><?= $hinhsanpham['sp_tomtat'] ?></td>
<td>
<!-- Nút sửa, bấm vào sẽ hiển thị form hiệu chỉnh thông tin dựa vào khóa chính `hsp_ma` -->
<a href="edit.php?hsp_ma=<?= $hinhsanpham['hsp_ma'] ?>" class="btn btn-warning">
Sửa
</a>
<!-- Nút xóa, bấm vào sẽ xóa thông tin dựa vào khóa chính `sp_ma` -->
<a href="delete.php?hsp_ma=<?= $hinhsanpham['hsp_ma'] ?>" class="btn btn-danger">
Xóa
</a>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<!-- End block content -->
</main>
</div>
</div>
<!-- footer -->
<?php include_once(__DIR__ . '/../../layouts/partials/footer.php'); ?>
<!-- end footer -->
<!-- Nhúng file quản lý phần SCRIPT JAVASCRIPT -->
<?php include_once(__DIR__ . '/../../layouts/scripts.php'); ?>
<!-- Các file Javascript sử dụng riêng cho trang này, liên kết tại đây -->
<!-- <script src="..."></script> -->
</body>
</html>
Step 4: tạo chức năng delete dùng để xóa Hình Sản phẩm
- Tạo file
/backend/functions/hinhsanpham/delete.php để xử lý logic/nghiệp vụ
- Nội dung file:
<?php
// Hiển thị tất cả lỗi trong PHP
// Chỉ nên hiển thị lỗi khi đang trong môi trường Phát triển (Development)
// Không nên hiển thị lỗi trên môi trường Triển khai (Production)
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
// Truy vấn database
// 1. Include file cấu hình kết nối đến database, khởi tạo kết nối $conn
include_once(__DIR__ . '/../../../dbconnect.php');
/* ---
--- 2. Truy vấn dữ liệu Hình ảnh Sản phẩm theo khóa chính
---
*/
// Chuẩn bị câu truy vấn $sqlSelect, lấy dữ liệu ban đầu của record cần update
// Lấy giá trị khóa chính được truyền theo dạng QueryString Parameter key1=value1&key2=value2...
$hsp_ma = $_GET['hsp_ma'];
$sqlSelect = "SELECT * FROM `hinhsanpham` WHERE hsp_ma=$hsp_ma;";
// var_dump($sqlSelect);die;
// Thực thi câu truy vấn SQL để lấy về dữ liệu ban đầu của record cần update
$resultSelect = mysqli_query($conn, $sqlSelect);
$hinhsanphamRow = mysqli_fetch_array($resultSelect, MYSQLI_ASSOC); // 1 record
/* --- End Truy vấn dữ liệu Sản phẩm theo khóa chính --- */
// 3. Xóa file cũ để tránh rác trong thư mục UPLOADS
// Đường dẫn để chứa thư mục upload trên ứng dụng web của chúng ta. Các bạn có thể tùy chỉnh theo ý các bạn.
// Ví dụ: các file upload sẽ được lưu vào thư mục ../../../assets/uploads
$upload_dir = __DIR__ . "/../../../assets/uploads/";
// Các hình ảnh sẽ được lưu trong thư mục con `products` để tiện quản lý
$subdir = 'products/';
// Kiểm tra nếu file có tổn tại thì xóa file đi
$old_file = $upload_dir . $subdir . $hinhsanphamRow['hsp_tentaptin'];
if (file_exists($old_file)) {
// Hàm unlink(filepath) dùng để xóa file trong PHP
unlink($old_file);
}
// 4. Chuẩn bị câu truy vấn $sql
// Lấy giá trị khóa chính được truyền theo dạng QueryString Parameter key1=value1&key2=value2...
$hsp_ma = $_GET['hsp_ma'];
$sql = "DELETE FROM `hinhsanpham` WHERE hsp_ma=" . $hsp_ma;
// 5. Thực thi câu lệnh DELETE
$result = mysqli_query($conn, $sql);
// 6. Đóng kết nối
mysqli_close($conn);
// Sau khi cập nhật dữ liệu, tự động điều hướng về trang Danh sách
header('location:index.php');
Step 5: tạo chức năng edit dùng để hiệu chỉnh Hình Sản phẩm
- Tạo file
/backend/functions/hinhsanpham/edit.php để xử lý logic/nghiệp vụ
- Nội dung file:
<!-- Nhúng file cấu hình để xác định được Tên và Tiêu đề của trang hiện tại người dùng đang truy cập -->
<?php include_once(__DIR__ . '/../../layouts/config.php'); ?>
<!DOCTYPE html>
<html>
<head>
<!-- Nhúng file quản lý phần HEAD -->
<?php include_once(__DIR__ . '/../../layouts/head.php'); ?>
</head>
<body class="d-flex flex-column h-100">
<!-- header -->
<?php include_once(__DIR__ . '/../../layouts/partials/header.php'); ?>
<!-- end header -->
<div class="container-fluid">
<div class="row">
<!-- sidebar -->
<?php include_once(__DIR__ . '/../../layouts/partials/sidebar.php'); ?>
<!-- end sidebar -->
<main role="main" class="col-md-10 ml-sm-auto px-4 mb-2">
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
<h1 class="h2">Hiệu chỉnh</h1>
</div>
<!-- Block content -->
<?php
// Hiển thị tất cả lỗi trong PHP
// Chỉ nên hiển thị lỗi khi đang trong môi trường Phát triển (Development)
// Không nên hiển thị lỗi trên môi trường Triển khai (Production)
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
// Truy vấn database
// 1. Include file cấu hình kết nối đến database, khởi tạo kết nối $conn
include_once(__DIR__ . '/../../../dbconnect.php');
/* ---
--- 2.Truy vấn dữ liệu sản phẩm
---
*/
// Chuẩn bị câu truy vấn sản phẩm
$sqlSanPham = "select * from `sanpham`";
// Thực thi câu truy vấn SQL để lấy về dữ liệu
$resultSanPham = mysqli_query($conn, $sqlSanPham);
// Khi thực thi các truy vấn dạng SELECT, dữ liệu lấy về cần phải phân tích để sử dụng
// Thông thường, chúng ta sẽ sử dụng vòng lặp while để duyệt danh sách các dòng dữ liệu được SELECT
// Ta sẽ tạo 1 mảng array để chứa các dữ liệu được trả về
$dataSanPham = [];
while ($rowSanPham = mysqli_fetch_array($resultSanPham, MYSQLI_ASSOC)) {
// Sử dụng hàm sprintf() để chuẩn bị mẫu câu với các giá trị truyền vào tương ứng từng vị trí placeholder
$sp_tomtat = sprintf(
"Sản phẩm %s, giá: %d",
$rowSanPham['sp_ten'],
number_format($rowSanPham['sp_gia'], 2, ".", ",") . ' vnđ'
);
$dataSanPham[] = array(
'sp_ma' => $rowSanPham['sp_ma'],
'sp_tomtat' => $sp_tomtat
);
}
/* --- End Truy vấn dữ liệu sản phẩm --- */
/* ---
--- 3. Truy vấn dữ liệu Sản phẩm theo khóa chính
---
*/
// Chuẩn bị câu truy vấn $sqlSelect, lấy dữ liệu ban đầu của record cần update
// Lấy giá trị khóa chính được truyền theo dạng QueryString Parameter key1=value1&key2=value2...
$hsp_ma = $_GET['hsp_ma'];
$sqlSelect = "SELECT * FROM `hinhsanpham` WHERE hsp_ma=$hsp_ma;";
// Thực thi câu truy vấn SQL để lấy về dữ liệu ban đầu của record cần update
$resultSelect = mysqli_query($conn, $sqlSelect);
$hinhsanphamRow = mysqli_fetch_array($resultSelect, MYSQLI_ASSOC); // 1 record
/* --- End Truy vấn dữ liệu Sản phẩm theo khóa chính --- */
?>
<!-- Form cho phép người dùng upload file lên Server bắt buộc phải có thuộc tính enctype="multipart/form-data" -->
<form name="frmhinhsanpham" id="frmhinhanpham" method="post" action="" enctype="multipart/form-data">
<div class="form-group">
<label for="">Hình ảnh hiện tại</label>
<br />
<img src="/php/myhand/assets/uploads/products/<?= $hinhsanphamRow['hsp_tentaptin'] ?>" class="img-fluid" width="300px" />
</div>
<div class="form-group">
<label for="sp_ma">Sản phẩm</label>
<select class="form-control" id="sp_ma" name="sp_ma" disabled="disabled">
<?php foreach ($dataSanPham as $sanpham) : ?>
<?php if ($sanpham['sp_ma'] == $hinhsanphamRow['sp_ma']) : ?>
<option value="<?= $sanpham['sp_ma'] ?>" selected><?= $sanpham['sp_tomtat'] ?></option>
<?php else : ?>
<option value="<?= $sanpham['sp_ma'] ?>"><?= $sanpham['sp_tomtat'] ?></option>
<?php endif; ?>
<?php endforeach; ?>
</select>
</div>
<div class="form-group">
<label for="hsp_tentaptin">Tập tin ảnh</label>
<!-- Tạo khung div hiển thị ảnh cho người dùng Xem trước khi upload file lên Server -->
<div class="preview-img-container">
<img src="/php/myhand/assets/shared/img/default-image_600.png" id="preview-img" width="200px" />
</div>
<!-- Input cho phép người dùng chọn FILE -->
<input type="file" class="form-control" id="hsp_tentaptin" name="hsp_tentaptin">
</div>
<button class="btn btn-primary" name="btnSave">Lưu</button>
<a href="index.php" class="btn btn-outline-secondary" name="btnBack" id="btnBack">Quay về</a>
</form>
<?php
// 3. Nếu người dùng có bấm nút Đăng ký thì thực thi câu lệnh UPDATE
if (isset($_POST['btnSave'])) {
// Lấy dữ liệu người dùng hiệu chỉnh gởi từ REQUEST POST
$hsp_ma = $_GET['hsp_ma'];
// Nếu người dùng có chọn file để upload
if (isset($_FILES['hsp_tentaptin'])) {
// Đường dẫn để chứa thư mục upload trên ứng dụng web của chúng ta. Các bạn có thể tùy chỉnh theo ý các bạn.
// Ví dụ: các file upload sẽ được lưu vào thư mục ../../../assets/uploads
$upload_dir = __DIR__ . "/../../../assets/uploads/";
// Các hình ảnh sẽ được lưu trong thư mục con `products` để tiện quản lý
$subdir = 'products/';
// Đối với mỗi file, sẽ có các thuộc tính như sau:
// $_FILES['hsp_tentaptin']['name'] : Tên của file chúng ta upload
// $_FILES['hsp_tentaptin']['type'] : Kiểu file mà chúng ta upload (hình ảnh, word, excel, pdf, txt, ...)
// $_FILES['hsp_tentaptin']['tmp_name'] : Đường dẫn đến file tạm trên web server
// $_FILES['hsp_tentaptin']['error'] : Trạng thái của file chúng ta upload, 0 => không có lỗi
// $_FILES['hsp_tentaptin']['size'] : Kích thước của file chúng ta upload
// 3.1. Chuyển file từ thư mục tạm vào thư mục Uploads
// Nếu file upload bị lỗi, tức là thuộc tính error > 0
if ($_FILES['hsp_tentaptin']['error'] > 0) {
echo 'File Upload Bị Lỗi';
die;
} else {
// Xóa file cũ để tránh rác trong thư mục UPLOADS
// Kiểm tra nếu file có tổn tại thì xóa file đi
$old_file = $upload_dir . $subdir . $hinhsanphamRow['hsp_tentaptin'];
if (file_exists($old_file)) {
// Hàm unlink(filepath) dùng để xóa file trong PHP
unlink($old_file);
}
// Để tránh trường hợp có 2 người dùng cùng lúc upload tập tin trùng tên nhau
// Ví dụ:
// - Người 1: upload tập tin hình ảnh tên `hoahong.jpg`
// - Người 2: cũng upload tập tin hình ảnh tên `hoahong.jpg`
// => dẫn đến tên tin trong thư mục chỉ còn lại tập tin người dùng upload cuối cùng
// Cách giải quyết đơn giản là chúng ta sẽ ghép thêm ngày giờ vào tên file
$hsp_tentaptin = $_FILES['hsp_tentaptin']['name'];
$tentaptin = date('YmdHis') . '_' . $hsp_tentaptin; //20200530154922_hoahong.jpg
// Tiến hành di chuyển file từ thư mục tạm trên server vào thư mục chúng ta muốn chứa các file uploads
// Ví dụ: move file từ C:\xampp\tmp\php6091.tmp -> C:/xampp/htdocs/learning.nentang.vn/php/twig/assets/uploads/hoahong.jpg
// var_dump($_FILES['hsp_tentaptin']['tmp_name']);
// var_dump($upload_dir . $subdir . $tentaptin);
move_uploaded_file($_FILES['hsp_tentaptin']['tmp_name'], $upload_dir . $subdir . $tentaptin);
}
// 3.2. Lưu thông tin file upload vào database
// Câu lệnh UPDATE
$sql = "UPDATE `hinhsanpham` SET hsp_tentaptin='$tentaptin' WHERE hsp_ma=$hsp_ma;";
// print_r($sql); die;
// Thực thi
mysqli_query($conn, $sql);
// Đóng kết nối
mysqli_close($conn);
// Sau khi cập nhật dữ liệu, tự động điều hướng về trang Danh sách
echo '<script>location.href = "index.php";</script>';
}
}
?>
<!-- End block content -->
</main>
</div>
</div>
<!-- footer -->
<?php include_once(__DIR__ . '/../../layouts/partials/footer.php'); ?>
<!-- end footer -->
<!-- Nhúng file quản lý phần SCRIPT JAVASCRIPT -->
<?php include_once(__DIR__ . '/../../layouts/scripts.php'); ?>
<!-- Các file Javascript sử dụng riêng cho trang này, liên kết tại đây -->
<script>
// Hiển thị ảnh preview (xem trước) khi người dùng chọn Ảnh
const reader = new FileReader();
const fileInput = document.getElementById("hsp_tentaptin");
const img = document.getElementById("preview-img");
reader.onload = e => {
img.src = e.target.result;
}
fileInput.addEventListener('change', e => {
const f = e.target.files[0];
reader.readAsDataURL(f);
})
</script>
</body>
</html>
Step 6: bổ sung menu chức năng Quản lý Hình Sản phẩm bên sidebar
- Hiệu chỉnh file
/backend/layouts/partials/sidebar.php
- Nội dung file:
<nav class="col-md-2 d-none d-md-block sidebar">
<div class="sidebar-sticky">
<ul class="nav flex-column">
...
<!-- Menu Hình Sản phẩm -->
<li class="nav-item">
<a href="#hinhsanphamSubMenu" data-toggle="collapse" aria-expanded="false" class="dropdown-toggle">
Hình Sản phẩm
</a>
<ul class="collapse" id="hinhsanphamSubMenu">
<li class="nav-item">
<a href="/php/myhand/backend/functions/hinhsanpham/index.php">Danh sách</a>
</li>
<li class="nav-item">
<a href="/php/myhand/backend/functions/hinhsanpham/create.php">Thêm mới</a>
</li>
</ul>
</li>
<!-- End Sản phẩm -->
...
</ul>
</div>
</nav>
Demo
|