Если вы видите это, значит, я еще не придумал, что написать.
<?php
use App\Http\Controllers\ProductController;
use Illuminate\Support\Facades\Route;
Route::post('products', [ProductController::class, 'store'])
->name('products.store');
<?php
declare(strict_types=1);
namespace App\Http\Controllers;
use App\Domains\Product\Core\Handlers\CreateProductHandler;
use App\Http\Requests\CreateProductRequest;
use Illuminate\Http\JsonResponse;
class ProductController extends Controller
{
public function store(CreateProductRequest $request, CreateProductHandler $handler): JsonResponse
{
$product = $handler->handle($request->getDto());
return response()->json([
'message' => 'Product created successfully',
'data' => $product
], 201);
}
}
<?php
declare(strict_types=1);
namespace App\Http\Requests;
use App\Domains\Product\Core\DTO\CreateProductDTO;
use Illuminate\Foundation\Http\FormRequest;
class CreateProductRequest extends FormRequest
{
public function authorize(): bool
{
return true; // Здесь можно добавить логику авторизации
}
public function rules(): array
{
return [
'product.name' => 'required|string|max:255',
'product.description' => 'required|string',
'product.price' => 'required|integer|min:0',
'tags' => 'array',
'tags.*' => 'integer|exists:tags,id',
'images' => 'array',
'images.*' => 'string',
];
}
public function getDto(): CreateProductDTO
{
return CreateProductDTO::fromArray($this->validated());
}
}
<?php
declare(strict_types=1);
namespace App\Domains\Product\Core\DTO;
use App\Domains\Product\Core\ValueObjects\ProductVO;
use Illuminate\Support\Arr;
final class CreateProductDTO
{
public function __construct(
public ProductVO $product
public array $tags,
public array $images
) {
}
public static function fromArray(array $data): self
{
return new self(
ProductVO::fromArray(Arr::get($data, 'product')),
Arr::get($data, 'tags', []),
Arr::get($data, 'images', [])
);
}
}
<?php
declare(strict_types=1);
namespace App\Domains\Product\Core\ValueObjects;
use Illuminate\Support\Arr;
final class ProductVO
{
public function __construct(
public string $name,
public string $description,
public float $price
) {
}
public static function fromArray(array $data): self
{
return new self(
Arr::get($data, 'name'),
Arr::get($data, 'description'),
null !== Arr::get($data, 'price') ? (float) Arr::get($data, 'price') : 0
);
}
}
<?php
declare(strict_types=1);
namespace App\Domains\Product\Core\Handlers;
use App\Domains\Product\Core\DTO\CreateProductDTO;
use App\Models\Product;
use Illuminate\Support\Facades\DB;
final class CreateProductHandler
{
public function handle(CreateProductDTO $dto): Product
{
return DB::transaction(function () use ($dto) {
// Создание товара
$product = new Product();
$product->name = $dto->product->name;
$product->description = $dto->product->description;
$product->price = $dto->product->price;
$product->save();
// Привязка тегов
$product->tags()->attach($dto->tags);
// Сохранение изображений
foreach ($dto->images as $image) {
$product->images()->create(['path' => $image]);
}
return $product;
});
}
}
Для успешного использования паттерна “Обработчик” с DTO и VO программист должен иметь уровень подготовки Middle (средний).
{message}