#Is this clean code (Controller, Validator, DTO)?

9 messages · Page 1 of 1 (latest)

vital yarrow
#

I'm trying to write cleaner Laravel code and recently started using DTOs. Here's a version of my store() method in ProductController:

public function store(Request $request)
    {
        $validatedData = $request->validate([
            'name' => 'required|string|max:255',
            'alloy' => 'required|string|max:50',
            'density' => 'required|numeric|min:0',
            'imperial_spec_sheet' => 'nullable|file|mimes:pdf|max:10240',
            'metric_spec_sheet' => 'nullable|file|mimes:pdf|max:10240',
        ]);

        if ($request->hasFile('imperial_spec_sheet'))
        {
            $validatedData['imperial_spec_sheet'] = $request->file('imperial_spec_sheet')->store('spec_sheets', 'public');
        }

        if ($request->hasFile('metric_spec_sheet'))
        {
            $validatedData['metric_spec_sheet'] = $request->file('metric_spec_sheet')->store('spec_sheets', 'public');
        }

        $dto = new ProductData(
            $validatedData['name'],
            $validatedData['alloy'],
            $validatedData['density'],
            $validatedData['imperial_spec_sheet'] ?? null,
            $validatedData['metric_spec_sheet'] ?? null,
        );

        $product = $this->productService->store($dto);

        return $this->success($product, 'Product created successfully');
    }

It works well, but something feels off. If I add a new field to the products table, I have to update the validation rules,the DTO constructor and everywhere I populate data with the DTO structure (Like in my controller here). And if I reuse this logic elsewhere (say, in a CLI command or job), I have to re-duplicate the validation or extract it.

Is there a more conventional or scalable way to handle this kind of structure? I know I can use Form Requests for the validation, but then I’d have to extract the DTO creation logic too. Curious how others handle this cleanly.

fair pond
#

First: move the validation to a form request

#

Second: use a service layer to handle the logic related to creating, storing files, exception handling etc. You can use eithrr Action layer, service/service+repository, rich model

#

That's on you to decide which one

#

You have a product service already, but you are embeddig logic to your controller.

vital yarrow
#

Okok, I thought since the spec sheets are files directly in the request, it should've been in the controller

Could you develop on repository ? And i'm not sure what you mean by creating, since it is already in a service

fair pond
#

Repository is just an abstraction layer for the queries, on Lavaral i think is not necessary

#

Because we already have the Eloquent

fair pond