PHP:嵌套如果条件混乱(显示错误)

时间:2015-07-28 02:37:55

标签: php multidimensional-array

这是我之前的question的延续。

更新:谢谢Rasclatt的清洁脚本。它整体上比我原来的要好,所以我会改用它。

这就是数据库中的内容,显示了ACOL的记录。使用的查询与我在脚本中使用的查询相同。 ACOL的DATEIN于2015/01/30结束,并于2015/03/04开始
what's in db

这是输出。橙色时间的行表示TIMEIN,红色表示TIMEOUT(数据库中未显示)。注意ACOL如何在二月份有记录,尽管数据库中没有。
the output

正如您所看到的,正确的现有日期的某些时间与数据库中的那些日期相匹配(第4,17),但有些时间完全缺失。
ACOL's march records

不存在可能导致不准确的其他ACOL实例。我已经查询过TIMEIN / OUT对是否与其他人匹配但是没有结果。我不知道时间从何而来。

脚本

<?php
function is_weekend($date = false)
    {
        return (date("D",strtotime($date)) == 'Sun' || date("D",strtotime($date)) == 'Sat')? true : false;
    }
// Make a function for on time, makes that part changeable
// gives the ability to change start times ($default) in the future
function on_time($timein = false, $default = '09:30')
    {
        if($timein == false)
            return true;

        return (strtotime($timein) > strtotime($default))? false : true;
    }

function early($timeout = false, $default = '18:00')
    {
        if($timeout == false)
            return true;

        return (strtotime($timeout) < strtotime($default))? false : true;
    }   

$staff = $dome = array();

while($row = ibase_fetch_assoc($result))
{   $dome[] = $row; }

foreach($dome as &$value)
    if (ctype_upper(substr($value['NAME'],0,2))== TRUE)
        $staff[] = $value['NAME'];
$staff = array_values(array_unique($staff,SORT_REGULAR));

$m = $_POST['month'];
$y = $_POST['year'];

//reorganize the array by day
foreach($dome as $user) {
        if(!preg_match('/^'.$y.'\/'.$m.'/',$user['DATEIN']))
            continue;

        $new[ltrim(substr($user['DATEIN'],-2),"0")][strtolower($user['NAME'])][] =   $user['TIMEIN'];
        $newto[ltrim(substr($user['DATEIN'],-2),"0")][strtolower($user['NAME'])][] =   $user['TIMEOUT'];
    } 

if ($m != '' || $y != '')
    echo "<br><u>Attendance for ".date("F", mktime(null, null, null, $m, 1)).", ".$y."</u>";
else
    break;
?>

<table id="caltable" cellpadding="0" cellspacing="0" border="0">
    <tr>
        <td>
            NAME
        </td>
<?php
// Set header row
$day_in_mo  =   cal_days_in_month(CAL_GREGORIAN,$m,$y);
for($i = 1; $i <= $day_in_mo; $i++) { ?>
        <td><?php echo $i; ?></td>
        <?php
    } ?>
    </tr>
<?php
// Loop through staff
foreach($staff as $name) { ?>
    <tr>
        <td rowspan=2><?php echo $name; ?></td>
        <?php
        $keyname    =   strtolower($name);
        for($i = 1; $i <= $day_in_mo; $i++) {
                $timein =   (!empty($new[$i][$keyname][0]))? $new[$i][$keyname][0] : false;?>

        <td class="<?php if(!is_weekend("{$y}-{$m}-{$i}")) { echo 'weekday'; if(!on_time($timein)) echo ' late'; echo '"'; } else echo 'weekend' ?>"><?php
                // Match keys and see if user is listed in that day
                echo ($timein != false)? $timein : '<div class="absent">-</div>'; ?></td>
        <?php
            } ?>
    </tr>
    <tr>
        <td style="display:none"></td>
        <?php
        $keyname    =   strtolower($name);
        for($i = 1; $i <= $day_in_mo; $i++) {
                $timeout = (!empty($newto[$i][$keyname][0]))? $newto[$i][$keyname][0] : false; ?>

        <td class="<?php if(!is_weekend("{$y}-{$m}-{$i}")) { echo 'weekday'; if(!early($timeout)) echo ' early'; echo '"'; } else echo 'weekend' ?>"><?php
                echo ($timeout != false)? $timeout : '<div class="absent">-</div>'; ?></td>
        <?php
            } ?>
    </tr>
    <?php
} ?>

</table>

2 个答案:

