php Laravel - given a certain argument, call different function I am building a simple calendar with recurring events.

CalendarEvent.php

id
start_date


CalendarRecurringPattern.php

parent_id
pattern_type // daily, weekly, monthly, yearly ...


Using pattern_type i build each following occurrence starting from start_date, using a recursive function and Carbon::class. What bugs me is the function getNextOccurrence(), I'd like to refactor the if/else block because it's not very clean. Here it is:


use \Carbon\Carbon;
....

public function getNextOccurrence(Carbon $startDate) {

    $pattern_type = $this->getPatternType() // daily, weekly...

    if ($pattern_type == 'daily') {
        $startDate->addDay();
    } else if ($pattern_type == 'weekly') {
        $startDate->addWeek();
    } else if ($pattern_type == 'monthly') {
        $startDate->addMonth();
    } else if ($pattern_type == 'yearly') {
        $startDate->addYear();
    }

}


Thanks!
I don't personally see a problem with the way its currently structured as there aren't that many options, but you could do it a couple of other ways;

Option 1

Array function name mapping (hacky name I just came up with), you could do the following; 

$functionMap = [
    "daily" =&gt; "addDay",
    "weekly" =&gt; "addWeek",
    "monthly" =&gt; "addMonth",
    "yearly" =&gt; "addYear"
];

if(!isset($functionMap[$pattern_type])){
    throw new \Exception("Can't find patern type $pattern_type", 1);
}

$startDate-&gt;$functionMap[$pattern_type]();


This might be seen as a sin by the PHP community but it works none the less 

Option 2

You could use a switch which probably isn't a sin by the community. 

switch ($pattern_type) {
    case "daily":
        // Do the daily task
        break;
    case "weekly":
        // Do the weekly task
        break;
    case "monthly":
        // Do the monthly task
        break;
    case "yearly":
        // Do the yearly task
        break;
    default: 
        throw new \Exception("Can't find pattern type $pattern_type", 1);
}


Conclusion

I would add some exception / error that can be picked up if a non matched  pattern_type is passed.

I would also convert the "magic strings" E.G "daily" to constants in case you need to re-use, change or update them in the future!

In terms of line count; 


your way 10 lines of code
option 1  11 lines of code
option 2  15 lines of code


The switch &amp; if statements may have some advantages when doing code analysis aswel where the expected required input values can be picked up.