@peterdickins You need to think about the inputs and outputs of your service classes more. A service class shouldn’t be receiving arrays, nor returning arrays. An array says nothing about its contents. It doesn’t enforce keys, or their values or the types of any values.
If you have a service class method called createProduct, then it should receive the information it needs to create a product, and the result it returns should be a created Product entity instance (so that could be an Eloquent model or some other entity class in your application if you have one).
For the information you send to the method, this is where a DTO would come in. If you have your createProduct method then you might have a CreateProductAttributes class that actually enforces the attributes it should contain. This way, the DTO can only be constructed with valid data, and the service class method can only be called with a valid DTO instance. If your service class method is just accepting and returning arrays then that’s just a hotspot for bugs.
So, your method signature should look something like this:
public function createProduct(CreateProductAttributes $attributes): Product;
Reading that, I know I need to pass it an instance of CreateProductAttributes, and I’m going to get a Product instance back. I’m not reading it going, “It takes an array, and returns an array. OK, what does the attributes array need to contain? What does the array it return contain? Great, I’ve now got to open up that class and read that method to work out what it does…”