答案 0 :(得分:1)

我想也许我对自己的建议并不十分清楚。我认为你出错的地方就是你如何接近这张桌子。因为它主要是一个基于日期的表,我认为从一开始就按日期重新组织数据数组是一个很好的计划。其次,如果您通过独立函数分解脚本,您将能够更好地自定义表格布局。如果您注意到,我在没有大量更改原始表生成脚本的情况下向表中添加了功能:

创建一些简单的功能(包含在页面顶部):

<?php
// Make a function for the weekend to isolate that condition
// makes it much cleaner
function is_weekend($date = false)
    {
        return (date("D",strtotime($date)) == 'Sun' || date("D",strtotime($date)) == 'Sat')? true : false;
    }
// Make a function for on time, makes that part changeable
// by giving you the ability to change start times ($default) in the future
function on_time($timein = false, $default = '09:10')
    {
        if($timein == false)
            return true;

        return (strtotime($timein) > strtotime($default))? false : true;
    }

根据您的首选项更改外观的CSS:

<!-- Just some quick styling -->
<style>
#caltable td    {
    width: 50px;
    padding: 5px;
    font-family: Arial, Helvetica, sans-serif;
    font-size: 13px;
    text-align: center;
    border-bottom: 1px solid #CCC;
}
#caltable td:first-child    {
    width: 150px;   
}
.weekend    {
    background-color: #FFFF00;
}
.late   {
    background-color: orange;
    color: #FFF;
}
.weekday    {
    background-color: #EBEBEB;
}
.absent {
    color: #888;
    font-weight: bold;
}
</style>

脚本算法:

$y  =   '2015';
$m  =   '01';

// I think it's important to reorganize the array by day
foreach($dome as $user) {
        if(!preg_match('/^'.$y.'\/'.$m.'/',$user['DATEIN']))
            continue;

        $new[ltrim(substr($user['DATEIN'],-2),"0")][strtolower($user['NAME'])][] =   $user['TIMEIN'];
    } ?>


<table id="caltable" cellpadding="0" cellspacing="0" border="0">
    <tr>
        <td>
            NAME
        </td>
<?php
// Set header row
$day_in_mo  =   cal_days_in_month(CAL_GREGORIAN,$m,$y);
for($i = 1; $i <= $day_in_mo; $i++) { ?>
        <td><?php echo $i; ?></td>
        <?php
    } ?>
    </tr>
<?php
// Loop through staff
foreach($staff as $name) { ?>
    <tr>
        <td><?php echo $name; ?></td>
        <?php
        $keyname    =   strtolower($name);
        for($i = 1; $i <= $day_in_mo; $i++) {
                $timein =   (!empty($new[$i][$keyname][0]))? $new[$i][$keyname][0] : false; ?>

        <td class="<?php if(is_weekend("{$y}-{$m}-{$i}")) { echo 'weekend'; if(!on_time($timein)) echo ' late'; echo '"'; } else echo 'weekday' ?>"><?php
                // Match keys and see if user is listed in that day
                echo ($timein != false)? $timein : '<div class="absent">-</div>'; ?></td>
        <?php
            } ?>
    </tr>
    <?php
    } ?>
</table>

答案 1 :(得分:1)

看起来不太错误(尽管许多嵌套ifs在保持代码时会保证头痛,但这不是你的问题。)

检查这些:

  • 灰色单元格其他情况在<td>中不输出任何内容,这可能会占空单元格。
  • 设置$cond = TRUE应该设置在当前位置之上一级,但我怀疑现在会产生太多差异。
  • 如果数组中的NAME工作人员的情况不正确,您显然必须比较strtoupper($value) == strtoupper(...array...)之类的内容。
  • 你的太阳/周六比较似乎很奇怪;会不会更像== 'Sun'== 'Sat'

除此之外,很难说出可能出现的问题。您必须提供完整的数据数组,错误的输出和所需的输出,否则无法确定哪些值会导致哪个输出。

编辑:$inidate通过print_r的初始分配是什么意思?我想您希望在主循环结束时使用strftime业务进行相同的分配?

毕竟,这是一个过于复杂且容易出错的代码的例子。考虑将变量重命名为有意义的内容,而不是$value,并提取方法而不是嵌套太深。

编辑2:也许我没有说清楚。这是我的建议之后的代码。输出现在好些了吗?

