Chuyển đến nội dung chính

第 20 課:簡潔的架構和包

儲存庫模式、服務層、操作類別。領域驅動設計基礎知識。創建 Laravel 包。基於模組的結構(nwidart/laravel-modules)。堅實的原則。

💻 程式設計 — 第 20 課 第 20 課:簡潔的架構和包

Laravel:從基礎到高級

第 6 部分:測試、Docker 和生產

亞洲開發網

1.服務層

namespace App\Services;

class ProductService
{
    public function __construct(
        private readonly ProductRepository $repository,
    ) {}

    public function create(array $data): Product
    {
        $product = $this->repository->create($data);

        if (isset($data['tags'])) {
            $product->tags()->sync($data['tags']);
        }

        event(new ProductCreated($product));
        Cache::tags(['products'])->flush();

        return $product;
    }
}

// Controller
class ProductController extends Controller
{
    public function store(StoreProductRequest $request, ProductService $service)
    {
        $product = $service->create($request->validated());
        return new ProductResource($product);
    }
}

2. 動作類

namespace App\Actions;

class CreateOrder
{
    public function __construct(
        private readonly PaymentService $payment,
    ) {}

    public function execute(User $user, array $items): Order
    {
        return DB::transaction(function () use ($user, $items) {
            $order = $user->orders()->create([
                'total' => collect($items)->sum(fn ($i) => $i['price'] * $i['quantity']),
            ]);

            foreach ($items as $item) {
                $order->items()->create($item);
                Product::where('id', $item['product_id'])->decrement('stock', $item['quantity']);
            }

            $this->payment->charge($order);
            return $order;
        });
    }
}

3. 儲存庫模式

interface ProductRepositoryInterface
{
    public function findBySlug(string $slug): ?Product;
    public function getActive(int $perPage = 20): LengthAwarePaginator;
}

class EloquentProductRepository implements ProductRepositoryInterface
{
    public function findBySlug(string $slug): ?Product
    {
        return Product::with('category')->where('slug', $slug)->first();
    }

    public function getActive(int $perPage = 20): LengthAwarePaginator
    {
        return Product::where('is_active', true)->paginate($perPage);
    }
}

// AppServiceProvider
$this->app->bind(ProductRepositoryInterface::class, EloquentProductRepository::class);

4. 基於模組的結構

app/
├── Modules/
│   ├── Product/
│   │   ├── Actions/
│   │   ├── Models/
│   │   ├── Services/
│   │   ├── Http/Controllers/
│   │   ├── Http/Requests/
│   │   ├── Http/Resources/
│   │   └── routes.php
│   ├── Order/
│   └── User/

下一篇: Docker 和 CI/CD。