我刚刚写了一个糟糕的PHP函数,我需要一些帮助(elseif-chain-switch?)

我刚刚写了一个糟糕的PHP函数,我需要一些帮助(elseif-chain-switch?),php,optimization,Php,Optimization,我正在制作一个站点,它根据时间来确定数组的值。我写了这个糟糕的(功能性)脚本,我想知道我是否可以让它更简洁。我从case/switch语句开始,但在使用多个条件时遇到了问题。下面是肮脏的行为: if ($now < november 18th) { $array_to_use = $home; } elseif (november 18th < $now && $now < november 21st ) { $array_to_use = $d

我正在制作一个站点,它根据时间来确定数组的值。我写了这个糟糕的(功能性)脚本,我想知道我是否可以让它更简洁。我从case/switch语句开始,但在使用多个条件时遇到了问题。下面是肮脏的行为:

if ($now < november 18th) {
    $array_to_use = $home;
}
elseif (november 18th < $now && $now < november 21st ) {
    $array_to_use = $driving;
}
elseif (november 21st < $now && $now < november 22nd) {
    $array_to_use = $flying;
}
...
...
...
elseif (february 1st < $now) {
    $array_to_use = $arrived;
}
else {
    $array_to_use = $default;
}
if($now<11月18日){
$array\u to\u use=$home;
}
elseif(11月18日<现在$和现在<11月21日){
$array_to_use=$driving;
}
elseif(11月21日<$now&$now<11月22日){
$array_to_use=$flying;
}
...
...
...
埃尔塞夫(2月1日<$now){
$array_to_use=$array;
}
否则{
$array\u to\u use=$default;
}
该计划实际上更复杂,其中包含13条
elseif
语句。有人能确认我刚刚有了编码块,还有更好的方法吗

编辑:我将Unix时间戳更改为粗略实时,以便更容易理解我在做什么(希望如此)

编辑2:请原谅当前坏掉的Javascript时钟,但这是我正在处理的网站:


每个阵列都基于我的位置,根据时间有15个“它们当前在”。这是一个小问题领域,有已知的开始/结束时间,所以灵活性不是关键,只是把它全部写下来。您可以看到时间是如何连续的,一次只需要选择一个字符串数组。

您可以使用switch语句执行以下操作:

switch (true)
{
    case $now < 1258783201:
        // your stuff
        break;
    case $now < 1258783201
        // more of your stuff
        break;
    //...
}
$array_to_use = null;
$dispatch = array(1258783201, $home, 1258956001, $driving, ..., $arrived);
for ($i=0; i<count($dispatch); $i+=2) {
    if ($now<$dispatch[$i]) {
        $array_to_use = $dispatch[$i+1];
        break;
    }
}
if ($array_to_use==null) $array_to_use = $dispatch[count($dispatch)-1];
开关(真)
{
案例$now<1258783201:
//你的东西
打破
案例$now<1258783201
//更多你的东西
打破
//...
}

这至少有点干净…

首先,请取出您的硬编码数字,并将它们放入常量中

$FLIGHT_START_TIME = 1258956001;
$FLIGHT_END_TIME   = 1260511201;
其次,我将为每个条件生成迷你函数:

最后,用单个函数调用替换整个内联代码部分:

$currentState = getStateArrayForTime($now);
正如其他海报所评论的,如果您知道只有开始和结束时间是状态参数,那么此时您可以使用数据表驱动函数返回状态:

因此,将getStateArrayForTime的实现替换为:

function getStateArrayForTime ($time)
{
// 
$states = array (
    array("startTime" => 1258956001, "endTime" => 1260511201, "state" => $flying),
    array("startTime" => 1260511201, "endTime" => 1260517000, "state" => $driving),
..etc...
);
    foreach($states as $checkStateArray)
    {
        if($checkStateArray['startTime'] < $time && $time < $checkStateArray['endTime'])
        {
            return $checkStateArray['state'];
        }
    }
    return null;
}
函数getStateArrayForTime($time) { // $states=数组( 数组(“开始时间”=>1258956001,“结束时间”=>1260511201,“状态”=>$flying), 数组(“开始时间”=>1260511201,“结束时间”=>1260517000,“状态”=>$driving), 等 ); foreach($状态为$checkStateArray) { 如果($checkStateArray['startTime']<$time&$time<$checkStateArray['endTime'])) { 返回$checkStateArray['state']; } } 返回null; } 最后,有些人可能会问“为什么要按这种顺序做事?”除了在应用程序中,我一点也不相信,但Martin Fowler有一本叫做“重构”的好书,解释了为什么要一步一步地清理代码,并在每一步进行测试,然后最终彻底替换没有意义的函数,一直在测试它们的功能是否相同。

类似这样的内容:

switch (true)
{
    case $now < 1258783201:
        // your stuff
        break;
    case $now < 1258783201
        // more of your stuff
        break;
    //...
}
$array_to_use = null;
$dispatch = array(1258783201, $home, 1258956001, $driving, ..., $arrived);
for ($i=0; i<count($dispatch); $i+=2) {
    if ($now<$dispatch[$i]) {
        $array_to_use = $dispatch[$i+1];
        break;
    }
}
if ($array_to_use==null) $array_to_use = $dispatch[count($dispatch)-1];
$array\u to\u use=null;
$dispatch=array(1258783201,$home,1258956001,$driving,$array);

对于($i=0;i这可能有些过分,但我会这样做,以便将所有时间范围放在一个清晰的位置:

@timeWindows = ({ start -> 0, end -> 1258783201, array -> $home },
                ... ,
                {start -> 1260511201, end -> MAXVAL, array -> $arrived});
然后是一个像

$array_to_use = $default;

foreach (my $window in @timeWindows) {
   if (($now > $window->start) && ($now < $window->end)) {
       $array_to_use = $window->array;
       last;
   }
}
$array\u to\u use=$default;
foreach(我在@timeWindows中的$window){
如果($now>$window->start)和($now<$window->end)){
$array\u to\u use=$window->array;
最后;
}
}

很抱歉,它是用Perl编写的,我不懂PHP,但我想它是类似的。

您可以将要使用的时间和数组放在一个数组中,并循环选择它们

$Selctions = array(
    1258783201 => $Home,
    1258956001 => $Driving,
    1260511201 => $Flying,
    ...
    1260511201 => $Arriving
);

// MUST SORT so that the checking will not skip
ksort($Selction);
$TimeToUse = -1;
$Now       = ...;
foreach ($Selctions as $Time => $Array) {
    if ($Now < $Time) {
        $TimeToUse = $Time;
        break;
    }
}
$ArrayToUse = ($TimeToUse != -1) ? $Selctions[$TimeToUse] : $Default;
$selections=array(
1258783201=>$Home,
1258956001=>$Driving,
1260511201=>$Flying,
...
1260511201=>$
);
//必须进行排序,以便检查不会跳过
ksort($选择);
$TimeToUse=-1;
$Now=。。。;
foreach($Time=>$Array的选择){
如果($Now<$Time){
$TimeToUse=$Time;
打破
}
}
$ArrayToUse=($TimeToUse!=-1)?$SELECTIONS[$TimeToUse]:$Default;
此方法只能在时间没有间隔(一个范围紧接着一个范围)时使用


希望这有帮助。

您可能想学习命令模式;它在这种情况下也有帮助。

您选择的时间戳有数学吗?有数学,是的。$现在被除数和取整几次有多少个条件?它们是重叠的,还是每个条件都是独占的?其他时间戳呢,这些模式有什么逻辑吗?Ma在接下来的3个月中,共有13个“区块”对于连续时间,一次只有一个是真的,因此一次只拾取一个数组值。我提到的数学是无关的,但只意味着我更喜欢将所有内容都保留在Unix时间内。这是一个很好的建议。冗长,但干净。我是个黑客。谢谢!问题是,如果你再得到200个状态,你就有200个函数了(他已经有13个了)。增加更多的州不应该增加代码,只是增加一些(最好是外部的)数据块。您还可以使$FLIGHT\u START\u TIME=1258956001;$FLIGHT\u END\u TIME=1260511201;动态,如果您也需要这种灵活性,而不是硬编码这些日期/时间。如果状态实际上只是一个时间驱动的数据表,则可以使用数据表根据时间范围执行单个函数来查找状态。然而,仅看到一小部分情况,不知道其他条件是否会影响状态,我更愿意将每个状态的灵活性定义为一个函数。Poster已经澄清。它是/应该是表驱动的。答案经过适当修改。这是最佳答案,因为它允许确定时间边界从语法上讲,不清楚是什么意思