Trong ví dụ này, chúng ta xây dựng một ứng dụng PHP theo mô hình MVC (Model - View - Controller) mà không sử dụng framework.
📂 Cấu trúc thư mục
project/
│
├── app/
│ ├── controllers/
│ │ └── ProductController.php
│ │
│ ├── models/
│ │ └── ProductModel.php
│ │
│ └── views/
│ └── home.php
│
├── config/
│ └── Database.php
│
└── public/
└── index.php
1️⃣ Database
File:
config/Database.php
<?php
class Database
{
public static function connect()
{
return mysqli_connect(
"localhost",
"root",
"",
"shop_dienthoai"
);
}
}
Nhiệm vụ
Kết nối MySQL.
Trả về đối tượng kết nối.
Các Model sẽ dùng chung class này.
phpMyadmin tạo database shop_dienthoai trước.-- Tạo database
CREATE DATABASE IF NOT EXISTS shop_dienthoai
CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci;
-- Chọn database
USE shop_dienthoai;
-- Tạo bảng products
CREATE TABLE products (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL
);
-- Dữ liệu mẫu
INSERT INTO products (name) VALUES
('iPhone 16 Pro Max'),
('Samsung Galaxy S25 Ultra'),
('Xiaomi 15 Pro'),
('OPPO Find X8 Pro'),
('Google Pixel 10');
2️⃣ Model
File:
app/models/ProductModel.php
<?php
class ProductModel
{
private $conn;
public function __construct()
{
$this->conn = Database::connect();
}
public function getAll()
{
$result = mysqli_query($this->conn, "SELECT * FROM products");
$products = [];
while ($row = mysqli_fetch_assoc($result)) {
$products[] = $row;
}
return $products;
}
}
Nhiệm vụ
Model chỉ làm việc với dữ liệu.
Trong ví dụ trên:
Kết nối database.
Thực hiện câu lệnh SQL.
Trả về mảng sản phẩm.
Model không hiển thị HTML và không xử lý giao diện.
3️⃣ Controller
File:
app/controllers/ProductController.php
<?php
class ProductController
{
public function index()
{
$model = new ProductModel();
$products = $model->getAll();
include ROOT . "/app/views/home.php";
}
}
Nhiệm vụ
Controller là trung gian giữa Model và View.
Quy trình:
Tạo Model.
Gọi Model lấy dữ liệu.
Đưa dữ liệu sang View.
View hiển thị kết quả.
Controller không viết SQL và không tạo HTML.
4️⃣ View
File:
app/views/home.php
<h1>Danh sách sản phẩm</h1>
<?php foreach($products as $row): ?>
<p><?= $row["name"] ?></p>
<?php endforeach; ?>
Nhiệm vụ
View chỉ nhận dữ liệu từ Controller rồi hiển thị.
Trong ví dụ này:
Không kết nối database.
Không chạy SQL.
Chỉ lặp mảng
$products.
5️⃣ Front Controller
File:
public/index.php
<?php
define('ROOT', dirname(__DIR__));
require_once ROOT . '/config/Database.php';
require_once ROOT . '/app/models/ProductModel.php';
require_once ROOT . '/app/controllers/ProductController.php';
$controller = new ProductController();
$controller->index();
Đây là điểm bắt đầu của toàn bộ ứng dụng.
Nó thực hiện:
Khai báo hằng số
ROOT.Nạp các class cần thiết.
Khởi tạo Controller.
Gọi action
index().
🔄 Luồng hoạt động của MVC
Trình duyệt
│
▼
public/index.php
│
▼
ProductController
│
▼
ProductModel
│
▼
Database
│
▼
MySQL
│
▼
ProductModel
│
▼
ProductController
│
▼
View (home.php)
│
▼
Hiển thị HTML
📌 Vai trò của từng thành phần
| Thành phần | Chức năng |
|---|---|
| Database | Kết nối MySQL |
| Model | Xử lý dữ liệu |
| Controller | Điều phối chương trình |
| View | Hiển thị giao diện |
| index.php | Điểm vào của ứng dụng |
Ưu điểm của mô hình MVC
Tách biệt giao diện và dữ liệu.
Code dễ đọc.
Dễ bảo trì.
Có thể mở rộng thành Router.
Dễ chuyển sang Framework như Laravel hoặc CodeIgniter.
Lưu ý về require_once
Trong ví dụ trên, tất cả các class được nạp thủ công bằng:
require_once ...
Cách này phù hợp với dự án nhỏ, nhưng khi số lượng Controller và Model tăng lên sẽ phát sinh một số bất tiện:
Phải tự thêm
require_oncemỗi khi tạo class mới.Nếu đổi tên file hoặc namespace thì phải sửa nhiều nơi.
Một số môi trường (đặc biệt khi dùng OPcache hoặc cấu hình Apache) có thể khiến việc đổi tên file, thêm class hoặc thay đổi đường dẫn chưa được nhận ngay, dẫn đến cảm giác phải Reload/Restart Apache mới hoạt động đúng.
Trong các dự án lớn, người ta thường sử dụng Autoload (ví dụ spl_autoload_register() hoặc Composer PSR-4) để PHP tự động nạp class khi cần. Khi đó, gần như không còn phải viết require_once cho từng Controller hoặc Model nữa và việc phát triển trở nên thuận tiện hơn rất nhiều.
p/S: xem thêm MVC viết theo phong cách API tại đây.
(chỉ cần link API là phần view lấy được dữ liệu dù bất kỳ ngôn ngữ nào)




Không có nhận xét nào:
Đăng nhận xét