对PHP中的简单开关感到困惑(5.5.38)

时间:2017-04-07 11:32:27

标签: php switch-statement

我已经设置了以下类,它模仿我正在处理的一个并尝试修复。

目标

根据传入的初始值返回费用(值)。

问题

我对以下当前代码有两个问题:

  1. 当传入的第一个值 0 (零) 12p 返回时不正确 - 它应该被第一个案例捕获并返回的 15P

  2. 我还没有解决这个问题,但是我想要回复最后一个案例的发行费用(如果没有定义下一个案例)。对于下面的例子;要设置的最后一个限制是$lower_3变量 - 这意味着传入的任何大于 31 * 的值都应返回 10p 的费用。然而,我看到null正在返回,因为支票刚刚落到最后一个案例。

  3. 代码

    <?php
    
    class IssuanceScheme
    {
        private $lower_1 = 0;
        private $upper_1 = 20;
        private $issuanceFee_1 = '15p';
    
        private $lower_2 = 21;
        private $upper_2 = 30;
        private $issuanceFee_2 = '12p';
    
        private $lower_3 = 31;
        private $upper_3 = null; //50;
        private $issuanceFee_3 = '10p';
    
        private $lower_4 = null; //51;
        private $upper_4 = null; //75;
        private $issuanceFee_4 = null;
    
        private $lower_5 = null; //76;
        // no $upper_5
        private $issuanceFee_5 = null;
    
        public function calculateIssuanceFee($volume)
        {
            $issuanceFee = $this->issuanceFee_1;
    
            switch ($volume) {
                case ($volume >= $this->lower_1 && $volume <= $this->upper_1):
                    $issuanceFee = $this->issuanceFee_1;
                    break;
                case ($volume >= $this->lower_2 && $volume <= $this->upper_2):
                    $issuanceFee = $this->issuanceFee_2;
                    break;
                case ($volume >= $this->lower_3 && $volume <= $this->upper_3):
                    $issuanceFee = $this->issuanceFee_3;
                    break;
                case ($volume >= $this->lower_4 && $volume <= $this->upper_4):
                    $issuanceFee = $this->issuanceFee_4;
                    break;
                case ($volume >= $this->lower_5):
                    $issuanceFee = $this->issuanceFee_5;
                    break;
            }
    
            return $issuanceFee;
        }
    }
    
    $issuanceScheme = new IssuanceScheme;
    
    // 15p
    echo sprintf("Passed in: %s, Exp: %s, Got: %s", 0, '15p', $issuanceScheme->calculateIssuanceFee(0));
    echo sprintf("Passed in: %s, Exp: %s, Got: %s", 5, '15p', $issuanceScheme->calculateIssuanceFee(5));
    echo sprintf("Passed in: %s, Exp: %s, Got: %s", 10, '15p', $issuanceScheme->calculateIssuanceFee(10));
    echo sprintf("Passed in: %s, Exp: %s, Got: %s", 15, '15p', $issuanceScheme->calculateIssuanceFee(15));
    echo sprintf("Passed in: %s, Exp: %s, Got: %s", 20, '15p', $issuanceScheme->calculateIssuanceFee(20));
    
    // 12p
    echo sprintf("Passed in: %s, Exp: %s, Got: %s", 25, '12p', $issuanceScheme->calculateIssuanceFee(25));
    echo sprintf("Passed in: %s, Exp: %s, Got: %s", 30, '12p', $issuanceScheme->calculateIssuanceFee(30));
    
    // 10p
    echo sprintf("Passed in: %s, Exp: %s, Got: %s", 50, '10p', $issuanceScheme->calculateIssuanceFee(50));
    echo sprintf("Passed in: %s, Exp: %s, Got: %s", 60, '10p', $issuanceScheme->calculateIssuanceFee(60));
    echo sprintf("Passed in: %s, Exp: %s, Got: %s", 75, '10p', $issuanceScheme->calculateIssuanceFee(75));
    echo sprintf("Passed in: %s, Exp: %s, Got: %s", 100, '10p', $issuanceScheme->calculateIssuanceFee(100));
    

    结果

    Passed in: 0, Exp: 15p, Got: 12p // Error, expected is 15p
    Passed in: 5, Exp: 15p, Got: 15p
    Passed in: 10, Exp: 15p, Got: 15p
    Passed in: 15, Exp: 15p, Got: 15p
    Passed in: 20, Exp: 15p, Got: 15p
    Passed in: 25, Exp: 12p, Got: 12p
    Passed in: 30, Exp: 12p, Got: 12p
    Passed in: 50, Exp: 10p, Got: // Not implemented (see goal 2, and not below)
    Passed in: 60, Exp: 10p, Got:
    Passed in: 75, Exp: 10p, Got:
    Passed in: 100, Exp: 10p, Got:
    

    第二个目标尚未实施,但我想退回最后一笔满意的发行费用。在这种情况下,应该返回 10p ,因为传入的值大于 31

