Php 简明教程
PHP – Design Patterns
在软件工程理论中,“设计模式”一词通常是指可重复使用的解决方案,该解决方案可用作模板,以便开发应用来解决常见问题。你可以将软件设计模式视为开发软件解决方案时的正规最佳实践。
In the theory of software engineering, the term "Design patterns" generally refers to a reusable solution that can be used as a template for developing applications to address commonly occurring problems. You can consider the software design patterns as formalized best practices when developing software solutions.
大多数标准设计模式在使用 PHP 开发应用时可以非常有效地实现。在本章中,我们将了解如何在开发 PHP 应用时应用一些流行设计模式。
Most of the standard design patterns can be very effectively implemented in developing applications in PHP. In this chapter, we shall learn how to apply some of the popular design patterns in developing PHP applications.
Singleton Pattern
当你希望将某个类的对象实例化限制为仅一个实例时,单例设计模式很有用。名称“单例模式”源自数学中的单例概念。单例模式确保只有一个实例,在整个应用中可以全局访问它。
The singleton design pattern is useful when you want to restrict the instantiation of an object of a certain class to only one instance. The name "singleton pattern" comes from the concept of singleton in Mathematics. Singleton pattern ensures that there will be only one instance, having a global access to it throughout the application.
单例模式的典型应用是创建数据库连接对象,该对象必须在应用的生命周期中创建一次。
Typical application of singleton pattern is creation of a database connection object, which must be created once in the lifetime of an application.
Example
在以下代码中,DataBaseConnector 类只能实例化一次,否则将发出不允许重复对象的消息。
In the following code, the DataBaseConnector class can be instantiated only once, otherwise a message that disallows duplicate object will be issued.
<?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);
?>
它将生成如下输出:
It will produce the following output −
DataBaseConnector object created for first time
connection object could not be created again
bool(false)
Factory Pattern
这是最常用的设计模式之一。在此模式中,你并不直接声明所需类的对象,而是提供了另一个类,其静态方法创建所需对象。
This is one of the most commonly used design patterns. In this pattern, you don’t declare the object of the desired class directly, but another class is provided whose static method creates the required object.
Example
以下示例演示了工厂设计模式的工作原理 −
The following example demonstrates how factory design pattern works −
<?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());
?>
它将生成如下输出:
It will produce the following output −
ktm Pulsar
Strategy Pattern
策略模式推荐使用以下方法:封装特定的算法族,允许负责实例化特定算法的客户端类。实现该模式的类不了解实际的实现。
The strategy pattern recommends an approach where you encapsulate specific families of algorithms allowing the client class responsible for instantiating a particular algorithm. The class that implements the pattern has no knowledge of the actual implementation.
Example
以下代码演示了策略模式的使用。我们有一个接口,其 case() 方法由两个不同的类以不同的方式实现。testdata 类的对象通过自己的 process() 方法间接调用各自的 case() 方法。
Here is a code that demonstrates the use of strategy pattern. We have an interface whose case() method is implemented differently by two different classes. The object of testdata class calls the respective case() methods indirectly through its own process() method.
<?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);
?>
它将生成以下 output −
It will produce the following output −
HELLO
Hello
MVC Design Pattern
MVC(代表模型、视图和控制器)是一种非常流行的软件架构模式。大多数 PHP 网络(例如 Laravel、Symfony 等)都实现了 MVC 架构。
MVC, which stands for Model, View and Controller, is a very popular softeware architecture pattern. Most of the PHP networks such as Laravel, Symfony etc. implement the MVC architecture.
应用中每个层的角色分离如下 −
The separation of the role of each layer in an application is as follows −
-
Model − Refers to the data structure. In this case, the database.
-
View − Refers to the user interface. The HTML and CSS.
-
Controller − The "middleman" doing the processing. Accepts input from the view, and works with the model. Self-explanatory, the PHP scripts and libraries themselves.
视图充当 GUI,模型充当后端,而控制器则充当适配器。在这里,三个部分相互连接。它会传递数据并在彼此之间访问数据。
The View acts as the GUI, the Model acts as the back-end and the Control acts as an adapter. Here, three parts are interconnected with each other. It will pass the data and access the data between each other.
Example
让我们在以下示例中用纯 PHP、JavaScript 和 HTML 实现 MVC 设计模式 −
Let us implement the MVC design pattern in pure PHP, JavaScript and HTML in the example below −
应用的表示层是 view.php,它呈现 HTML 表单。用户将数据提交给控制器脚本。控制器返回的结果使用一些 JavaScript 在网页上呈现。
The presentation layer of the application is view.php, which renders a HTML form. The user submits the data to a controller script. The result returned by the controller is rendered on the web page with a bit of 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>
控制器脚本需要 model.php,并使用数据库对象,调用 select 方法从数据库中获取数据。结果存储在当前会话中,以便在视图页面上访问它。
The controller script requires model.php, and uses the database object, calls the select method to fetch data from the database. The result is stored in the current session so that it can be accessed on the view page.
<?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);
?>
应用的模型层在“model.php”中编码。它使用 PDO 扩展与名为 mydb 的 mysql 数据库建立连接。
The model layer of the application is coded in "model.php". It establishes connection with mysql database named mydb, using PDO extension.
<?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();
?>
后端 mydb 数据库必须有一个包含 ID 和 NAME 字段的 users 表。
The backend mydb database must have a users table with ID and NAME fields.
-- 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');
在浏览器中访问 "http://localhost/view.php" 以启动应用程序。输入与包含必需字母的名称相对应的搜索词。
Start the application by visiting "http://localhost/view.php" in the browser. Enter a search term corresponding to the names having required letters.