本文目录导读:

我来详细讲解PHP洋葱架构(Onion Architecture)的概念和实现方法。
什么是洋葱架构
洋葱架构是一种分层架构模式,强调依赖方向始终向内层,核心业务逻辑不依赖外部基础设施。
外层:基础设施(数据库、框架、外部API)
↓
应用层:用例、应用服务
↓
领域层:实体、值对象、领域服务
↓
核心:领域模型(最内层)
PHP实现示例
目录结构
src/
├── Domain/ # 领域层(最内层)
│ ├── Entity/ # 实体
│ ├── ValueObject/ # 值对象
│ ├── Repository/ # 仓库接口
│ └── Service/ # 领域服务
├── Application/ # 应用层
│ ├── UseCase/ # 用例
│ └── DTO/ # 数据传输对象
├── Infrastructure/ # 基础设施层(最外层)
│ ├── Persistence/ # 持久化
│ ├── Framework/ # 框架适配
│ └── External/ # 外部服务
└── Interface/ # 接口层
├── Controller/ # 控制器
└── Request/ # 请求处理
领域层实现
<?php
// Domain/Entity/User.php
namespace App\Domain\Entity;
class User
{
private string $id;
private string $name;
private Email $email;
public function __construct(string $id, string $name, Email $email)
{
$this->id = $id;
$this->name = $name;
$this->email = $email;
}
public function getId(): string
{
return $this->id;
}
public function getName(): string
{
return $this->name;
}
public function getEmail(): Email
{
return $this->email;
}
}
// Domain/ValueObject/Email.php
namespace App\Domain\ValueObject;
class Email
{
private string $value;
public function __construct(string $value)
{
if (!filter_var($value, FILTER_VALIDATE_EMAIL)) {
throw new \InvalidArgumentException('Invalid email address');
}
$this->value = $value;
}
public function getValue(): string
{
return $this->value;
}
}
// Domain/Repository/UserRepositoryInterface.php
namespace App\Domain\Repository;
use App\Domain\Entity\User;
interface UserRepositoryInterface
{
public function findById(string $id): ?User;
public function save(User $user): void;
public function delete(string $id): void;
}
应用层实现
<?php
// Application/UseCase/CreateUserUseCase.php
namespace App\Application\UseCase;
use App\Domain\Entity\User;
use App\Domain\Repository\UserRepositoryInterface;
use App\Domain\ValueObject\Email;
use App\Application\DTO\CreateUserRequest;
use App\Application\DTO\CreateUserResponse;
class CreateUserUseCase
{
public function __construct(
private UserRepositoryInterface $userRepository
) {}
public function execute(CreateUserRequest $request): CreateUserResponse
{
// 业务逻辑校验
$email = new Email($request->getEmail());
$existingUser = $this->userRepository->findById($request->getId());
if ($existingUser) {
throw new \RuntimeException('User already exists');
}
// 创建用户
$user = new User(
$request->getId(),
$request->getName(),
$email
);
// 保存用户
$this->userRepository->save($user);
return new CreateUserResponse(
$user->getId(),
$user->getName()
);
}
}
// Application/DTO/CreateUserRequest.php
namespace App\Application\DTO;
class CreateUserRequest
{
public function __construct(
private string $id,
private string $name,
private string $email
) {}
public function getId(): string
{
return $this->id;
}
public function getName(): string
{
return $this->name;
}
public function getEmail(): string
{
return $this->email;
}
}
// Application/DTO/CreateUserResponse.php
namespace App\Application\DTO;
class CreateUserResponse
{
public function __construct(
private string $id,
private string $name
) {}
public function getId(): string
{
return $this->id;
}
public function getName(): string
{
return $this->name;
}
}
基础设施层实现
<?php
// Infrastructure/Persistence/UserRepository.php
namespace App\Infrastructure\Persistence;
use App\Domain\Entity\User;
use App\Domain\Repository\UserRepositoryInterface;
use App\Domain\ValueObject\Email;
use PDO;
class UserRepository implements UserRepositoryInterface
{
private PDO $connection;
public function __construct(PDO $connection)
{
$this->connection = $connection;
}
public function findById(string $id): ?User
{
$stmt = $this->connection->prepare('SELECT * FROM users WHERE id = ?');
$stmt->execute([$id]);
$row = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$row) {
return null;
}
return new User(
$row['id'],
$row['name'],
new Email($row['email'])
);
}
public function save(User $user): void
{
$stmt = $this->connection->prepare(
'INSERT INTO users (id, name, email) VALUES (?, ?, ?)
ON DUPLICATE KEY UPDATE name = VALUES(name), email = VALUES(email)'
);
$stmt->execute([
$user->getId(),
$user->getName(),
$user->getEmail()->getValue()
]);
}
public function delete(string $id): void
{
$stmt = $this->connection->prepare('DELETE FROM users WHERE id = ?');
$stmt->execute([$id]);
}
}
接口层实现(Controller)
<?php
// Interface/Controller/UserController.php
namespace App\Interface\Controller;
use App\Application\DTO\CreateUserRequest;
use App\Application\UseCase\CreateUserUseCase;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
class UserController
{
public function __construct(
private CreateUserUseCase $createUserUseCase
) {}
public function create(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface
{
try {
$body = json_decode($request->getBody()->getContents(), true);
$createUserRequest = new CreateUserRequest(
$body['id'] ?? uniqid(),
$body['name'],
$body['email']
);
$result = $this->createUserUseCase->execute($createUserRequest);
$response->getBody()->write(json_encode([
'success' => true,
'data' => [
'id' => $result->getId(),
'name' => $result->getName()
]
]));
return $response->withStatus(201);
} catch (\Exception $e) {
$response->getBody()->write(json_encode([
'success' => false,
'error' => $e->getMessage()
]));
return $response->withStatus(400);
}
}
}
应用容器配置
<?php
// config/container.php
use App\Domain\Repository\UserRepositoryInterface;
use App\Infrastructure\Persistence\UserRepository;
use App\Application\UseCase\CreateUserUseCase;
use App\Interface\Controller\UserController;
return [
'dependencies' => [
'definitions' => [
PDO::class => function() {
return new PDO('mysql:host=localhost;dbname=test', 'user', 'password');
},
UserRepositoryInterface::class => function($container) {
return new UserRepository($container->get(PDO::class));
},
CreateUserUseCase::class => function($container) {
return new CreateUserUseCase(
$container->get(UserRepositoryInterface::class)
);
},
UserController::class => function($container) {
return new UserController(
$container->get(CreateUserUseCase::class)
);
}
]
]
];
路由配置
<?php
// routes.php
use App\Interface\Controller\UserController;
$app->post('/users', [UserController::class, 'create']);
$app->get('/users/{id}', [UserController::class, 'get']);
$app->put('/users/{id}', [UserController::class, 'update']);
$app->delete('/users/{id}', [UserController::class, 'delete']);
核心原则
依赖规则
- 内层不依赖外层
- 依赖方向始终向内
- 通过接口实现依赖倒置
领域模型
- 核心业务逻辑
- 不含技术细节
- 业务规则表达
应用服务
- 用例执行
- 事务管理
- 事件发布
基础设施
- 数据库实现
- 框架集成
- 外部服务
最佳实践
<?php
// 高级示例:依赖注入
// UseCase with dependency inversion
class OrderService
{
public function __construct(
private OrderRepositoryInterface $orderRepository,
private PaymentGatewayInterface $paymentGateway,
private EventDispatcherInterface $eventDispatcher
) {}
public function processOrder(Order $order): void
{
// 业务逻辑
$order->markAsProcessing();
$this->orderRepository->save($order);
// 外部依赖
$paymentResult = $this->paymentGateway->process(
$order->getTotal()
);
// 领域事件
$this->eventDispatcher->dispatch(
new OrderProcessedEvent($order)
);
}
}
优点
- 清晰分层:职责明确
- 可测试性:核心逻辑不依赖外部
- 可维护性:易扩展和修改
- 解耦:基础设施变更影响小
- 业务焦点:核心关注业务规则
注意事项
- 避免过设计:简单项目不需要全架构
- 严格控制依赖方向:不要反向依赖
- 接口设计合理:不要过多或过少
- 性能考虑:多层可能影响性能
- 学习成本:团队需要理解架构
洋葱架构适合:
- 复杂业务系统
- 需要长期维护的项目
- 团队有DDD经验
- 需要高度可测试性
通过这种方式,你可以构建一个清晰、可维护、可扩展的PHP应用架构。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播