Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

jrdavidson's avatar

Adding Fields To Validated That Aren't Directly Validated

I'm running into a problem where I'm trying to send all the validated request data to the create method for an Eloquent model. I found a macro that can help send all validated data except for any fields that shouldn't be send to the create method. The problem here is that I can't do this because of the afterValidationHook method in my request class. The reason why I can't is because when it goes to create the model its going to look for the feet and inches parameters and those don't exist in the database table.

Does anyone have any suggestions on what I could do here so that I could easily pass validated data minus the feet and inches but plus the height parameter added in the hook?

Patient::create($request->validatedExcept('started_at'));
<?php

namespace App\Http\Requests\Patients;

use App\Models\Patient;
use Illuminate\Validation\Validator;
use Illuminate\Foundation\Http\FormRequest;

class StoreRequest extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
            'feet' => [
                'required',
                'integer',
                'min:5',
                'max:7'
            ],
            'inches' => [
                'required',
                'integer',
                'max:11'
            ],
            'started_at' => [
                'nullable',
                'string',
                'date_format:Y-m-d H:i:s'
            ],
            // More validated fields
        ];
    }

    /**
     * Configure the validator instance.
     *
     * @param  \Illuminate\Validation\Validator  $validator
     * @return void
     */
    public function withValidator(Validator $validator): void
    {
        $validator->after(function (Validator $validator) {
            if ($validator->errors()->isEmpty()) {
                $this->merge(['height' => ($this->input('feet') * 12) + $this->input('inches')]);
                $this->offsetUnset('feet');
                $this->offsetUnset('inches');
            }
        });
    }
}

Request::macro('validatedExcept', function ($keys) {
    $keys = is_array($keys) ? $keys : func_get_args();

    $results = $this->validated();

    Arr::forget($results, $keys);

    return $results;
});
0 likes
17 replies
bobbybouwmann's avatar

I would expect that offsetUnset would work here indeed. The only thing I can think of is that $this is not referring to the correct instance.

Try this instead

public function withValidator(Validator $validator): void
{ 
    $this->merge(['height' => ($this->input('feet') * 12) + $this->input('inches')]);
    $this->offsetUnset('feet');
    $this->offsetUnset('inches');
}
Snapey's avatar

You could accept feet and inches into your model as mutators and then create the height during updating and creating model event hooks ?

Snapey's avatar

or

Patient::create($request->validatedExcept('started_at', 'feet', 'inches') + 
    ['height' => ($request->feet * 12)+ $request->inches ]);

and then not use the after validation hook at all

jrdavidson's avatar

@bobbybouwmann I tried your solution and unfortunately came up with the same results were it still adds the feet and inches back into the validated fields. Is there a problem I'm having from my macro above?

jrdavidson's avatar

@snapey At this time I'm not looking to store the feet and inches in the database along side the height. I'd rather just maintain the one field in the database.

As far as the second option you provided. It could work however I was hoping to keep that logic contained in the request class.

martinbean's avatar

@xtremer360 Are you specifying the fillable fields in the model? As if so (and feet and inches aren’t fillable) then they’ll just be discarded if you pass the request data to your model:

Patient::create($request->input());
martinbean's avatar

@xtremer360 This is why I prefer to explicitly set fillable columns instead of having everything fillable by default.

jrdavidson's avatar

@martinbean I added the fields that needed to be fillable meaning the patients name and height and a few other fields and unfortunately it did not improve my results.

jrdavidson's avatar

If I do $request->all() as the first line of my store method then it shows the height property with the correct value AND it removed the feet and inches properties, but when I call validated() on the request it gives me the true validated fields. Is there an alternative so that I can handle this problem?

jrdavidson's avatar

@snapey I'm wondering if I try and use the mutator approach with the feet and inches. Would I just unset the property? I'm having a hard time understanding what I would do with the mutator for those two fields. Can you explain that portion for me please?

public function setFeetAttribute($value)
{
        $this->attributes['feet'] = $value;
}

public function setInchesAttribute($value)
{
        $this->attributes['inches'] = $value;
}
martinbean's avatar

@xtremer360 The problem is, you’re trying to get a mix of validated fields with non-validated fields. Laravel is working exactly as it should: it’s returning only the fields that were validated. The height field wasn’t part of the request nor was it validated, so it’s not going to be present through the validated() method.

martinbean's avatar
Level 80

@xtremer360 I can’t say I’ve created a “pseudo” property like this in a request. But I set which columns are fillable and then use $request->validated() when creating/updating a model.

In your case you could either use $request->input() instead to get all request data and only set values for columns that are fillable (including your height column). If you’re absolutely adamant on using validated() for whatever reason, then you could fill your model with the validated request data, and then explicitly set the height value before saving:

$patient = new Patient($request->validated());
$patient->height = $request->input('height');
$patient->save();

Or, you could add your height value to the validated values:

$patient = Patient::create(array_merge($request->validated(), [
    'height' => $request->input('height'),
]));

Or, the simplest method, override the validated() method in your StorePatientRequest class if you’re sure you want the height value in there:

class StorePatientRequest extends FormRequest
{
    // Other form request methods like rules(), etc.

    public function validated()
    {
        return array_merge(parent::validated(), [
            'height' => $this->input('height'),
        ]);
    }
}

You can then use validated() as intended:

$patient = Patient::create($request->validated());
4 likes
BluKoffee's avatar

@martinbean Thank you very much, your answer helped me too solve the same problem. I think this solution

Patient::create(array_merge($request->validated(), [
    'height' => $request->input('height'),
]));

makes more sense and it is more readable as it shows what fields are passed to the instance created without going through the validator (in my case)

Please or to participate in this conversation.