发布日期:2023年12月1日
难度等级:中级 → 高级
现代PHP开发:从过程式到面向对象的演进
PHP语言经历了从简单的脚本语言到成熟的企业级开发语言的蜕变。现代PHP开发强调面向对象编程(OOP)、设计模式应用和架构设计,本教程将通过构建一个完整的电商系统来展示这些先进理念。
技术栈概览:
- PHP 8.1+:新特性如枚举、只读属性、纤程
- Composer:现代化的依赖管理工具
- PDO:安全的数据库操作接口
- MVC模式:清晰的分层架构
- 命名空间:代码组织和自动加载
电商系统项目结构设计
首先创建清晰的项目目录结构,这是良好架构的基础:
ecommerce-system/
├── app/
│ ├── Controllers/
│ │ ├── ProductController.php
│ │ ├── UserController.php
│ │ └── OrderController.php
│ ├── Models/
│ │ ├── Product.php
│ │ ├── User.php
│ │ └── Order.php
│ ├── Views/
│ │ ├── products/
│ │ ├── users/
│ │ └── layouts/
│ └── Core/
│ ├── Router.php
│ ├── Database.php
│ └── Validator.php
├── config/
│ ├── database.php
│ └── app.php
├── public/
│ └── index.php
├── vendor/
└── composer.json
核心组件实现:从数据库到路由
1. 数据库连接层(使用PDO和单例模式)
<?php
namespace AppCore;
class Database
{
private static ?Database $instance = null;
private PDO $connection;
private function __construct()
{
$config = require __DIR__ . '/../../config/database.php';
$dsn = "mysql:host={$config['host']};dbname={$config['database']};charset={$config['charset']}";
$this->connection = new PDO($dsn, $config['username'], $config['password'], [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false
]);
}
public static function getInstance(): Database
{
if (self::$instance === null) {
self::$instance = new self();
}
return self::$instance;
}
public function getConnection(): PDO
{
return $this->connection;
}
// 防止克隆和反序列化
private function __clone() {}
public function __wakeup() {}
}
?>
2. 智能路由系统
<?php
namespace AppCore;
class Router
{
private array $routes = [];
private array $middlewares = [];
public function add(string $method, string $path, array $handler): void
{
$this->routes[] = [
'method' => strtoupper($method),
'path' => $this->normalizePath($path),
'handler' => $handler,
'middlewares' => $this->middlewares
];
// 重置中间件
$this->middlewares = [];
}
public function middleware(string $middleware): self
{
$this->middlewares[] = $middleware;
return $this;
}
public function dispatch(string $method, string $path): void
{
$method = strtoupper($method);
$path = $this->normalizePath($path);
foreach ($this->routes as $route) {
if ($this->matchRoute($route, $method, $path)) {
$this->executeHandler($route);
return;
}
}
http_response_code(404);
echo "页面未找到";
}
private function matchRoute(array $route, string $method, string $path): bool
{
return $route['method'] === $method && $route['path'] === $path;
}
private function executeHandler(array $route): void
{
[$controllerClass, $method] = $route['handler'];
// 执行中间件
foreach ($route['middlewares'] as $middleware) {
$middlewareInstance = new $middleware();
if (!$middlewareInstance->handle()) {
return;
}
}
$controller = new $controllerClass();
$controller->$method();
}
private function normalizePath(string $path): string
{
return '/' . trim($path, '/');
}
}
?>
MVC模式深度实现
1. 产品模型(使用Active Record模式)
<?php
namespace AppModels;
use AppCoreDatabase;
class Product
{
private PDO $db;
public ?int $id = null;
public string $name;
public string $description;
public float $price;
public int $stock;
public DateTime $created_at;
public function __construct()
{
$this->db = Database::getInstance()->getConnection();
}
public function save(): bool
{
if ($this->id === null) {
return $this->create();
}
return $this->update();
}
private function create(): bool
{
$sql = "INSERT INTO products (name, description, price, stock)
VALUES (:name, :description, :price, :stock)";
$stmt = $this->db->prepare($sql);
$result = $stmt->execute([
'name' => $this->name,
'description' => $this->description,
'price' => $this->price,
'stock' => $this->stock
]);
if ($result) {
$this->id = (int)$this->db->lastInsertId();
}
return $result;
}
public static function find(int $id): ?Product
{
$db = Database::getInstance()->getConnection();
$sql = "SELECT * FROM products WHERE id = ?";
$stmt = $db->prepare($sql);
$stmt->execute([$id]);
$data = $stmt->fetch();
if (!$data) {
return null;
}
$product = new Product();
$product->id = $data['id'];
$product->name = $data['name'];
$product->description = $data['description'];
$product->price = (float)$data['price'];
$product->stock = (int)$data['stock'];
$product->created_at = new DateTime($data['created_at']);
return $product;
}
public static function getAll(): array
{
$db = Database::getInstance()->getConnection();
$sql = "SELECT * FROM products ORDER BY created_at DESC";
$stmt = $db->query($sql);
$products = [];
while ($data = $stmt->fetch()) {
$product = new Product();
$product->id = $data['id'];
$product->name = $data['name'];
$product->description = $data['description'];
$product->price = (float)$data['price'];
$product->stock = (int)$data['stock'];
$product->created_at = new DateTime($data['created_at']);
$products[] = $product;
}
return $products;
}
}
?>
2. 产品控制器
<?php
namespace AppControllers;
use AppModelsProduct;
class ProductController
{
public function index(): void
{
$products = Product::getAll();
// 在实际项目中,这里会渲染视图
header('Content-Type: application/json');
echo json_encode(array_map(function($product) {
return [
'id' => $product->id,
'name' => $product->name,
'price' => $product->price,
'stock' => $product->stock
];
}, $products));
}
public function show(int $id): void
{
$product = Product::find($id);
if (!$product) {
http_response_code(404);
echo json_encode(['error' => '产品未找到']);
return;
}
header('Content-Type: application/json');
echo json_encode([
'id' => $product->id,
'name' => $product->name,
'description' => $product->description,
'price' => $product->price,
'stock' => $product->stock
]);
}
public function create(): void
{
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
http_response_code(405);
echo json_encode(['error' => '方法不允许']);
return;
}
$data = json_decode(file_get_contents('php://input'), true);
$product = new Product();
$product->name = $data['name'] ?? '';
$product->description = $data['description'] ?? '';
$product->price = (float)($data['price'] ?? 0);
$product->stock = (int)($data['stock'] ?? 0);
if ($product->save()) {
http_response_code(201);
echo json_encode(['message' => '产品创建成功', 'id' => $product->id]);
} else {
http_response_code(500);
echo json_encode(['error' => '产品创建失败']);
}
}
}
?>
PHP 8+ 高级特性应用
1. 枚举类型(PHP 8.1+)
<?php
namespace AppEnums;
enum OrderStatus: string
{
case PENDING = 'pending';
case PROCESSING = 'processing';
case SHIPPED = 'shipped';
case DELIVERED = 'delivered';
case CANCELLED = 'cancelled';
public function getLabel(): string
{
return match($this) {
self::PENDING => '待处理',
self::PROCESSING => '处理中',
self::SHIPPED => '已发货',
self::DELIVERED => '已送达',
self::CANCELLED => '已取消'
};
}
public function canBeCancelled(): bool
{
return in_array($this, [self::PENDING, self::PROCESSING]);
}
}
?>
2. 属性构造器(PHP 8.0+)
<?php
namespace AppValueObjects;
class Money
{
public function __construct(
public readonly float $amount,
public readonly string $currency = 'CNY'
) {
if ($amount currency !== $other->currency) {
throw new InvalidArgumentException('货币类型不匹配');
}
return new Money($this->amount + $other->amount, $this->currency);
}
public function format(): string
{
return number_format($this->amount, 2) . ' ' . $this->currency;
}
}
?>
安全最佳实践
1. 输入验证器
<?php
namespace AppCore;
class Validator
{
private array $errors = [];
private array $data;
public function __construct(array $data)
{
$this->data = $data;
}
public function required(string $field, string $message = '此字段为必填项'): self
{
if (!isset($this->data[$field]) || trim($this->data[$field]) === '') {
$this->errors[$field][] = $message;
}
return $this;
}
public function email(string $field, string $message = '请输入有效的邮箱地址'): self
{
if (isset($this->data[$field]) && !filter_var($this->data[$field], FILTER_VALIDATE_EMAIL)) {
$this->errors[$field][] = $message;
}
return $this;
}
public function minLength(string $field, int $length, string $message = '长度不足'): self
{
if (isset($this->data[$field]) && strlen($this->data[$field]) errors[$field][] = $message;
}
return $this;
}
public function passes(): bool
{
return empty($this->errors);
}
public function getErrors(): array
{
return $this->errors;
}
}
?>
2. 中间件:认证保护
<?php
namespace AppMiddlewares;
class AuthMiddleware
{
public function handle(): bool
{
session_start();
if (!isset($_SESSION['user_id'])) {
http_response_code(401);
echo json_encode(['error' => '未授权访问']);
return false;
}
return true;
}
}
?>
3. 应用入口点(public/index.php)
<?php
require_once __DIR__ . '/../vendor/autoload.php';
use AppCoreRouter;
use AppControllersProductController;
use AppMiddlewaresAuthMiddleware;
$router = new Router();
// 公开路由
$router->add('GET', '/products', [ProductController::class, 'index']);
$router->add('GET', '/products/{id}', [ProductController::class, 'show']);
// 需要认证的路由
$router->middleware(AuthMiddleware::class)
->add('POST', '/products', [ProductController::class, 'create']);
$method = $_SERVER['REQUEST_METHOD'];
$path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$router->dispatch($method, $path);
?>
总结与进阶方向
本教程实现的核心功能:
- 完整的MVC架构实现
- 面向对象的数据库操作层
- 灵活的路由系统
- 输入验证和安全防护
- PHP 8+ 新特性应用
架构思维:现代PHP开发不仅仅是写代码,更是构建可维护、可扩展、安全的系统架构。通过本教程的学习,你已经掌握了构建企业级应用的核心技能。