Search code examples
phplaravellaravel-7

How to create custom validation rule for dependent input fields in laravel


In my input form, I have two fields; momentFrom & momentTo. I need to put a validation which gives error message if any of the following criteria fails.

  • momentFrom is greater than or equal to momentTo.
  • momentFrom is less than now.

My code for storing the data:

public function store(Request $request, Requisition $requisitionObj) {
    $momentFrom = strtotime($request->txtTravelDate . " " . $request->txtTimeFrom);
    $momentTo = strtotime($request->txtTravelDate . " " . $request->txtTimeTo);

    $timeValidation = $requisitionObj->validateTiming($momentFrom, $momentTo);
    if ($timeValidation['error']) {
        echo 'ERROR: ' . $timeValidation['message'];
        return view('requisitions.create');
    } else {
        /* store form data into requisition object */
        $requisitionObj->travel_date = $request->txtTravelDate;
        $requisitionObj->moment_from = $momentFrom;
        $requisitionObj->moment_to = $momentTo;

        $requisitionObj->save();
        
        return redirect()->route('requisitions.index');
    }
}

I have seen laravel custom validation rules where only one field can be validated at a time. But in my scenario I need to check both fields at a time depending on each other. How can I achieve this?

Thanks for any help in advance!


Solution

  • At last, I have solved this problem using FormRequest and AppServiceProvider. Thought this would help others who come to this place.

    First I have created FormRequest validator using following artisan command.

    php artisan make:request StoreRequisition
    

    Then added primary validation rules and messages into it.

    namespace App\Http\Requests;
    use Illuminate\Foundation\Http\FormRequest;
    
    class StoreRequisition extends FormRequest {
        public function authorize() {
            return true;
        }
    
        public function rules() {
            $rules = [
            'txtTravelDate' => 'required|date_format:Y-m-d|after_or_equal:today',
            'txtTimeFrom' => 'required|date_format:H:i|travel_time_validate',
            'txtTimeTo' => 'required|date_format:H:i',
            ];
            return $rules;
        }
    
    
        public function messages() {
            return [
                'txtTravelDate.required' => 'Travel date is required!',
                'txtTravelDate.date_format' => 'Invalid format for Travel Date!',
                'txtTravelDate.after_or_equal' => 'Travel Date should be today or later!',
                'txtTimeFrom.required' => 'Time From is required!',
                'txtTimeFrom.date_format' => 'Invalid format for Time From!',
                'txtTimeFrom.travel_time_validate' => 'Invalid time selected!',
                'txtTimeTo.required' => 'Time To is required!',
                'txtTimeTo.date_format' => 'Invalid format for Time To!',
                'listFunction.required' => 'Department to be selected!',
                'txtPickLoc.required' => 'Pickup Location is required!',
                'txtDropLoc.required' => 'Drop Location is required!',
                'listPurpose.required' => 'Travel Purpose to be selected!'
            ];
        }
    }
    

    Then inside app\Providers\AppServiceProvider, added the extra validation logic.

    public function boot() {
        Validator::extend(
            'travel_time_validate',
            function ($attribute, $value, $parameters, $validator) {
                $inputs = $validator->getData();
                /* convert time to moments */
                $momentFrom = strtotime($inputs['txtTravelDate'] . " " . $inputs['txtTimeFrom']);
                $momentTo = strtotime($inputs['txtTravelDate'] . " " . $inputs['txtTimeTo']);
    
                $result = true;
                if ($momentFrom >= $momentTo) {
                    $result = false;
                }
                return $result;
            }
        );
    }
    

    My Controller:

    public function store(StoreRequisition $request, Requisition $requisitionObj) {
    
        $validatedData = $request->validated();
    
        /* store form data into requisition object */
        $requisitionObj->requester_id = Auth::user()->id;
        $requisitionObj->travel_date = $request->txtTravelDate;
        $requisitionObj->time_from = $request->txtTimeFrom;
        $requisitionObj->time_to = $request->txtTimeTo;
        $requisitionObj->purpose_id = $request->listPurpose;
    
        /* Finally save the record into the database */
        $requisitionObj->save();
    
        return redirect()->route('requisitions.index');
    }