探索PHP的高级功能与技术
PHP 5及以上版本提供了完整的面向对象编程功能,包括类、接口、抽象类、继承、多态等特性。
类是创建对象的模板,对象是类的实例。
<?php // 定义类 class Person { // 属性 public $name; protected $age; private $salary; // 构造函数 public function __construct($name, $age, $salary) { $this->name = $name; $this->age = $age; $this->salary = $salary; } // 方法 public function sayHello() { return "你好,我是 {$this->name},今年 {$this->age} 岁。"; } // 获取私有属性的方法 public function getSalary() { return $this->salary; } } // 创建对象 $person = new Person("张三", 30, 10000); // 访问公共属性 echo $person->name; // 输出:张三 // 调用方法 echo $person->sayHello(); // 输出:你好,我是 张三,今年 30 岁。 // 通过方法访问私有属性 echo $person->getSalary(); // 输出:10000 ?>
继承允许子类继承父类的属性和方法。
<?php // 父类 class Employee { protected $name; protected $salary; public function __construct($name, $salary) { $this->name = $name; $this->salary = $salary; } public function getInfo() { return "员工: {$this->name}, 薪水: {$this->salary}"; } } // 子类 class Manager extends Employee { private $bonus; public function __construct($name, $salary, $bonus) { parent::__construct($name, $salary); $this->bonus = $bonus; } // 重写父类方法 public function getInfo() { return "经理: {$this->name}, 薪水: {$this->salary}, 奖金: {$this->bonus}"; } } $manager = new Manager("李四", 20000, 5000); echo $manager->getInfo(); // 输出:经理: 李四, 薪水: 20000, 奖金: 5000 ?>
<?php // 接口 interface Drawable { public function draw(); } // 抽象类 abstract class Shape { protected $color; public function __construct($color) { $this->color = $color; } // 抽象方法 abstract public function getArea(); public function getColor() { return $this->color; } } // 实现抽象类和接口 class Circle extends Shape implements Drawable { private $radius; public function __construct($color, $radius) { parent::__construct($color); $this->radius = $radius; } public function getArea() { return pi() * $this->radius * $this->radius; } public function draw() { return "绘制一个 {$this->color} 的圆,半径为 {$this->radius}"; } } $circle = new Circle("红色", 5); echo $circle->getArea(); // 输出:78.539816339745 echo $circle->draw(); // 输出:绘制一个 红色 的圆,半径为 5 ?>
命名空间用于解决类名、函数名和常量名冲突的问题。
<?php // file1.php namespace App\Models; class User { public function __construct() { echo "App\\Models\\User 被实例化"; } } // file2.php namespace App\Controllers; class User { public function __construct() { echo "App\\Controllers\\User 被实例化"; } } // file3.php namespace App; // 使用完全限定名称 $user1 = new Models\User(); $user2 = new Controllers\User(); // 或者使用use语句 use App\Models\User as ModelUser; use App\Controllers\User as ControllerUser; $user3 = new ModelUser(); $user4 = new ControllerUser(); ?>
PHP 8.1引入了许多新功能和改进,为开发者提供了更多的工具和可能性。
枚举类型提供了一种定义有限集合值的方式。
<?php enum Status { case Pending; case Active; case Suspended; case Cancelled; } function updateStatus(Status $status) { // 处理不同状态 return match($status) { Status::Pending => '待处理', Status::Active => '已激活', Status::Suspended => '已暂停', Status::Cancelled => '已取消', }; } $status = Status::Active; echo updateStatus($status); // 输出:已激活 // 带值的枚举 enum Currency: string { case Euro = "EUR"; case Dollar = "USD"; case Yuan = "CNY"; public function getSymbol(): string { return match($this) { self::Euro => "€", self::Dollar => "$", self::Yuan => "¥", }; } } $currency = Currency::Yuan; echo $currency->value; // 输出:CNY echo $currency->getSymbol(); // 输出:¥ ?>
只读属性允许类属性在初始化后不可修改。
<?php class User { public readonly string $name; public readonly string $email; public function __construct(string $name, string $email) { $this->name = $name; $this->email = $email; } } $user = new User("张三", "zhangsan@example.com"); echo $user->name; // 输出:张三 // 以下代码会产生错误 // $user->name = "李四"; // Fatal error: Cannot modify readonly property User::$name ?>
纤程提供了一种轻量级的协程实现,使异步编程更加简单。
<?php $fiber = new Fiber(function(): void { $value = Fiber::suspend('fiber suspended'); echo "Value used to resume fiber: ", $value, "\n"; }); $value = $fiber->start(); echo "Fiber suspended with value: ", $value, "\n"; $fiber->resume('fiber resumed'); // 输出: // Fiber suspended with value: fiber suspended // Value used to resume fiber: fiber resumed ?>
PHP 8.1允许在定义属性时直接初始化。
<?php class Product { public string $name = "默认产品"; public float $price = 0.0; public array $tags = ["新品"]; public function __construct(string $name = null, float $price = null) { if ($name !== null) { $this->name = $name; } if ($price !== null) { $this->price = $price; } } } $product1 = new Product(); echo $product1->name; // 输出:默认产品 $product2 = new Product("手机", 1999.99); echo $product2->name; // 输出:手机 ?>
设计模式是解决特定问题的可复用方案,掌握常见的设计模式可以提高代码质量和可维护性。
确保一个类只有一个实例,并提供一个全局访问点。
<?php class Database { private static $instance = null; private $connection; // 私有构造函数,防止外部实例化 private function __construct() { $this->connection = new PDO("mysql:host=localhost;dbname=test", "username", "password"); } // 获取单例实例 public static function getInstance() { if (self::$instance === null) { self::$instance = new self(); } return self::$instance; } public function query($sql) { return $this->connection->query($sql); } // 防止克隆 private function __clone() {} // 防止反序列化 private function __wakeup() {} } // 使用 $db1 = Database::getInstance(); $db2 = Database::getInstance(); // $db1 和 $db2 是同一个实例 var_dump($db1 === $db2); // 输出:bool(true) ?>
提供一个创建对象的接口,但允许子类决定实例化的类。
<?php // 产品接口 interface Vehicle { public function drive(); } // 具体产品 class Car implements Vehicle { public function drive() { return "驾驶汽车..."; } } class Bike implements Vehicle { public function drive() { return "骑自行车..."; } } class Truck implements Vehicle { public function drive() { return "驾驶卡车..."; } } // 工厂类 class VehicleFactory { public static function createVehicle($type) { switch ($type) { case 'car': return new Car(); case 'bike': return new Bike(); case 'truck': return new Truck(); default: throw new Exception("未知的车辆类型: {$type}"); } } } // 使用 $car = VehicleFactory::createVehicle('car'); echo $car->drive(); // 输出:驾驶汽车... $bike = VehicleFactory::createVehicle('bike'); echo $bike->drive(); // 输出:骑自行车... ?>
定义对象间一对多的依赖关系,当一个对象状态改变时,所有依赖它的对象都会收到通知。
<?php // 观察者接口 interface Observer { public function update(string $message); } // 具体观察者 class EmailNotifier implements Observer { private $email; public function __construct(string $email) { $this->email = $email; } public function update(string $message) { echo "向 {$this->email} 发送邮件通知: {$message}\n"; } } class SMSNotifier implements Observer { private $phone; public function __construct(string $phone) { $this->phone = $phone; } public function update(string $message) { echo "向 {$this->phone} 发送短信通知: {$message}\n"; } } // 主题 class OrderStatus { private $observers = []; private $status; public function attach(Observer $observer) { $this->observers[] = $observer; } public function detach(Observer $observer) { $key = array_search($observer, $this->observers, true); if ($key !== false) { unset($this->observers[$key]); } } public function setStatus(string $status) { $this->status = $status; $this->notify(); } private function notify() { foreach ($this->observers as $observer) { $observer->update("订单状态已更新为: {$this->status}"); } } } // 使用 $orderStatus = new OrderStatus(); $emailNotifier = new EmailNotifier("customer@example.com"); $smsNotifier = new SMSNotifier("13800138000"); $orderStatus->attach($emailNotifier); $orderStatus->attach($smsNotifier); $orderStatus->setStatus("已发货"); // 输出: // 向 customer@example.com 发送邮件通知: 订单状态已更新为: 已发货 // 向 13800138000 发送短信通知: 订单状态已更新为: 已发货 ?>
Composer是PHP的依赖管理工具,它允许你声明项目所依赖的库,并自动帮你安装和更新它们。
在Windows上,下载并运行Composer-Setup.exe。在Linux/Mac上,使用命令行安装:
curl -sS https://getcomposer.org/installer | php sudo mv composer.phar /usr/local/bin/composer
{ "name": "vendor/project-name", "description": "项目描述", "type": "project", "require": { "monolog/monolog": "^2.0", "guzzlehttp/guzzle": "^7.0" }, "require-dev": { "phpunit/phpunit": "^9.0" }, "autoload": { "psr-4": { "App\\": "src/" } } }
composer install
composer require symfony/console
composer update
Composer生成的自动加载器使得你可以轻松加载项目中的类:
<?php // 加载自动加载器 require 'vendor/autoload.php'; // 现在可以直接使用Composer安装的库 use Monolog\Logger; use Monolog\Handler\StreamHandler; // 创建日志频道 $log = new Logger('name'); $log->pushHandler(new StreamHandler('app.log', Logger::WARNING)); // 添加记录 $log->warning('警告信息'); $log->error('错误信息'); ?>
提示:Composer已成为PHP项目的标准工具,几乎所有现代PHP项目都使用Composer进行依赖管理。
保护PHP应用程序安全是每个开发者的责任。以下是一些安全最佳实践:
不安全的代码:
<?php $username = $_POST['username']; $query = "SELECT * FROM users WHERE username = '$username'"; $result = $db->query($query); ?>
安全的代码:
<?php // 使用预处理语句 $stmt = $db->prepare("SELECT * FROM users WHERE username = ?"); $stmt->bind_param("s", $_POST['username']); $stmt->execute(); $result = $stmt->get_result(); // 或使用PDO $stmt = $pdo->prepare("SELECT * FROM users WHERE username = :username"); $stmt->execute(['username' => $_POST['username']]); $result = $stmt->fetchAll(); ?>
不安全的代码:
<?php echo "欢迎, " . $_GET['name']; ?>
安全的代码:
<?php echo "欢迎, " . htmlspecialchars($_GET['name'], ENT_QUOTES, 'UTF-8'); ?>
在表单中添加CSRF令牌,并在提交表单时验证:
<?php // 在会话中存储令牌 session_start(); if (empty($_SESSION['csrf_token'])) { $_SESSION['csrf_token'] = bin2hex(random_bytes(32)); } // 在表单中包含令牌 echo '<form method="post">'; echo '<input type="hidden" name="csrf_token" value="' . $_SESSION['csrf_token'] . '">'; echo '<!-- 其他表单字段 -->'; echo '</form>'; // 验证令牌 if ($_SERVER['REQUEST_METHOD'] == 'POST') { if (!isset($_POST['csrf_token']) || $_POST['csrf_token'] !== $_SESSION['csrf_token']) { die('CSRF令牌验证失败'); } // 处理表单提交 } ?>
display_errors = Off
error_log
记录错误expose_php
设置为Off,以隐藏PHP版本信息disable_functions = exec,passthru,shell_exec,system,proc_open,popen
open_basedir
限制PHP可访问的目录