现代PHP开发的演进
随着PHP语言的不断发展,现代PHP开发已经告别了传统的”include/require”模式,转向更加规范、可维护的依赖管理和自动加载体系。Composer作为PHP的依赖管理工具,与PSR标准共同构成了现代PHP开发的基石。
Composer基础与安装配置
Composer的安装
# 全局安装Composer
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php composer-setup.php
php -r "unlink('composer-setup.php');"
# 移动到全局可访问位置
sudo mv composer.phar /usr/local/bin/composer
初始化项目配置
{
"name": "mycompany/myproject",
"description": "现代PHP项目示例",
"type": "project",
"require": {
"php": "^8.0",
"monolog/monolog": "^2.0",
"guzzlehttp/guzzle": "^7.0"
},
"require-dev": {
"phpunit/phpunit": "^9.0"
},
"autoload": {
"psr-4": {
"MyCompany\MyProject\": "src/"
}
}
}
PSR标准深度解析
PSR-4自动加载标准实践
PSR-4是现代PHP项目中最常用的自动加载标准,它规定了类名与文件路径的映射关系。
// 项目目录结构
// src/
// Controllers/
// UserController.php
// Models/
// User.php
// Services/
// EmailService.php
// vendor/
// composer.json
实现符合PSR-4的类文件
// src/Controllers/UserController.php
<?php
namespace MyCompanyMyProjectControllers;
use MyCompanyMyProjectModelsUser;
use MyCompanyMyProjectServicesEmailService;
class UserController
{
private EmailService $emailService;
public function __construct(EmailService $emailService)
{
$this->emailService = $emailService;
}
public function register(string $email, string $password): array
{
$user = new User($email, $password);
if ($user->save()) {
$this->emailService->sendWelcomeEmail($user);
return ['success' => true, 'message' => '用户注册成功'];
}
return ['success' => false, 'message' '注册失败'];
}
}
// src/Models/User.php
<?php
namespace MyCompanyMyProjectModels;
class User
{
private string $email;
private string $passwordHash;
private DateTime $createdAt;
public function __construct(string $email, string $password)
{
$this->email = $email;
$this->passwordHash = password_hash($password, PASSWORD_DEFAULT);
$this->createdAt = new DateTime();
}
public function save(): bool
{
// 模拟保存到数据库
return true;
}
public function getEmail(): string
{
return $this->email;
}
}
自定义Composer包开发
创建可复用的日志包
// 包目录结构
// my-logger/
// src/
// Logger.php
// Formatters/
// JsonFormatter.php
// tests/
// composer.json
包的核心实现
// my-logger/src/Logger.php
<?php
namespace MyCompanyLogger;
use MyCompanyLoggerFormattersJsonFormatter;
class Logger
{
private string $logFile;
private JsonFormatter $formatter;
public function __construct(string $logFile = 'app.log')
{
$this->logFile = $logFile;
$this->formatter = new JsonFormatter();
}
public function info(string $message, array $context = []): void
{
$this->log('INFO', $message, $context);
}
public function error(string $message, array $context = []): void
{
$this->log('ERROR', $message, $context);
}
private function log(string $level, string $message, array $context): void
{
$logEntry = $this->formatter->format([
'timestamp' => date('c'),
'level' => $level,
'message' => $message,
'context' => $context
]);
file_put_contents($this->logFile, $logEntry . PHP_EOL, FILE_APPEND);
}
}
// my-logger/src/Formatters/JsonFormatter.php
<?php
namespace MyCompanyLoggerFormatters;
class JsonFormatter
{
public function format(array $data): string
{
return json_encode($data, JSON_PRETTY_PRINT);
}
}
包的composer.json配置
{
"name": "mycompany/logger",
"description": "一个简单的PSR兼容日志库",
"type": "library",
"license": "MIT",
"autoload": {
"psr-4": {
"MyCompany\Logger\": "src/"
}
},
"require": {
"php": "^8.0"
},
"require-dev": {
"phpunit/phpunit": "^9.0"
}
}
依赖注入与服务容器实战
实现简单的服务容器
// src/Container/Container.php
<?php
namespace MyCompanyMyProjectContainer;
class Container
{
private array $bindings = [];
private array $instances = [];
public function bind(string $abstract, Closure $concrete): void
{
$this->bindings[$abstract] = $concrete;
}
public function singleton(string $abstract, Closure $concrete): void
{
$this->bindings[$abstract] = function () use ($concrete) {
static $instance;
if ($instance === null) {
$instance = $concrete($this);
}
return $instance;
};
}
public function make(string $abstract)
{
if (isset($this->instances[$abstract])) {
return $this->instances[$abstract];
}
if (isset($this->bindings[$abstract])) {
$concrete = $this->bindings[$abstract];
$instance = $concrete($this);
if ($this->isSingleton($abstract)) {
$this->instances[$abstract] = $instance;
}
return $instance;
}
return $this->resolve($abstract);
}
private function resolve(string $class)
{
$reflection = new ReflectionClass($class);
if (!$reflection->isInstantiable()) {
throw new Exception("类 {$class} 不能被实例化");
}
$constructor = $reflection->getConstructor();
if ($constructor === null) {
return new $class;
}
$parameters = $constructor->getParameters();
$dependencies = $this->resolveDependencies($parameters);
return $reflection->newInstanceArgs($dependencies);
}
private function resolveDependencies(array $parameters): array
{
$dependencies = [];
foreach ($parameters as $parameter) {
$type = $parameter->getType();
if ($type === null || $type->isBuiltin()) {
if ($parameter->isDefaultValueAvailable()) {
$dependencies[] = $parameter->getDefaultValue();
} else {
throw new Exception("无法解析参数: {$parameter->getName()}");
}
} else {
$dependencies[] = $this->make($type->getName());
}
}
return $dependencies;
}
private function isSingleton(string $abstract): bool
{
// 简化实现,实际中需要更复杂的逻辑
return isset($this->instances[$abstract]);
}
}
使用服务容器
// bootstrap.php
<?php
require_once 'vendor/autoload.php';
use MyCompanyMyProjectContainerContainer;
use MyCompanyMyProjectServicesEmailService;
use MyCompanyMyProjectControllersUserController;
$container = new Container();
// 注册服务
$container->singleton(EmailService::class, function ($container) {
return new EmailService();
});
$container->bind(UserController::class, function ($container) {
return new UserController($container->make(EmailService::class));
});
// 使用容器
$userController = $container->make(UserController::class);
$result = $userController->register('user@example.com', 'password123');
print_r($result);
现代PHP项目架构实战
完整的MVC架构示例
// 项目完整目录结构
// src/
// Controllers/
// UserController.php
// Models/
// User.php
// Services/
// EmailService.php
// Repositories/
// UserRepository.php
// Container/
// Container.php
// config/
// database.php
// public/
// index.php
// vendor/
// composer.json
// bootstrap.php
数据仓库模式实现
// src/Repositories/UserRepository.php
<?php
namespace MyCompanyMyProjectRepositories;
use MyCompanyMyProjectModelsUser;
use PDO;
class UserRepository
{
private PDO $connection;
public function __construct(PDO $connection)
{
$this->connection = $connection;
}
public function save(User $user): bool
{
$stmt = $this->connection->prepare(
"INSERT INTO users (email, password_hash, created_at) VALUES (?, ?, ?)"
);
return $stmt->execute([
$user->getEmail(),
$user->getPasswordHash(),
$user->getCreatedAt()->format('Y-m-d H:i:s')
]);
}
public function findByEmail(string $email): ?User
{
$stmt = $this->connection->prepare("SELECT * FROM users WHERE email = ?");
$stmt->execute([$email]);
$data = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$data) {
return null;
}
return $this->hydrateUser($data);
}
private function hydrateUser(array $data): User
{
$user = new User($data['email'], '');
// 设置其他属性...
return $user;
}
}
应用入口文件
// public/index.php
<?php
require_once __DIR__ . '/../bootstrap.php';
use MyCompanyMyProjectContainerContainer;
// 路由解析(简化版)
$path = $_SERVER['REQUEST_URI'] ?? '/';
$method = $_SERVER['REQUEST_METHOD'] ?? 'GET';
// 简单的路由匹配
if ($path === '/users/register' && $method === 'POST') {
$container = new Container();
// 配置容器绑定...
$userController = $container->make(UserController::class);
$result = $userController->register(
$_POST['email'] ?? '',
$_POST['password'] ?? ''
);
header('Content-Type: application/json');
echo json_encode($result);
} else {
http_response_code(404);
echo "页面未找到";
}
性能优化与最佳实践
Composer自动加载优化
# 生成优化的自动加载文件
composer dump-autoload -o
# 生产环境使用classmap优化
composer dump-autoload --optimize --apcu
# 使用APCu缓存加速自动加载
composer dump-autoload --apcu
依赖管理最佳实践
- 使用精确的版本约束(^1.2.3 或 ~1.2.3)
- 定期更新依赖:composer update
- 提交composer.lock文件到版本控制
- 分离开发依赖和生产依赖
- 使用私有包仓库管理内部依赖
PSR标准遵循建议
- 严格遵守PSR-1和PSR-12编码规范
- 使用PSR-4自动加载标准
- 遵循PSR-11容器接口规范
- 实现PSR-3日志接口兼容
总结
现代PHP开发已经形成了以Composer和PSR标准为核心的完整生态系统。通过本文的实战指南,我们深入探讨了:
- Composer依赖管理的核心概念和最佳实践
- PSR-4自动加载标准的实现原理
- 自定义Composer包的开发流程
- 依赖注入和服务容器的实现方法
- 现代PHP项目的完整架构设计
掌握这些现代PHP开发技术,将帮助您构建更加健壮、可维护和可扩展的应用程序,跟上PHP语言发展的步伐。