$inidate = "$y/$m/01"; //$y and $m chosen by user
$count=0; 
foreach ($staff as $key => $team) //row or use count on staff
{
    $j=0;
    echo "<tr><td>".($count+1).".</td><td>".$team."</td>";
    for ($i=0;$i<cal_days_in_month(CAL_GREGORIAN,$m,$y);$i++) //column
    {
        $cond = FALSE;
        while (($dome[$j]['DATEIN'] != "") && ($cond == FALSE))
        {
            if ($dome[$j]['DATEIN'] == $inidate)
            {
                if (strtoupper($team) == strtoupper($dome[$j]['NAME']))
                {
                    if ($dome[$j]['TIMEIN'] != "")
                    {
                        $cond = TRUE;
                        if (date("D",strtotime($getdate)) == 'Sun' || date("D",strtotime($getdate)) == 'Sat')
                        {   
                            //if late output time in yellow cell
                            if (strtotime($dome[$j]['TIMEIN']) > strtotime('09:10'))
                                echo "<td BGCOLOR='#ffff00'>".$dome[$j]['TIMEIN']."</td>";
                            else //output time normally
                                echo "<td>".$dome[$j]['TIMEIN']."</td>";
                        }
                        else //if its weekday outputs gray cell
                            echo "<td BGCOLOR='#525266'>".$dome[$j]['TIMEIN']."</td>";
                    }
                    else
                        echo "<td>AB</td>";
                }
            $j++;
            }
        }
        $inidate = strftime("%Y/%m/%d", strtotime("$inidate +1 day"));
        echo "</tr>";
    }
    $count++;
}

编辑3:好的,代码比我原先想象的更加混乱。我PhpFiddled它,这对于给定的输入按预期工作(我想)。我不关心着色或其他微不足道的变化。此外,我不会指出更改,如果您将其与原始代码进行比较,则可以看到它们。你应该提取方法,正如我之前指出的那样,并且正如在另一个答案中所做的那样。 “提取方法”是指重构术语(http://refactoring.com/catalog/extractMethod.html),而不是PHP函数。

<?php
$month = "01";
$year = "2015";

$staff=array('STAFF A-Full Name',
             'STAFF B-Full Name',
             'STAFF C-Full Name');

$dome[]=array('NAME' => 'STAFF A-Full Name',
              'DATEIN' => '2015/01/01' ,
              'TIMEIN' => '09:02');
$dome[]=array('NAME' => 'STAFF A-Full Name',
              'DATEIN' => '2015/01/02',
              'TIMEIN' => '08:30');
$dome[]=array('NAME' => 'STAFF B-Full Name',
              'DATEIN' => '2015/01/01',
              'TIMEIN' => '08:43');
$dome[]=array('NAME' => 'Staff B-Full Name',
              'DATEIN' => '2015/01/03',
              'TIMEIN' => '09:11');

echo "<table>";
$countTeam = 0;
foreach ($staff as $key => $team) //row or use count on staff
{
    $inidate = "$year/$month/01"; //$year and $month chosen by user

    echo "<tr><td>".($countTeam + 1).".</td><td>".$team."</td>";
    for ($i = 0; $i < cal_days_in_month(CAL_GREGORIAN, $month, $year); $i++) //column
    {
        $found = false;

        foreach($dome as $domeKey => $staffAssignment){
            if($found){
                break;
            }

            if ($staffAssignment['DATEIN'] == $inidate)
            {
                if (strtoupper($team) == strtoupper($staffAssignment['NAME']))
                {
                    if ($staffAssignment['TIMEIN'] != "")
                    {
                        $found = true;
                        if (date("D", strtotime($inidate)) == 'Sun' || date("D", strtotime($inidate)) == 'Sat')
                        {   
                            //if late output time in yellow cell
                            if (strtotime($staffAssignment['TIMEIN']) > strtotime('09:10')){
                                echo "<td BGCOLOR='#ffff00'>".$staffAssignment['TIMEIN']."</td>";
                            }
                            else { //output time normally
                                echo "<td>".$staffAssignment['TIMEIN']."</td>";
                            }
                        }
                        else { //if its weekday outputs gray cell
                            echo "<td BGCOLOR='#525266'>".$staffAssignment['TIMEIN']."</td>";
                        }
                    }
                    else {
                        echo "<td>AB</td>";
                    }
                }
            }
        }

        if(!$found){
            echo "<td></td>";
        }       

        $inidate = strftime("%Y/%m/%d", strtotime("$inidate +1 day"));
    }

    $countTeam++;
    echo "</tr>";
}
echo "</table>";
?>