Trong lý thuyết kỹ thuật phần mềm, thuật ngữ "Mẫu thiết kế" thường chỉ đến một giải pháp có thể tái sử dụng, có thể được sử dụng như một mẫu để phát triển ứng dụng nhằm giải quyết các vấn đề thường gặp. Bạn có thể coi các mẫu thiết kế phần mềm như những thực tiễn tốt nhất được chính thức hóa khi phát triển các giải pháp phần mềm.
Hầu hết các mẫu thiết kế tiêu chuẩn có thể được triển khai rất hiệu quả trong việc phát triển ứng dụng bằng PHP. Trong chương này, chúng ta sẽ học cách áp dụng một số mẫu thiết kế phổ biến trong việc phát triển ứng dụng PHP.
Mẫu thiết kế singleton rất hữu ích khi bạn muốn hạn chế việc khởi tạo một đối tượng của một lớp nhất định chỉ còn một thể hiện duy nhất. Tên gọi "mẫu singleton" xuất phát từ khái niệm singleton trong Toán học. Mẫu singleton đảm bảo rằng sẽ chỉ có một thể hiện, và có thể truy cập toàn cầu vào nó trong toàn bộ ứng dụng.
Ứng dụng điển hình của mẫu singleton là tạo ra một đối tượng kết nối cơ sở dữ liệu, đối tượng này phải được tạo ra một lần trong suốt vòng đời của một ứng dụng.
Trong đoạn mã sau, lớp DataBaseConnector chỉ có thể được khởi tạo một lần duy nhất, nếu không, một thông báo sẽ được phát ra để không cho phép tạo đối tượng trùng lặp.
<?php class DataBaseConnector { private static $obj; private final function __construct() { echo __CLASS__ . " object created for first time ". PHP_EOL; } public static function getConnect() { if (!isset(self::$obj)) { self::$obj = new DataBaseConnector(); return self::$obj; } else { echo "connection object could not be created again" . PHP_EOL; } } } $obj1 = DataBaseConnector::getConnect(); $obj2 = DataBaseConnector::getConnect(); var_dump($obj1 == $obj2); ?>
Nó sẽ tạo ra đầu ra sau −
DataBaseConnector object created for first time connection object could not be created again bool(false)
Đây là một trong những mẫu thiết kế được sử dụng phổ biến nhất. Trong mẫu này, bạn không khai báo đối tượng của lớp mong muốn trực tiếp, mà một lớp khác được cung cấp, lớp này có phương thức tĩnh tạo ra đối tượng cần thiết.
Ví dụ sau đây minh họa cách hoạt động của mẫu thiết kế factory −
<?php class Automobile { private $bikeMake; private $bikeModel; public function __construct($make, $model) { $this->bikeMake = $make; $this->bikeModel = $model; } public function getMakeAndModel() { return $this->bikeMake . ' ' . $this->bikeModel; } } class AutomobileFactory { public static function create($make, $model) { return new Automobile($make, $model); } } $pulsar = AutomobileFactory::create('ktm', 'Pulsar'); print_r($pulsar->getMakeAndModel()); ?>
Nó sẽ tạo ra đầu ra sau −
ktm Pulsar
Mẫu chiến lược (strategy pattern) khuyến nghị một cách tiếp cận mà bạn đóng gói các gia đình thuật toán cụ thể, cho phép lớp khách hàng (client class) chịu trách nhiệm khởi tạo một thuật toán cụ thể. Lớp thực hiện mẫu này không có kiến thức về việc triển khai thực tế.
Dưới đây là một đoạn mã minh họa việc sử dụng mẫu chiến lược (strategy pattern). Chúng ta có một giao diện mà phương thức case() được triển khai khác nhau bởi hai lớp khác nhau. Đối tượng của lớp testdata gọi các phương thức case() tương ứng một cách gián tiếp thông qua phương thức process() của chính nó.
<?php interface example { public function case($str); } class ucase implements example { public function case($str) { return strtoupper($str); } } class lcase implements example { public function case($str) { return strtolower($str); } } class testdata { private $data; public function __construct($input) { $this->data = $input; } public function process(example $type) { return $this->data = $type->case($this->data); } } $str = "hello"; $obj = new testdata($str); echo $obj->process(new ucase) . PHP_EOL; $str = "HELLO"; echo $obj->process(new lcase); ?>
Nó sẽ tạo ra output −
HELLO Hello
MVC, viết tắt của Model, View và Controller, là một mẫu kiến trúc phần mềm rất phổ biến. Hầu hết các framework PHP như Laravel, Symfony, v.v. đều triển khai kiến trúc MVC.
Sự phân tách vai trò của từng lớp trong một ứng dụng như sau −
Model − Đề cập đến cấu trúc dữ liệu. Trong trường hợp này, là cơ sở dữ liệu.
View − Đề cập đến giao diện người dùng. HTML và CSS.
Controller − "Người trung gian" thực hiện xử lý. Nhận đầu vào từ giao diện, và làm việc với mô hình. Rõ ràng, chính các script và thư viện PHP.
View hoạt động như giao diện người dùng (GUI), Model hoạt động như phần back-end và Control hoạt động như một bộ chuyển đổi. Ở đây, ba phần này được kết nối với nhau. Nó sẽ truyền dữ liệu và truy cập dữ liệu giữa các phần với nhau.
Hãy cùng triển khai mẫu thiết kế MVC trong PHP thuần, JavaScript và HTML trong ví dụ dưới đây −
Lớp trình bày của ứng dụng là view.php, nơi hiển thị một biểu mẫu HTML. Người dùng gửi dữ liệu đến một tập lệnh điều khiển. Kết quả được trả về từ bộ điều khiển sẽ được hiển thị trên trang web với một chút JavaScript.
<!DOCTYPE html> <html> <head> <title>View (User Interface)</title> <link rel="stylesheet" href="style.css"> </head> <body> <form id="mysearch" action="controller.php" method="POST"> <input type="text" id = "nm" name="search" required> <input type="submit" value="Search"> </form> <div id="results"></div> <script> let results = document.getElementById("results"); results.innerHTML = ""; </script> <?php session_start(); if (isset($_SESSION['result'])) { $arr=$_SESSION['result']; foreach ($arr as $obj) {?> <script> results.innerHTML += "<div><?php echo $obj['id'] . "-" . $obj['name'] . "</div>"; ?>"; </script> <?php } } ?> </body> </html>
Kịch bản điều khiển yêu cầu model.php, và sử dụng đối tượng cơ sở dữ liệu, gọi phương thức select để lấy dữ liệu từ cơ sở dữ liệu. Kết quả được lưu trữ trong phiên hiện tại để có thể truy cập trên trang xem.
<?php session_start(); require "model.php"; $results = $_DB->select( "SELECT * FROM `users` WHERE `name` LIKE ?", ["%{$_POST["search"]}%"] ); $_SESSION['search'] = $_POST['search']; $_SESSION['result'] = $results; Header("Location: view.php", true); ?>
Lớp mô hình của ứng dụng được mã hóa trong "model.php". Nó thiết lập kết nối với cơ sở dữ liệu MySQL có tên là mydb, sử dụng phần mở rộng PDO.
<?php class DB { public $error = ""; private $pdo = null; private $stmt = null; var $dsn="localhost"; var $dbName="myDB"; var $username="root"; var $password=""; function __construct () { $this->pdo = new PDO("mysql:host=$this->dsn;dbname=$this-> dbName",$this->username,$this->password); } function __destruct () { if ($this->stmt!==null) { $this->stmt = null; } if ($this->pdo!==null) { $this->pdo = null; } } function select ($sql, $data=null) { $this->stmt = $this->pdo->prepare($sql); $this->stmt->execute($data); return $this->stmt->fetchAll(); } } $_DB = new DB(); ?>
Cơ sở dữ liệu mydb ở backend phải có một bảng users với các trường ID và NAME.
-- Table structure for table `users` -- CREATE TABLE `users` ( `id` bigint(20) NOT NULL, `name` varchar(255) NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; -- -- Dumping data for table `users` -- INSERT INTO `users` (`id`, `name`) VALUES (21, 'Ahmad Shaikh'), (24, 'Akshay Wadkar'), (26, 'Bridget Wooten'), (10, 'Coby Kelleigh'), (20, 'Dashan Shah'), (12, 'Elizabeth Taylor'), (41, 'Issac Newton'), (34, 'Julia Roberts'), (31, 'Junior Mahmood'), (32, 'Kailas Bende'), (47, 'Karan Sharma'), (16, 'Kenneth Sanders'), (28, 'Kirstie Thomas'), (33, 'Lawrence Murphy'), (14, 'Leah Shan'), (51, 'Marcus Best'), (29, 'Maya Pande'), (50, 'Nathaniel Khan'), (6, 'Richard Breann'), (54, 'Rowan Avalos'), (3, 'Rusty Terry'), (37, 'Sacha Gross'), (27, 'Sally Castillo'), (11, 'Sarah Sanders'), (18, 'Seth Sonnel'), (38, 'Shannon Peterson'), (25, 'Shayan Clements'), (49, 'Shoaib Vickers'), (43, 'Simran Kaur'), (35, 'Sulaiman Gilmour'), (44, 'Taran Morin'), (48, 'Taran Morin'), (22, 'Thelma Kim'), (8, 'Tillie Sharalyn'), (36, 'Virgil Collier');
Bắt đầu ứng dụng bằng cách truy cập "http://localhost/view.php" trong trình duyệt. Nhập một từ khóa tìm kiếm tương ứng với các tên có các chữ cái cần thiết.