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

AbehoM's avatar

Only return fields that are enabled based on another field

In order for you understand what I need I have to give you the full story:

I'm planning on using this library (https://github.com/spatie/opening-hours) to make a kind of scheduling for opening hours, the thing is that this library doesn't have database saving support, it's more like a parsing so I need help on what is the best way to save and retrieve this data from the database and use it to parse it.

$openingHours = OpeningHours::create([
    'monday'     => ['09:00-12:00', '13:00-18:00'],
    'tuesday'    => ['09:00-12:00', '13:00-18:00'],
    'wednesday'  => ['09:00-12:00'],
    'thursday'   => ['09:00-12:00', '13:00-18:00'],
    'friday'     => ['09:00-12:00', '13:00-20:00'],
    'saturday'   => ['09:00-12:00', '13:00-16:00'],
    'sunday'     => [],
]);

It's way more advanced, supports exceptions, hollydays and stuff like that but I'm looking for is kinda simpler than that, it's just the days of the week.

On the user panel I plan on adding a checkbox so the user can select if he wants this day of the week or not listed on the schedule.

That is what I thought about saving on the database:

The OpeningHours class accepts an array with this format: 'monday' => ['09:00-12:00', '13:00-18:00'] so I was thinking about creating two fields (for each day of the week), one as type json with the name of the day, like $table->json('monday'); and store the ['09:00-12:00', '13:00-18:00'] ranges and another field called monday_enabled (boolean) so I know if I should return it or not.

That is what I thought, the thing is: I need somehow to be able to exclude a day of the week from returning based on if the user checked that day or not. For example: imagine that the user do have his schedule on Monday but this Monday he decides that he is not going to open for some reason, he just have to uncheck the Monday day but the range will still be saved so he can enable later on.

What is the best way to store that information, retrieve and organize as array like I mentioned above for OpeningHours based on if it's enabled or not?

0 likes
6 replies
Sti3bas's avatar
Sti3bas
Best Answer
Level 53

@zefex I'm using this package myself and I'm storing the full array in a single json field in my model's table.

In your case, I would store additional enabled value for each day and filter out disabled days before creating an instance of OpeningHours.

[
    'monday' => [
        '09:00-11:00',
        '13:00-19:00',
        'data' => [
            'enabled' => true
        ],
    ],
    'tuesday' => [
        '09:00-11:00',
        '13:00-19:00',
        'data' => [
            'enabled' => false
        ],
    ],
]

Creating OpeningHours instance:

OpeningHours::create(collect($openingHours)->filter(function ($day) {
    return $day['data']['enabled'];
})->all());
AbehoM's avatar

@sti3bas I thought about in the model Schedule I could like create a field called enabled so I can retrieve only the enabled ones, this would get rid of the extra data field on the json, what you think?

I have 2 questions:

  1. How do you retrieve the data from the database and put back on the OpeningHours?
  2. How did you structured your frontend (form) to accept the user input and handled on the controller to save on the database?
Sti3bas's avatar

@zefex will you ever need to query opening hours in the database? If no, storing everything in a single json column seems a lot easier to me.

1: I have a method in my model class, so I can call it like $model->openingHours()->isOpenAt(new DateTime('2016-12-25')); :

public function openingHours()
{
    return OpeningHours::create($this->opening_hours ?: []);
}

2: I'm using Vue components. I have a component for a day which consists of dynamic number (user can click a button to add new one) of interval components. Then I emit events to the parent OpeningHours component where I store all the details in the array (same format as used in the package). Then after user clicks save button I'm sending a patch request with axios. In the controller I'm validating (I have few custom validation rules) the array and then updating my model:

$model->update([
   'opening_hours' => $request->validated()['opening_hours'] ?: null,
]);
AbehoM's avatar

@sti3bas Is it possible for you to share your Vue component and how you validated it? Thank you

Sti3bas's avatar

@zefex the validation is quite simple, but Vue components are ~600 lines of code, because it handles some additional functionality, so it would be hard to extract the code only for the basic functionality, sorry.

Validation rules:

'opening_hours' => [
    'bail',
    'array',
    new WeekdayNames(),
],
'opening_hours.*' => [
    'bail',
    'array',
    'max:2', // only 2 intervals per day - business rule
],
'opening_hours.*.*' => [
    'bail',
    'array',
    'max:2', // ['hours', 'data']
],
'opening_hours.*.*.hours' => [
    'bail',
    new TimeRange(),
],
// other rules for validating data

WeekdayNames validation rule:

public function passes($attribute, $value)
{
    foreach ($value as $weekday => $i) {
        if (! \Spatie\OpeningHours\Day::isValid($weekday)) {
            return false;
        }
    }

    return true;
}

TimeRange validation rule:

public function passes($attribute, $value)
{
    try {
        \Spatie\OpeningHours\TimeRange::fromString($value);

        return true;
    } catch (\Exception $e) {
        return false;
    }
}

Please or to participate in this conversation.