laravelvalidationlaravel-request

Laravel request remove fields before validation


I am trying to remove some fields before they are validated.
Trying to attempt this inside prepareForValidation()

use Illuminate\Foundation\Http\FormRequest;

class VideoRequest extends ApiRequest
{

    // ..code..

    protected function prepareForValidation()
    {
        $this->merge([
            'public' => $this->toBoolean($this->public),
            'notify' => $this->toBoolean($this->notify),
        ]);

        $video_id = $this->route('video_id');
        if($this->isMethod('put') && Video::salesStarted($video_id)){
            Log::info('removing sales');
            // attempt 1
            $this->except(['sales_start', 'tickets', 'price']);
            // attempt 2
            $this->request->remove('sales_start');
            // attempt 3
            $this->offsetUnset('sales_start');
        }
        if($this->isMethod('put') && Video::streamStarted($video_id)){
            Log::info('removing streams');
            // attempt 1
            $this->except(['stream_start', 'stream_count', 'archive']);
            // attempt 2
            $this->request->remove('sales_start');
            // attempt 3
            $this->offsetUnset('sales_start');
        }
        
        $thumb = $this->uploadThumbnail($video_id);
        if($thumb !== null){
            $this->merge($thumb);
        }
    }

    // ..code..

}

I made sure the code was entering inside the if statement, however the fields are not being removed.

Running $this->request->remove() and $this->except() have no effect.
If I add safe() it throws Call to a member function safe() on null.
I also tried to use unset() but nothing seems to work.

The rules for the dates are like so:

'sales_start' => 'sometimes|required|date|after:now|before:stream_start',
'stream_start' => 'sometimes|required|date|after:now',

but the $request->validated() returns the errors although it shouldn't be validating the deleted fields.

"sales_start": [
    "The sales start must be a date after now."
],
"stream_start": [
    "The stream start must be a date after now."
]

Why are the fields not being deleted?

Edit

As requested I added some code.
This is what ApiRequest looks like:

use Illuminate\Http\Exceptions\HttpResponseException;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Contracts\Validation\Validator;

abstract class ApiRequest extends FormRequest
{
    protected function failedValidation(Validator $validator): void
    {
        $response['data']    = [];
        $response['api_status']  = 'ng';
        $response['status_message'] = 'failed validation';
        $response['errors']  = $validator->errors()->toArray();

        throw new HttpResponseException(
            response()->json( $response, 422 )
        );
    }

    protected function toBoolean($booleable)
    {
        return filter_var($booleable, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE);
    }
}

And the request is called from the controller like so:

public function update(VideoRequest $request, $video_id)
{
    ... some code ...

    $validated = $request->validated();

    ... some code ...
}

so $this refers to the VideoRequest that extends FormRequest.


Solution

  • None of the above is really correct, but the following will work.

    In protected function prepareForValidation(), you can do something like this:

    protected function prepareForValidation()
    {
       $input = $this->input();
    
       unset($input['my_key']);
    
       $this->replace($input);
    }
    

    That will let you change and replace data before it's validated.

    Of course you can also collect() the $this->input() data before working with it, if you prefer to work with a collection.