PHP 服务层代码示例

wen PHP项目 3

本文目录导读:

PHP 服务层代码示例

  1. 基础服务层架构
  2. 用户服务示例
  3. 订单服务示例(更复杂的业务逻辑)
  4. 服务提供者注册示例
  5. 控制器中使用服务层
  6. 单元测试示例
  7. 服务层设计最佳实践

我来提供一个完整的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:数据实体和关联

事务管理

  • 所有写操作放入事务
  • 使用锁处理并发问题
  • 失败时正确回滚

异常处理

  • 自定义异常类型
  • 统一异常处理
  • 日志记录

依赖注入

  • 服务通过构造函数注入
  • 避免硬编码依赖
  • 便于单元测试

缓存策略

  • 查询结果缓存
  • 缓存失效时机合理
  • 缓存键设计规范

性能优化

  • 批量操作
  • 预加载关系
  • 查询优化

安全考虑

  • 权限检查
  • 数据验证
  • 防止注入

可维护性

  • 单一职责
  • 清晰命名
  • 注释记录
  • 单元测试

服务层是业务逻辑的核心,设计良好的服务层能提高代码复用性、可测试性和可维护性,根据项目复杂度,可以适当简化或扩展服务层结构。

抱歉,评论功能暂时关闭!