3 个答案:

答案 0 :(得分:5)

你误解了switch陈述

switch($var) {
    case $val:
        //something

平均值

  

如果$var == $val则执行//something

所以在你的代码中它是:

switch ($volume) {
    case ($volume >= $this->lower_1 && $volume <= $this->upper_1):
        $issuanceFee = $this->issuanceFee_1;
        break;

表示

  

如果$volume == ($volume >= $this->lower_1 && $volume <= $this->upper_1)则执行$issuanceFee = $this->issuanceFee_1;

$volume=0并非如此,因为($volume >= $this->lower_1 && $volume <= $this->upper_1)true,因此条件$volume == true0 == true

您需要将代码重新组织为if {} elseif {} else {}语句。

对于第二个问题,您可以将$volume <= $this->upper_1更改为($this->upper_1===null || $volume <= $this->upper_1),将其他级别更改为null

如果设置为public function calculateIssuanceFee($volume) { $issuanceFee = $this->issuanceFee_1; if ($volume >= $this->lower_1 && ($this->upper_1===null || $volume <= $this->upper_1)) { return $this->issuanceFee_1; } if ($volume >= $this->lower_2 && ($this->upper_2===null || $volume <= $this->upper_2)) { return $this->issuanceFee_2; } if ($volume >= $this->lower_3 && ($this->upper_3===null || $volume <= $this->upper_3)) { return $this->issuanceFee_3; } if ($volume >= $this->lower_4 && ($this->upper_4===null || $volume <= $this->upper_4)) { return $this->issuanceFee_4; } if ($volume >= $this->lower_5) { return $this->issuanceFee_5; } } (这意味着无限),将跳过上限检查。

Passed in: 0, Exp: 15p, Got: 15p 
Passed in: 5, Exp: 15p, Got: 15p 
Passed in: 10, Exp: 15p, Got: 15p 
Passed in: 15, Exp: 15p, Got: 15p 
Passed in: 20, Exp: 15p, Got: 15p 
Passed in: 25, Exp: 12p, Got: 12p 
Passed in: 30, Exp: 12p, Got: 12p 
Passed in: 50, Exp: 10p, Got: 10p 
Passed in: 60, Exp: 10p, Got: 10p 
Passed in: 75, Exp: 10p, Got: 10p 
Passed in: 100, Exp: 10p, Got: 10p

以下是工作示例: https://3v4l.org/uamib

(\w+)=((?:(?!&startrow).)+)

答案 1 :(得分:2)

您使用开关盒是错误的。 switch()之后的任何内容都应该是与$volume > $lower中的内容匹配的值。像$volume这样的表达式将被计算为布尔值,并且此布尔值将与switch($volume)中的if变量进行比较。

我建议只使用早期退货的public function calculateIssuanceFee($volume) { if ($volume >= $this->lower_1 && $volume <= $this->upper_1) { return $this->issuanceFee_1; } if ($volume >= $this->lower_2 && $volume <= $this->upper_2) { return $this->issuanceFee_2; } if ($volume >= $this->lower_3 && $volume <= $this->upper_3) { return $this->issuanceFee_3; } if ($volume >= $this->lower_4 && $volume <= $this->upper_4) { return $this->issuanceFee_4; } if ($volume >= $this->lower_5) { return $this->issuanceFee_5; } return $this->issuanceFee_1; } 语句:

class IssuanceScheme
{
    private $fees = [
        ['min' => 0, 'max' => 20, 'fee' => '15p'],   
        ['min' => 21, 'max' => 30, 'fee' => '12p'],   
    ];
    private $defaultFee = '10p';

    public function calculateIssuanceFee($volume)
    {
        foreach ($this->fees as $fee) {
            if ($volume >= $fee['min'] && $volume <= $fee['max']) {
                return $fee['fee'];
            }
        }
        return $this->defaultFee;
    }
}

编辑:再次查看您的代码,您可能真正想要的是定义一个带有下限和上限的费用列表,如果没有匹配则返回默认费用。通过像下面这样指定代码可以更加紧凑:

'Accept-Encoding: gzip'

答案 2 :(得分:0)

基于你的答案,我已经切换了顺序并删除了上限,因为我认为这更有意义。如果我错了,请纠正我,但它符合我传递的各种价值观。

public function calculateIssuanceFee($volume)
{
    if (isset($this->lower_5) && $volume >= $this->lower_5) {
        return $this->issuanceFee_5;
    }

    if (isset($this->lower_4) && $volume >= $this->lower_4) {
        return $this->issuanceFee_4;
    }

    if (isset($this->lower_3) && $volume >= $this->lower_3) {
        return $this->issuanceFee_3;
    }

    if (isset($this->lower_2) && $volume >= $this->lower_2) {
        return $this->issuanceFee_2;
    }

    if (isset($this->lower_1) && $volume >= $this->lower_1) {
        return $this->issuanceFee_1;
    }
}