0

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.

The Blind Hawk
  • 1,199
  • 8
  • 24
  • Do you use `$request->all()` to validate? – geertjanknapen May 25 '22 at 10:19
  • Why are you going to delete fields of request while you can exclude fields that you need? – Sahand Moghadam May 25 '22 at 11:35
  • @geertjanknapen No, I use ```$request->validated()``` – The Blind Hawk May 26 '22 at 01:47
  • @Sahand Moghadam I am fine with either deleting or excluding. I tried both, both didn't work. (I tried ```$request->except()```). Or are you referring to another method? – The Blind Hawk May 26 '22 at 01:49
  • Let's just stick to ` $this->request->remove('sales_start');` method. please take it out from all if statements and check whether it is working. besides, `$request->validated()` is responsible for returning fields that the validation rules have validated. – Sahand Moghadam May 26 '22 at 06:02
  • I tried taking the code out of all if statements, but nothing changed. As far as I know ```$request->validated()``` should not be validating the field if it were removed successfully, because of ```sometimes|required``` @Sahand Moghadam – The Blind Hawk May 26 '22 at 06:16

3 Answers3

1

Can't find anything about deleting. But acording to Laravel docs you pick what keys you need from a request as follows:

$request->only(['username', 'password']);
// plug everything you need into the array.
$request->except(['username', 'password']);
//plug everything you don't need into the array

The latter is probably most useful to you.

Example:

Say I have the following keys: ['username', 'password', 'randomVal'];

$request->only(['username', 'password']);
// Output:
['username', 'password']

$request->except(['username', 'password']);
// Output:
['randomVal']
geertjanknapen
  • 1,159
  • 8
  • 23
  • Thanks, but I already tried this (in the commented out code). For some reason it is not having any effect. – The Blind Hawk May 26 '22 at 01:35
  • What is `$this`, usually it refers to the calling object, so how does it (in your case) refer to the request? Can you show some more code. – geertjanknapen May 27 '22 at 06:06
  • I added the code to the original comment – The Blind Hawk May 30 '22 at 05:16
  • So if this refers to an instance of `FormRequest` how do you see it removing keys? `FormRequest` is not the same as `Request` try using `$request` instead of `$this` for me.. – geertjanknapen May 30 '22 at 07:53
  • ```FormRequest``` extends ```Request``` so it actually is "the same" ([docs](https://laravel.com/api/5.5/Illuminate/Foundation/Http/FormRequest.html)). And using ```$this->``` inside the request should be the same as using ```$request->```. I also tested out ```$request```, but unfortunately nothing changed. – The Blind Hawk May 30 '22 at 10:10
  • For reference I tried using ```$request``` inside the controller, so I put ```$request->except([...stuff...])``` right before ```$request->validated```. – The Blind Hawk May 30 '22 at 10:19
  • Well if its a `Request` then `->except([...])` and `->only([...])` should work.. are you missing something else? – geertjanknapen May 30 '22 at 10:52
  • I don't think I'm missing anything, since other methods such as ```merge()```are working fine. I will later on try and removing some codes from the ```VideoRequest``` to see if something was interfering. – The Blind Hawk May 31 '22 at 09:19
0

To remove (unset) a key from a Request before it goes to the Controller you can use offsetUnset()
inside your request:

 protected function prepareForValidation()
    {
        $this->offsetUnset('sales_start');//same goes for the other key to remove...
    }
ml59
  • 1,495
  • 1
  • 9
  • 10
0

This is a bit of an ugly answer.
Instead of modifying the request before the validation, I tried adding exclude when getting rules().
So something along these lines:

public function rules() {
    $ex = $this->isMethod('put') && Video::salesStarted($video_id) ? 'exclude|' : '';
    return [
        'sales_start' => $ex.'sometimes|required|other_stuff',
    ];
}

Note that the validation 'exclude' only works if added first.
So this won't work:

'sometimes|required|other_stuff|exclude' //exclude is called last

I am still unable to find out why remove(), exclude(), offsetUnset() were not working, so this is not the right answer, but I hope it helps if someone is having the same issue.

Edit
Setting this as correct answer as I was unable to find an alternative solution/fix.

The Blind Hawk
  • 1,199
  • 8
  • 24