本文目录导读:

在 Laravel 架构中,领域服务(Domain Services) 的放置位置取决于你采用的是传统分层架构还是 DDD(领域驱动设计)风格,以下是两种主流实践方案:
传统 Laravel 分层架构(推荐入门/中小项目)
如果项目没有严格遵循 DDD,而是使用 Laravel 默认的 app/ 目录结构,领域服务可以放在:
app/Services/
└── Domain/
├── OrderService.php
├── PaymentService.php
└── UserDomainService.php
实现示例:
// app/Services/Domain/OrderService.php
namespace App\Services\Domain;
use App\Models\Order;
use App\Repositories\OrderRepository;
use App\Exceptions\InsufficientStockException;
class OrderService
{
public function __construct(
private OrderRepository $repository
) {}
public function placeOrder(array $items, string $userId): Order
{
// 领域逻辑:检查库存、计算总价、创建订单
$this->validateStock($items);
$total = $this->calculateTotal($items);
return $this->repository->create([
'user_id' => $userId,
'items' => $items,
'total' => $total,
'status' => 'pending'
]);
}
private function validateStock(array $items): void
{
foreach ($items as $item) {
if ($item['quantity'] > $item['product']->stock) {
throw new InsufficientStockException($item['product']->name);
}
}
}
}
DDD 风格架构(推荐大型/复杂项目)
对于严格遵循 DDD 的项目,使用 app/Domain/ 目录:
app/Domain/
├── Services/
│ ├── OrderPlacementService.php
│ ├── PaymentService.php
│ └── ShippingService.php
├── Models/
│ ├── Order.php
│ └── Payment.php
├── Repositories/
│ └── OrderRepository.php
└── Events/
└── OrderPlaced.php
DDD 风格示例:
// app/Domain/Services/OrderPlacementService.php
namespace App\Domain\Services;
use App\Domain\Repositories\OrderRepository;
use App\Domain\Events\OrderPlaced;
use App\Domain\ValueObjects\Money;
use Illuminate\Support\Facades\Event;
class OrderPlacementService
{
public function __construct(
private OrderRepository $orderRepo,
private InventoryService $inventory,
private PricingService $pricing
) {}
public function execute(OrderRequest $request): Order
{
// 1. 验证库存
$this->inventory->reserveItems($request->items);
// 2. 计算价格
$total = $this->pricing->calculate($request->items);
// 3. 创建订单实体
$order = new Order(
userId: $request->userId,
items: $request->items,
total: new Money($total)
);
// 4. 持久化
$this->orderRepo->save($order);
// 5. 触发事件
Event::dispatch(new OrderPlaced($order));
return $order;
}
}
使用 Laravel 包(推荐模块化开发)
如果你使用 nWidart/laravel-modules 或类似包,按模块组织:
Modules/
└── Order/
├── Services/
│ └── OrderService.php
├── Entities/
│ └── Order.php
└── Repositories/
└── OrderRepository.php
关键原则
无论放在哪里,请遵循:
| 原则 | 说明 | 反例 |
|---|---|---|
| 业务逻辑 | 领域服务只包含业务规则,不处理 HTTP 请求 | ❌ 在服务里调用 request()->all() |
| 无状态 | 服务不应该持有状态(除了依赖注入) | ❌ 在服务类里定义 public 属性 |
| 单一职责 | 每个服务只处理一个领域关注点 | ❌ UserService 同时处理用户、订单、支付 |
| 依赖抽象 | 依赖接口而非具体实现 | ❌ 直接实例化 Eloquent Model |
什么时候该用领域服务?
| 场景 | 应该使用 |
|---|---|
| 多个实体协同工作(如订单+支付+库存) | ✅ 必须 |
| 复杂事务性操作 | ✅ 推荐 |
| 简单 CRUD | ❌ 直接使用 Repository 或 Model |
| 只有一个实体的简单规则 | ❌ 放在实体方法里 |
避免的常见错误
// ❌ 错误:在 Controller 里写领域逻辑
class OrderController {
public function store(Request $request) {
// 检查库存、计算价格... 太多逻辑在控制器
}
}
// ✅ 正确:控制器只负责编排
class OrderController {
public function store(Request $request) {
$order = app(OrderService::class)->placeOrder(
$request->items,
auth()->id()
);
return response()->json($order, 201);
}
}
- 传统 Laravel:
app/Services/Domain/ - DDD:
app/Domain/Services/ - 模块化:
Modules/{Module}/Services/
选择哪种取决于项目规模和团队规范,对于大多数 Laravel 项目,app/Services/Domain/ 是最平衡的选择。
版权声明: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直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播