PHP的If/ELSE或Switch/Case语句

14

我已经提供了可以是1或0的输入。

$no_required
$on_arrival
$schengen_visa
$uk_visa
$usa_visa
我有下列情况,我想为每种情况向用户显示唯一的消息。
a b c d e
1 0 0 0 0   No Visa Required
0 1 0 0 0   Visa can be obtained on Arrival
0 0 1 0 0   You need Schengen Visa
0 0 0 1 0   You need UK visa
0 0 0 0 1   You need US visa
0 0 1 1 1   You need Either of the Visas
0 0 1 1 0   You need Schengen/UK visa
0 0 1 0 1   You need Schengen/US visa
0 0 0 1 1   You need USA/UK visa

在上述变量A B C D E F中,哪种方式是最佳和最优化的结果显示方式。


你是如何在代码中存储数据的?能否提供一些代码? - Brock Hensley
@dirt,它基本上是来自数据库。 - Harsha M V
3
将这些值作为二进制值相加,然后在加法上运行开关,如果我理解正确,就不可能有两个相同的值。例如,如果a为1,则将其加到变量总数1中;如果b为1,则加2;如果c为1,则加4,然后根据总数的值运行开关。 - Rick Calder
4个回答

17

您展示的条件可以通过位掩码非常好地建模:

$messages = [
    16 => 'No Visa Required',
    8  => 'Visa can be obtained ...',
    4  => ...
];

那么你只需要将单独的变量格式化为位掩码:

$bitmask = ($no_required ? 16 : 0)
         | ($on_arrival  ? 8  : 0)
         | ...;

然后只需选择正确的信息:

echo $messages[$bitmask];
注意:在这里使用常量而不是魔术数字几乎是强制性的,因此它将看起来像这样:
define('VISA_NONE',       1);
define('VISA_ON_ARRIVAL', 2);
...

$messages = [
    VISA_NONE         => 'No Visa Required',
    ...,
    VISA_US | VISA_UK => 'You need USA/UK visa'
];

// using multiplication instead of conditionals, as mentioned in the comments
$bitmask = $no_required * VISA_NONE
         | $on_arrival  * VISA_ON_ARRIVAL
         | ...;

echo $messages[$bitmask];
将整个内容放入适当的类中,就可以得到一个漂亮、易读、易维护、可重用的业务逻辑部分:
class Visa {

    const NONE       = 1;
    const ON_ARRIVAL = 2;
    ...

    protected $messages = [];

    protected $visa;

    public function __construct() {
        $this->messages = [
            static::NONE            => 'No Visa Required',
            ...,
            static::US | static::UK => 'You need USA/UK visa'
        ];
    }

    /**
     * @param int  $type    One of the class constants.
     * @param bool $enabled Whether this type of visa is required.
     */
    public function set($type, $enabled) {
        $this->visa = $this->visa | $type * (int)(bool)$enabled;
    }

    public function getMessage() {
        return $this->messages[$this->visa];
    }

}


$visa = new Visa;
$visa->set($visa::NONE,       $no_required);
$visa->set($visa::ON_ARRIVAL, $on_arrival);

echo $visa->getMessage();

如果这些值只是0或1,难道你不可以通过每次乘以2的幂次方来代替条件判断吗? - Novak
这被称为过度工程 :) - Engineer
我会使用 map,而不是 switch/case 或 if/else ;) - Engineer
@deceze,您在谈论可维护性,如果变量可以具有除“0”和“1”之外的其他值呢?我是否应该重构所有逻辑?)) - Engineer
@工程师 变量表示布尔值,是或否,一个真值表。如果它们将来会持有完全不同的值,那么这里的任何解决方案都需要更改。 - deceze
显示剩余5条评论

11
<?php
$messages = array('10000' => 'No Visa Required', '01000' => 'Visa can be obtained on Arrival');
$no_required = '0';
$on_arrival = '1';
$schengen_visa = '0';
$uk_visa = '0';
$usa_visa = '0';

$result = "$no_required$on_arrival$schengen_visa$uk_visa$usa_visa";
if(array_key_exists($result, $messages)){
 echo $messages[$result]; //Visa can be obtained on Arrival
}

?>

5

我认为使用switch语句是个不错的选择:

$val=$no_required.$on_arrival.$schengen_visa.$uk_visa.$usa_visa;

switch($val)
{
    case "10000":
        echo "No Visa Required";
        break;
    case "01000"   
        echo "Visa can be obtained on Arrival.";
        break;
    case "00100":
        echo "You need Schengen Visa";
        break;
         .
         .   //Continue to add cases .
}

3

一个小技巧:

为什么不先将所有二进制数转换为整数值,然后再通过switch语句传递它们?

<?php

    $integer_value = convert_binary_to_integer(a,b,c,d,e);

    // I'm not sure PHP provdies a function to convert binary numbers to integers number:
    // But you can write it yourself. It's pretty easy

    switch($integer_value) {
        case 16: // As the first combination of a,b,c,d,e corresponds to number 16 
             // do the appropriate action
        break;
            // ... and so on
    }
?>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接