本文目录导读:

我来提供一个完整的PHP服务层代码示例,包含常见的业务场景和最佳实践。
基础服务层架构
<?php
// app/Services/BaseService.php
namespace App\Services;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Collection;
use Exception;
abstract class BaseService
{
protected Model $model;
/**
* 创建记录
*/
public function create(array $data): Model
{
try {
DB::beginTransaction();
$result = $this->model->create($data);
DB::commit();
return $result;
} catch (Exception $e) {
DB::rollBack();
Log::error('创建失败: ' . $e->getMessage(), $data);
throw new \RuntimeException('创建记录失败');
}
}
/**
* 更新记录
*/
public function update(int $id, array $data): Model
{
try {
DB::beginTransaction();
$model = $this->model->findOrFail($id);
$model->update($data);
DB::commit();
return $model->fresh();
} catch (Exception $e) {
DB::rollBack();
Log::error('更新失败: ' . $e->getMessage(), ['id' => $id]);
throw new \RuntimeException('更新记录失败');
}
}
/**
* 删除记录
*/
public function delete(int $id): bool
{
try {
DB::beginTransaction();
$model = $this->model->findOrFail($id);
$result = $model->delete();
DB::commit();
return $result;
} catch (Exception $e) {
DB::rollBack();
Log::error('删除失败: ' . $e->getMessage(), ['id' => $id]);
throw new \RuntimeException('删除记录失败');
}
}
/**
* 获取记录
*/
public function find(int $id): Model
{
return $this->model->findOrFail($id);
}
/**
* 获取所有记录
*/
public function all(): Collection
{
return $this->model->all();
}
}
用户服务示例
<?php
// app/Services/UserService.php
namespace App\Services;
use App\Models\User;
use App\Repositories\UserRepository;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\ValidationException;
class UserService extends BaseService
{
protected UserRepository $userRepository;
public function __construct(UserRepository $userRepository)
{
parent::__construct();
$this->model = new User();
$this->userRepository = $userRepository;
}
/**
* 创建用户(带验证和业务逻辑)
*/
public function createUser(array $data): User
{
// 业务验证
$validator = Validator::make($data, [
'name' => 'required|string|max:255',
'email' => 'required|email|unique:users,email',
'password' => 'required|string|min:8|confirmed',
'role' => 'required|in:admin,user,editor'
]);
if ($validator->fails()) {
throw new ValidationException($validator);
}
// 业务逻辑处理
$data['password'] = Hash::make($data['password']);
$data['status'] = 'active';
$data['verification_token'] = $this->generateVerificationToken();
// 调用父类创建
$user = parent::create($data);
// 发送欢迎邮件
$this->sendWelcomeEmail($user);
return $user;
}
/**
* 更新用户资料
*/
public function updateProfile(int $userId, array $data): User
{
$allowedFields = ['name', 'avatar', 'bio', 'phone'];
$filteredData = array_intersect_key($data, array_flip($allowedFields));
return parent::update($userId, $filteredData);
}
/**
* 更改用户密码
*/
public function changePassword(int $userId, string $oldPassword, string $newPassword): bool
{
$user = $this->find($userId);
// 验证旧密码
if (!Hash::check($oldPassword, $user->password)) {
throw new \InvalidArgumentException('原密码错误');
}
// 更新密码
return parent::update($userId, [
'password' => Hash::make($newPassword)
]) instanceof User;
}
/**
* 获取用户列表(带分页和缓存)
*/
public function getUserList(array $filters = [], int $perPage = 20): \Illuminate\Pagination\LengthAwarePaginator
{
$cacheKey = 'users_list_' . md5(serialize($filters)) . '_' . $perPage;
return Cache::remember($cacheKey, 3600, function () use ($filters, $perPage) {
$query = $this->model->newQuery();
if (isset($filters['status'])) {
$query->where('status', $filters['status']);
}
if (isset($filters['search'])) {
$query->where(function ($q) use ($filters) {
$q->where('name', 'like', '%' . $filters['search'] . '%')
->orWhere('email', 'like', '%' . $filters['search'] . '%');
});
}
$query->orderBy($filters['sort_by'] ?? 'created_at', $filters['sort_order'] ?? 'desc');
return $query->paginate($perPage);
});
}
/**
* 获取用户统计信息
*/
public function getUserStats(int $userId): array
{
$user = $this->find($userId);
return [
'total_orders' => $user->orders()->count(),
'total_spent' => $user->orders()->sum('total_amount'),
'recent_orders' => $user->orders()->latest()->take(5)->get(),
'favorite_products' => $user->favorites()->latest()->take(10)->get()
];
}
/**
* 软删除用户
*/
public function softDeleteUser(int $userId): bool
{
$user = $this->find($userId);
// 撤销token
$user->tokens()->delete();
// 更新状态
$user->status = 'deleted';
$user->save();
// 异步清理用户数据
$this->cleanupUserData($userId);
return parent::delete($userId);
}
/**
* 导出用户数据(GDPR合规)
*/
public function exportUserData(int $userId): array
{
$user = $this->find($userId);
return [
'profile' => $user->toArray(),
'orders' => $user->orders()->get()->toArray(),
'addresses' => $user->addresses()->get()->toArray(),
'payment_methods' => $user->paymentMethods()->get()->toArray()
];
}
/**
* 批量操作
*/
public function batchUpdateStatus(array $userIds, string $status): int
{
$affected = 0;
try {
DB::beginTransaction();
$affected = $this->model->whereIn('id', $userIds)
->where('status', '!=', $status)
->update(['status' => $status]);
DB::commit();
return $affected;
} catch (Exception $e) {
DB::rollBack();
throw $e;
}
}
// 私有辅助方法
private function generateVerificationToken(): string
{
return bin2hex(random_bytes(32));
}
private function sendWelcomeEmail(User $user): void
{
Log::info('发送欢迎邮件', ['user_id' => $user->id]);
// 邮件发送逻辑
}
private function cleanupUserData(int $userId): void
{
// 清理用户数据的异步任务
}
}
订单服务示例(更复杂的业务逻辑)
<?php
// app/Services/OrderService.php
namespace App\Services;
use App\Models\Order;
use App\Models\OrderItem;
use App\Models\Product;
use App\Models\InventoryLog;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\Lock;
use Illuminate\Support\Facades\Log;
class OrderService extends BaseService
{
public function __construct()
{
$this->model = new Order();
}
/**
* 创建订单(并发控制)
*/
public function createOrder(int $userId, array $items, array $options = []): Order
{
$lockKey = 'order_creation_' . $userId;
// 使用分布式锁防止并发创建
return Lock::lock($lockKey, 10, function () use ($userId, $items, $options) {
try {
DB::beginTransaction();
// 创建订单
$order = $this->model->create([
'user_id' => $userId,
'order_number' => $this->generateOrderNumber(),
'status' => 'pending',
'total_amount' => 0,
'shipping_address' => $options['shipping_address'] ?? null,
'billing_address' => $options['billing_address'] ?? null,
'payment_method' => $options['payment_method'] ?? null,
'notes' => $options['notes'] ?? null
]);
$totalAmount = 0;
$orderItems = [];
// 处理每个商品
foreach ($items as $item) {
$product = Product::where('id', $item['product_id'])
->where('status', 'active')
->lockForUpdate()
->firstOrFail();
// 检查库存
if ($product->stock < $item['quantity']) {
throw new \RuntimeException('商品库存不足: ' . $product->name);
}
// 计算价格(考虑促销)
$unitPrice = $this->calculatePrice($product, $item['quantity'], $options);
// 创建订单项
$orderItems[] = [
'product_id' => $product->id,
'product_name' => $product->name,
'product_sku' => $product->sku,
'quantity' => $item['quantity'],
'unit_price' => $unitPrice,
'subtotal' => $unitPrice * $item['quantity']
];
$totalAmount += $unitPrice * $item['quantity'];
// 扣减库存
$product->update([
'stock' => $product->stock - $item['quantity']
]);
// 记录库存流水
InventoryLog::create([
'product_id' => $product->id,
'type' => 'order',
'quantity' => -$item['quantity'],
'reference_id' => $order->id,
'reference_type' => 'order',
'remarks' => "订单 #{$order->order_number}"
]);
}
// 应用优惠券
$discount = $this->applyCoupon($totalAmount, $options['coupon'] ?? null);
// 计算运费
$shippingFee = $this->calculateShippingFee($totalAmount, $options);
// 计算税费
$tax = $this->calculateTax($totalAmount);
// 更新订单
$order->items()->createMany($orderItems);
$order->update([
'total_amount' => $totalAmount,
'discount_amount' => $order['discount'] ?? 0,
'shipping_fee' => $shippingFee,
'tax_amount' => $tax,
'grand_total' => $totalAmount - ($discount ?? 0) + $shippingFee + $tax,
'promo_code' => $options['coupon'] ?? null
]);
// 触发事件
Event::dispatch('order.created', ['order' => $order]);
DB::commit();
// 异步任务
$this->afterOrderCreated($order);
return $order->fresh(['items', 'user']);
} catch (\Exception $e) {
DB::rollBack();
Log::error('创建订单失败', [
'user_id' => $userId,
'items' => $items,
'error' => $e->getMessage()
]);
throw $e;
}
});
}
/**
* 取消订单
*/
public function cancelOrder(int $orderId, string $reason = ''): Order
{
try {
DB::beginTransaction();
$order = $this->model->findOrFail($orderId);
// 检查是否可取消
if (!in_array($order->status, ['pending', 'processing'])) {
throw new \RuntimeException('当前订单状态不能取消');
}
// 更新状态
$order->update([
'status' => 'cancelled',
'cancel_reason' => $reason,
'cancelled_at' => now()
]);
// 恢复库存
foreach ($order->items as $item) {
$item->product->increment('stock', $item->quantity);
InventoryLog::create([
'product_id' => $item->product_id,
'type' => 'order_cancel',
'quantity' => $item->quantity,
'reference_id' => $order->id,
'reference_type' => 'order',
'remarks' => "订单取消 #{$order->order_number}"
]);
}
// 退款处理
if ($order->payment_status === 'paid') {
$this->processRefund($order);
}
DB::commit();
return $order->fresh();
} catch (\Exception $e) {
DB::rollBack();
throw $e;
}
}
/**
* 订单状态流转
*/
public function transitionOrderStatus(Order $order, string $newStatus): bool
{
$transitions = [
'pending' => ['processing', 'cancelled'],
'processing' => ['shipped', 'cancelled'],
'shipped' => ['delivered'],
'delivered' => ['completed'],
'cancelled' => [],
'completed' => []
];
if (!in_array($newStatus, $transitions[$order->status] ?? [])) {
throw new \InvalidArgumentException(
"无效的状态转换: {$order->status} -> {$newStatus}"
);
}
$order->update([
'status' => $newStatus,
'status_history' => array_merge(
$order->status_history ?? [],
[
[
'from' => $order->status,
'to' => $newStatus,
'at' => now()->toDateTimeString()
]
]
)
]);
return true;
}
/**
* 获取订单报表
*/
public function getOrderReport(array $filters = []): array
{
$query = $this->model->newQuery();
// 时间过滤
if (isset($filters['from']) && isset($filters['to'])) {
$query->whereBetween('created_at', [$filters['from'], $filters['to']]);
}
// 状态过滤
if (isset($filters['status'])) {
$query->where('status', $filters['status']);
}
$stats = [
'total_orders' => $query->count(),
'total_revenue' => $query->sum('grand_total'),
'avg_order_value' => $query->avg('grand_total'),
'status_breakdown' => $query->groupBy('status')
->selectRaw('status, COUNT(*) as count, SUM(grand_total) as total')
->get()
->pluck('total', 'status')
];
// 每日订单统计
$dailyStats = $this->model->newQuery()
->whereBetween('created_at', [$filters['from'] ?? now()->subDays(30), $filters['to'] ?? now()])
->groupBy('date')
->selectRaw('DATE(created_at) as date, COUNT(*) as orders, SUM(grand_total) as revenue')
->get();
return [
'summary' => $stats,
'daily_breakdown' => $dailyStats,
'top_products' => $this->getTopProducts($filters['from'] ?? null, $filters['to'] ?? null)
];
}
// 辅助私有方法
private function generateOrderNumber(): string
{
return 'ORD-' . date('YmdHis') . '-' . strtoupper(substr(uniqid(), -6));
}
private function calculatePrice(Product $product, int $quantity, array $options): float
{
$price = $product->price;
// 促销价
if ($product->sale_price && $product->sale_price < $price) {
$price = $product->sale_price;
}
// 批量折扣示例
if ($quantity >= 10) {
$price *= 0.9; // 10% discount
}
// 会员价
if (isset($options['user']) && $options['user']->vip_level > 0) {
$price *= (1 - $options['user']->vip_discount);
}
return round($price, 2);
}
private function applyCoupon(float $amount, ?string $couponCode): float
{
// 优惠券逻辑(略)
return 0;
}
private function calculateShippingFee(float $totalAmount, array $options): float
{
return $totalAmount > 50 ? 0 : 5.99;
}
private function calculateTax(float $amount): float
{
return $amount * 0.08;
}
private function processRefund(Order $order): void
{
// 退款处理逻辑
}
private function afterOrderCreated(Order $order): void
{
// 发送邮件通知
// 生成发票
// 通知库存系统
}
private function getTopProducts(?string $from, ?string $to): \Illuminate\Support\Collection
{
return OrderItem::query()
->join('orders', 'orders.id', '=', 'order_items.order_id')
->when($from, fn($q) => $q->where('orders.created_at', '>=', $from))
->when($to, fn($q) => $q->where('orders.created_at', '<=', $to))
->where('orders.status', '!=', 'cancelled')
->groupBy('product_id', 'product_name')
->selectRaw('product_id, product_name, SUM(quantity) as total_quantity, SUM(subtotal) as total_amount')
->orderByDesc('total_quantity')
->limit(10)
->get();
}
}
服务提供者注册示例
<?php
// app/Providers/AppServiceProvider.php
namespace App\Providers;
use App\Services\UserService;
use App\Services\OrderService;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
public function register(): void
{
// 绑定服务
$this->app->singleton(UserService::class, function ($app) {
return new UserService(
$app->make('App\Repositories\UserRepository')
);
});
$this->app->singleton(OrderService::class, function ($app) {
return new OrderService();
});
// 也可以简单的绑定
$this->app->bind(UserService::class);
$this->app->bind(OrderService::class);
}
public function boot(): void
{
//
}
}
控制器中使用服务层
<?php
// app/Http/Controllers/OrderController.php
namespace App\Http\Controllers;
use App\Services\OrderService;
use App\Services\UserService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
class OrderController extends Controller
{
protected OrderService $orderService;
protected UserService $userService;
public function __construct(OrderService $orderService, UserService $userService)
{
$this->orderService = $orderService;
$this->userService = $userService;
$this->middleware('auth:api');
}
/**
* 创建订单
*/
public function store(Request $request)
{
// 验证请求
$validator = Validator::make($request->all(), [
'items' => 'required|array|min:1',
'items.*.product_id' => 'required|exists:products,id',
'items.*.quantity' => 'required|integer|min:1',
'shipping_address' => 'required|array',
'payment_method' => 'required|string'
]);
if ($validator->fails()) {
return response()->json(['errors' => $validator->errors()], 422);
}
try {
// 调用服务层
$order = $this->orderService->createOrder(
$request->user()->id,
$request->items,
[
'shipping_address' => $request->shipping_address,
'payment_method' => $request->payment_method,
'coupon' => $request->coupon_code
]
);
return response()->json([
'message' => '订单创建成功',
'data' => $order
], 201);
} catch (\Exception $e) {
return response()->json([
'message' => $e->getMessage()
], 500);
}
}
/**
* 订单列表
*/
public function index(Request $request)
{
$filters = $request->only(['status', 'from', 'to', 'page', 'per_page']);
$orders = $this->orderService->getOrderReport($filters);
return response()->json([
'data' => $orders
]);
}
}
单元测试示例
<?php
// tests/Feature/OrderServiceTest.php
namespace Tests\Feature;
use App\Models\Order;
use App\Models\Product;
use App\Models\User;
use App\Services\OrderService;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class OrderServiceTest extends TestCase
{
use RefreshDatabase;
protected OrderService $orderService;
protected function setUp(): void
{
parent::setUp();
$this->orderService = app(OrderService::class);
}
/** @test */
public function it_creates_an_order_successfully()
{
$user = User::factory()->create();
$product = Product::factory()->create(['stock' => 10, 'price' => 99.99]);
$order = $this->orderService->createOrder($user->id, [
['product_id' => $product->id, 'quantity' => 2]
]);
$this->assertInstanceOf(Order::class, $order);
$this->assertEquals($order->total_amount, 199.98);
$this->assertEquals($order->status, 'pending');
$this->assertEquals($product->fresh()->stock, 8);
}
/** @test */
public function it_throws_exception_when_stock_insufficient()
{
$user = User::factory()->create();
$product = Product::factory()->create(['stock' => 5]);
$this->expectException(\RuntimeException::class);
$this->orderService->createOrder($user->id, [
['product_id' => $product->id, 'quantity' => 10]
]);
}
/** @test */
public function it_cancels_order_and_restores_stock()
{
$user = User::factory()->create();
$product = Product::factory()->create(['stock' => 10]);
$order = $this->orderService->createOrder($user->id, [
['product_id' => $product->id, 'quantity' => 3]
]);
$this->orderService->cancelOrder($order->id);
$this->assertEquals($order->fresh()->status, 'cancelled');
$this->assertEquals($product->fresh()->stock, 10);
}
}
服务层设计最佳实践
分层原则
- Controller:只负责请求响应流程
- Service:业务逻辑核心
- Repository:数据访问层(可选)
- Model:数据实体和关联
事务管理
- 所有写操作放入事务
- 使用锁处理并发问题
- 失败时正确回滚
异常处理
- 自定义异常类型
- 统一异常处理
- 日志记录
依赖注入
- 服务通过构造函数注入
- 避免硬编码依赖
- 便于单元测试
缓存策略
- 查询结果缓存
- 缓存失效时机合理
- 缓存键设计规范
性能优化
- 批量操作
- 预加载关系
- 查询优化
安全考虑
- 权限检查
- 数据验证
- 防止注入
可维护性
- 单一职责
- 清晰命名
- 注释记录
- 单元测试
服务层是业务逻辑的核心,设计良好的服务层能提高代码复用性、可测试性和可维护性,根据项目复杂度,可以适当简化或扩展服务层结构。
版权声明: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直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播