3
\$\begingroup\$

I have a problem. In my project the user can copy a menu for a specific day or for a specific week. The value that will be sent to the back-end will be something like:

2022-10-07 or 2022-W43

Depending on the selection of the user. But now in the back-end I need to query those items using the given date, but I am not allowed to use the week input (2022-W43), because that is not a valid date. What is a clean way to write the query, because this is my code right now:

public function scopeGetMenuItemsOnGivenDate(Builder $query, string $date): Builder
{
    $start = Carbon::parse($date);
    $end = Carbon::parse($date);
    $extraCondition = $start->dayOfWeek;

    // Check if string is meant for a week
    if (str_contains($date, 'W')) {
        $date = Carbon::parse($date);
        $startDateCopy = $date->copy();
        $start = $startDateCopy->startOfWeek();

        $endDateCopy = $date->copy();
        $end = $endDateCopy->endOfWeek();
        $extraCondition = '';
    }

    return $query
        ->whereDate('recurring_start', '<=', $end)
        ->whereDate('recurring_end', '>=', $start)
        ->where('recurring_days', 'like', '%' . $extraCondition . '%')
        ->OrwhereNull('recurring_end');
}

First I set the default values to be a given date, but then I check the string if it contains a W, so I know a week has been provided or a regular day. This is not a nice way to check, I prefer if I could use a Carbon date, and check if the recurring_start and recurring_end is inside the given Carbon date.

Can someone help me make this code clean and efficient, because I don't feel proud of this code :(

\$\endgroup\$
1
  • 1
    \$\begingroup\$ Can you give us more detail around a "... user can copy a menu for a specific day or for a specific week" Vs. "... query those items using the given date"? Is the code you showed related to copying the menu items or querying them? Edit your question with more details instead of replying in this comments section. Thx. \$\endgroup\$ Oct 11, 2022 at 14:06

1 Answer 1

3
\$\begingroup\$

Your function is trying to do two things at the same time, which is not aligned with the Single responsibility principle: it tries to make a query based on YYYY-MM-DD format or YYYY-WWW format.

To make it simpler, we could extract each of those into two functions. Each of the function would get a date in a specific format (YYYY-MM-DD or YYYY-WWW) and return a structure with start date and end date for your database query. The structure can be a DTO (Object), array or even JSON string, up to you.

This will bring the following benefits:

  • smaller function, with one single responsibility each
  • we can implement unit tests for your two new functions, which would make your code robust and reliable
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.