when add a product to my app, I check if property "is_force", user should add all required properties to request. but when sent with multipart/form-data header and if user does not send all required properties in the output just show number "1". and not created product.
output error

but when send with application/json and comment image and gallery validation in request show me correct form of validation error.
Comment Requests

correct form error

Controller:
public function storeForSeller(AddSellerProductRequest $request): \Illuminate\Http\JsonResponse
{
$uploaded = UploaderHelper::upload($request->file('image'), config('path.product'));
$category = $this->categoryRepository->findById($request->category_id);
$result = $this->productPropertyRepository->checkPropertyValidation($request->properties(null));
if(!$result){
return ControllerHelper::errorJsonResponse(trans('admin.invalid_property_items'));
}
$product = $this->productRepository->create($request->product([
'image' => $uploaded ,
'expire_date' => Carbon::now()->addDays($category->listing_duration),
'user_id' => auth('sanctum')->id()
]));
if (empty($product)) {
UploaderHelper::delete($uploaded);
return ControllerHelper::createError();
}
$this->productTagRepository->replaceTags($request->tags(), $product->id, auth('sanctum')->id());
$this->productPropertyRepository->createAll($request->properties($product->id));
$galleries = collect($request->galleries())->map(function ($item) use ($product){
return [
'title' => $product->title,
'product_id' => $product->id,
'url' => UploaderHelper::upload($item, config('path.product')),
'updater' => auth('sanctum')->id()
];
});
$result = $this->productGalleryRepository->insert($galleries->toArray());
if(!$result){
UploaderHelper::delete($uploaded);
$this->productRepository->deleteById($product->id);
return ControllerHelper::errorJsonResponse(trans('admin.error_image_upload'));
}
return ControllerHelper::successJsonData($product);
}
Request:
public function rules(): array
{
return [
'id' => ['nullable', 'numeric', Rule::exists('products', 'id')->where('status', ListingStatus::PENDING->value), new Ownership('product', false)],
'category_id' => ['required', Rule::exists('categories', 'id')->where('is_hidden', false)],
'product_status' => ['required', 'in:' . implode(',', ProductStatus::toArray()),],
'title' => ['required', 'max:500'],
'price' => ['required', 'numeric', 'min:0', 'max:1000000'],
'discount' => ['nullable', 'numeric', 'min:0', 'max:100'],
'description' => ['nullable', 'string', 'min:0', 'max:2000'],
'city_id' => 'nullable|integer|exists:' . Region::class . ',id',
'state_id' => 'nullable|integer|exists:' . Region::class . ',id',
'country_id' => 'nullable|integer|exists:' . Region::class . ',id',
'tags' => ['required', 'array', 'max:10'],
'tags.*' => ['required', 'string', 'max:50'],
'image' => [Rule::requiredIf(empty(request('id'))), 'mimes:jpg,png,jpe,jpeg', 'max:500', 'image'],
'galleries' => ['array', Rule::requiredIf(empty(request('id'))), 'max:5'],
'galleries.*' => ['required', 'mimes:jpg,png,jpe,jpeg', 'max:500', 'image'],
'properties' => ['array', Rule::requiredIf(empty(request('id'))), new ForceProperty()],
'properties.*.property_id' => ['required',Rule::exists('properties', 'id')],
'properties.*.property_item_id' => ['required',Rule::exists('property_items', 'id')],
];
}
public function product($merge, $except = null): array
{
return $this->safe()->merge([
'updater' => auth('sanctum')->id()
])->merge($merge)->except('id', 'tags', 'galleries', 'properties', $except);
}
public function tags(): array
{
return $this->get('tags');
}
public function galleries(): array
{
return $this->file('galleries');
}
public function properties($product_id): array
{
return collect($this->get('properties'))->map(function ($value) use ($product_id) {
$value['product_id'] = $product_id;
$value['updater'] = auth()->id();
return $value;
})->toArray();
}
ForceValidation:
class ForceProperty implements ValidationRule
{
/**
* Run the validation rule.
*
* @param \Closure(string): PotentiallyTranslatedString $fail
*/
public function validate(string $attribute, mixed $value, Closure $fail): void
{
$forceProperties = CategoryProperty::query()->where('is_force', true)->pluck('id','title')->toArray();
$propertyIds = collect($value)->pluck('property_id')->toArray();
$missingForceProperties = array_diff($forceProperties, $propertyIds);
if (!empty($missingForceProperties)) {
$missingForcePropertyTitles = array_flip($missingForceProperties);
$fail("Please provide all required properties with IDs: " . implode(', ', $missingForcePropertyTitles));
}
}
}
I can't find any solution for this problem.
Accept: application/jsonheader, otherwise how does Laravel know to respond in jsontryandcatchto see the error,