减少过多的if语句

时间:2018-01-18 07:53:03

标签: php laravel if-statement conditional-statements

所以我有一个输入字段用于搜索我的数据库。我希望能够只搜索dayday + monthday + month + year,就像这样:

仅限18日 18-1 //天+月 18-1-2018 //日+月+年

我首先需要做的是使用explode分割结果:

$date = explode("-", $this->string); // $this->string is set in the constructor

这会给我一个1,2或3个结果的数组(我们假设输入是正确的)。

问题在于我的方法中有太多if/else语句:

搜索():

public function search()
{
    $date = explode("-", $this->string);

    if (array_key_exists(2, $date))
    {
        if (!is_numeric($date[0]) || !is_numeric($date[1]) || !is_numeric($date[2]))
        {
            return false;
        }

        return $this->dateCheck($date[0], $date[1], $date[2]);
    }

    if (array_key_exists(1, $date))
    {
        if (!is_numeric($date[0]) || !is_numeric($date[1]))
        {
            return false;
        }

        return $this->dateCheck($date[0], $date[1]);
    }

    if (array_key_exists(0, $date))
    {
        if (!is_numeric($date[0]))
        {
            return false;
        }

        return $this->dateCheck($date[0]);
    }

    return false;
}

dateCheck():

private function dateCheck($day = null, $month = null, $year = null)
{
    if ($year == null)
    {
        $year = Carbon::now()->format('Y');
    }

    if ($month == null)
    {
        $month = Carbon::now()->format('m');
    }

    if ($day == null)
    {
        $day = Carbon::now()->format('d');
    }

    return (bool) checkdate($month, $day, $year);
}

我的问题是,任何人都有更好的解决方案来减少任何数量的if/else陈述吗?

PS。如果在任何地方返回false,将会有一个重定向返回到输入页面,并显示一条消息,指出没有结果。

4 个答案:

答案 0 :(得分:2)

假设您使用PHP> = 5.6,则可以使用splat运算符(...),也称为参数解包。您可以在PHP manual here

中阅读

splat运算符将获取数组中的元素并将它们作为单独的参数传递。

public function search()
{
    $date = explode("-", $this->string);

    // If any items are not numeric, this will evaluate to false.
    $numeric = array_reduce($date, function ($carry, $item) {
        return $carry && is_numeric($item);
    }, true);

    if (empty($date) || !$numeric) {
        return false;
    }

    return $this->dateCheck(...$date);
}

如果您还没有使用PHP 5.6,那么您的最后几行将需要有所不同。您可以使用call_user_func_array()函数,该函数使用数组项作为参数调用函数。

return call_user_func_array([$this, 'datecheck'], $date);

或者,您可以设计数组,以便索引始终存在:

$date = array_replace([null, null, null], $date);

return $this->dateCheck($date[0], $date[1], $date[2]);

您还可以使用三元快捷键操作符(?:)将dateCheck函数缩减为:

private function dateCheck($day = null, $month = null, $year = null)
{
    return (bool) checkdate(
        $month ?: Carbon::now()->format('m'),
        $day ?: Carbon::now()->format('d'),
        $year ?: Carbon::now()->format('Y')
    );
}

这基本上表示如果变量为false-y(null,0,'',false等),则将其替换为Carbon输出。如果你想对null检查严格,并且你在PHP 7上,你可以使用null coalesce运算符(??)而不是三元快捷运算符。然后,只有在变量为null时才会使用Carbon值。

答案 1 :(得分:1)

$date = explode('-', $x);
$date = array_replace([date('d'), date('m'), date('Y')], $date);

emo

答案 2 :(得分:1)

您可以大量简化代码。 dateCheck函数在逻辑上不能减少那么多,但我们可以写得更漂亮:

$year = $year === null ? Carbon::now()->format('Y') : $year;
$month = $month === null ? Carbon::now()->format('m') : $month;
$day = $day === null ? Carbon::now()->format('d') : $day;
return (bool) checkdate($month, $day, $year);

search函数可以使用实用程序函数来减少确定日期是否有效所需的开销量。像这样:

$date = explode("-", $this->string);
if (count($date) === 3 and static::isValidDate($date)) {
    return $this->dateCheck($date[0], $date[1], $date[2]);
}
if (count($date) === 2 and static::isValidDate($date)) {
    return $this->dateCheck($date[0], $date[1]);
}
if (count($date) === 1 and static::isValidDate($date)) {
    return $this->dateCheck($date[0]);
}
return false;

最后,新的(静态)方法isValidDate

private static function isValidDate(array $date) {
    foreach ($date as $field) {
        if (!is_numeric($field)) {
            return false;
        }
    }

    return true;
}

您还可以将编码器重写为更简单,重用相同的isValidDate方法,并将search函数更改为:

$date = explode("-", $this->string);
if (static::isValidDate($date)) {
    return $this->dateCheck($date);
}
return false;

并且dateCheck到(请注意,此函数的参数现在是一个数组的date变量):

$year = !isset($date[0]) ? Carbon::now()->format('Y') : $date[0];
$month = !isset($date[1]) ? Carbon::now()->format('m') : $date[1];
$day = !isset($date[2]) ? Carbon::now()->format('d') : $date[2];
return (bool) checkdate($month, $day, $year);

答案 3 :(得分:1)

在搜索功能中,您只需将日期字符串转换为数组

即可
    $date = explode("-", $this->string);

过滤掉非数值(不应该在那里)

    $valid = array_filter($date, 'is_numeric');

并检查是否所有有效的Il有效(评估的短路)返回实际计算的结果

    return (count($date) === count($valid)) && 
            call_user_func_array(array($this, 'dateCheck'), $valid);    

public function search()
{
    $date = explode("-", $this->string);
    $valid = array_filter($date, 'is_numeric');
    return (count($date) === count($valid)) && 
            call_user_func_array(array($this, 'dateCheck'), $valid);    
}

对于datecheck函数:我们只需在传递的参数末尾添加默认值,只需使用前三个值,不需要ifs或三元操作。

private function dateCheck($day = null, $month = null, $year = null)
{
    $date = array_filter(func_get_args(), 'is_int');
    array_push($date, Carbon::now()->format('m'), Carbon::now()->format('Y');
    list($day, $month, $year) = array_slice($date, 0,3);
    return (bool) checkdate($month, $day, $year);
}