I'll-Be-Back I'll-Be-Back - 15 days ago 9
PHP Question

Multiple Open and Close Time array validation in Laravel?

I have array of open time and close time.

The inputs look like this:

<input type="text" name="time[1][open]">
<input type="text" name="time[1][close]">
<input type="text" name="time[x][open]">
<input type="text" name="time[x][close]">


This is a dump from
dd($request->all())


array:2 [
"days" => array:2 [
0 => "1" // Mon
1 => "2" // Tue
]
"time" => array:2 [
1 => array:2 [
"open" => "09:00"
"close" => "11:30"
]
2 => array:2 [
"open" => "16:00"
"close" => "21:00"
]
]
]


Using Laravel Request Validation - how do loop through between open and close time to validate to make sure it does not overlap of existing record in mysql database? For example, we may have Open:14:00 - Close:19:00 in the database but user have a requested of
"open" => "16:00"
and
"close" => "21:00"
- so the validation should not passed.

Update:

Example result in the
times
table, a day can have multiple open/close times.

id | day | open_time | close_time
-----------------------------------------------
1 | 1 | 13:30:00 | 15:00:00
2 | 2 | 16:30:00 | 20:00:00
3 | 3 | 09:30:00 | 14:30:00
4 | 3 | 18:00:00 | 22:00:00
-----------------------------------------------


You can see there is overlapping from
times.id=2
(16:30:00 - 20:00:00) and user request
"open" => "16:00"
and
"close" => "21:00"
. Validation should not passed.

Answer

This is not a complete answer but it might help OP. I still do not understand relation between days / time etc. this is boilerplate without logic that needs to be implemented


firstly make new provider (for custom validation rules)

$ php artisan make:provider ValidatorServiceProvider

and register it in config/app.php

    ...
    App\Providers\RouteServiceProvider::class,
    App\Providers\ValidatorServiceProvider::class,
    ...

Make new folder/file for new validation rule:

$ mkdir ./app/Validators
$ touch ./app/Validators/OverlappingTimeValidator.php

And put some code inside new Validator rule (can not make out the logic since I do not understand problem fully, perhaps I lack language skill to understand it)

<?php

namespace App\Validators;

class OverlappingTimeValidator
{
    public function validate($attribute, $value, $parameters, $validator)
    {
        //make sure you have valid time format (for each time[])
        //make sure open < close for each pair
        //compare each set of open-close times with each other
        //connect to database and get all required data from $parameters[0] table
        //to connect to database and get data use \DB::table($parameters[0])->get(); follow this https://laravel.com/docs/5.3/queries#retrieving-results
        //array_get($validator->getData(), $parameters[1], null); // gives you days user picked or null
        dd($attribute, $value, $parameters, $validator);
        return false; //in case validation fails
        return true; //in case validation passes
    }
}

run $ composer dump-autoload so new file is auto-loaded

register validation rule in ValidatorServiceProvider.php

public function boot()
{
    Validator::extend('overlapping_time', 'App\Validators\OverlappingTimeValidator@validate');
}

And finally rules in *Request should look like:

public function rules()
{
    return [
        'time' => 'overlapping_time:table_name,days'
    ];
}

You may use 'time.*' and validation will run against each time separately which you may not want! So use 'time' and make validation on whole array of times.

As I understand days is relevant attribute in validating time, therefore I added it as parameter, but you can change it. Please see what dd() in OverlappingTimeValidator@validate outputs.

In order to add error message open up ./resources/lang/en/validation.php and add (near bottom, really does not matter):

'overlapping_time' => 'The :attribute...',
Comments