PHP:嵌套的If条件混淆(显示错误)

PHP:嵌套的If条件混淆(显示错误),php,multidimensional-array,Php,Multidimensional Array,这是我上一篇文章的延续 更新:感谢Rasclatt提供更简洁的脚本。总体而言,它比我原来的版本要好,所以我将改用它 这是数据库中的内容,显示ACOL的记录。使用的查询与我在脚本中使用的查询相同。ACOL的DATEIN于2015年1月30日结束,并于2015年3月4日开始 这是输出。带有橙色时间的行表示TIMEIN,而红色表示超时(未显示在db上)。请注意,ACOL有2月份的记录,尽管数据库中没有记录。 如您所见,正确的现有日期的一些时间与数据库中的时间(第4、17)匹配,但有些时间完全丢失。

这是我上一篇文章的延续

更新:感谢Rasclatt提供更简洁的脚本。总体而言,它比我原来的版本要好,所以我将改用它

这是数据库中的内容,显示ACOL的记录。使用的查询与我在脚本中使用的查询相同。ACOL的DATEIN于2015年1月30日结束,并于2015年3月4日开始

这是输出。带有橙色时间的行表示TIMEIN,而红色表示超时(未显示在db上)。请注意,ACOL有2月份的记录,尽管数据库中没有记录。

如您所见,正确的现有日期的一些时间与数据库中的时间(第4、17)匹配,但有些时间完全丢失。

不存在其他可能导致不准确的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>

名称

我想我可能没有很清楚地表达我的建议。我认为你错的地方是你如何接近这张桌子。因为它主要是一个基于日期的表,所以我认为一开始就按日期重新组织数据数组是一个很好的计划。其次,如果您将脚本分解为单独的函数,您将能够更好地自定义表布局。如果您注意到,我向表中添加了功能,而没有对原始表生成脚本进行大量更改:

创建一些简单的函数(包括在页面顶部):

<?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;
    }
<!-- 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>
看起来没有太大问题(尽管在维护代码时,许多嵌套的ifs会让人头疼,但这不是你的问题)

检查以下各项:

  • 灰色单元格else case在
    中不输出任何内容,这可能是空单元格的原因
  • 设置
    $cond=TRUE
    可能应该设置为比当前位置高一个级别,尽管我怀疑这现在会造成太大的差异
  • 如果数组中工作人员的
    名称
    大小写不正确,则显然必须比较类似于
    strtoupper($value)==strtoupper(…数组…)
    的内容
  • 你的Sun/Sat比较似乎很奇怪;那不是更像是太阳和卫星吗
除此之外,很难说什么是错的。您必须提供完整的数据数组、错误的输出和所需的输出,否则无法看到哪些值导致哪些输出

编辑:通过
print\r
$inidate
分配的初始任务是什么意思?我想你会想要和主循环结束时一样的任务,
strftime
business

毕竟,这是一个过于复杂,因而容易出错的代码的例子。考虑将变量重命名为有意义的,而不是<代码> $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++;
}
$inidate=“$y/$m/01”//$y和$m由用户选择
$count=0;
foreach($key=>$team的staff)//行或使用人员计数
{
$j=0;
回显“.”($count+1)。“$team.”;
对于($i=0;$i标准时间($09:10)))
回声“$dome[$j]['TIMEIN']”;
else//正常输出时间
回声“$dome[$j]['TIMEIN']”;
}
else//如果其工作日输出灰色单元格
回声“$dome[$j]['TIMEIN']”;
}
其他的
回声“AB”;
}
$j++;
}
}
$inidate=strftime(“%Y/%m/%d”,strftime($inidate+1天”);
回声“;
}
$count++;
}
编辑3:好的,代码比我原来想象的更混乱。我将其设为phpFiddle,对于给定的输入,它可以按预期(我想)工作。我不在乎颜色或其他琐碎的变化。此外,我不会指出这些更改,如果您将其与原始代码进行比较,您可以看到它们。你们应该提取方法,正如我之前指出的,以及在另一个答案中所做的。“Extract methods”指的是重构术语(),不是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>";
?>


键3的日期应该是2012年还是2015年?同时,大写的职员和职员是否可以互换(即代表同一实体)?@Rasclatt 2012$dome包含2012年至2015年的所有数据。它低于较新日期的原因是因为SQL中的按名称分组。对于这些情况,我为系统编写了代码,完全忽略了非所有caps用户名,因为我无法找到通过SQL过滤它们的方法。但是在您的示例中,除了2015年1月,您不会显示任何内容(如果点击它,它将跳过)?是的,如果用户选择了2015年1月,它不会显示其他日期的任何出席人数谢谢你的代码,但我很抱歉不够清楚:让我烦恼的是if/else语句。我尝试了很多方法来获得输出,但我根本不知道哪里出了问题。你的代码真的很好,输出也很漂亮,所以请投赞成票。检查我的修改。我已经调整了脚本以适应您在表中的首选项。此外,此注释的一个注释:澄清:问题是我一直得到不匹配的时间和空白单元格,我知道这些单元格由if语句控制。这是100%正确的,您之所以得到这个结果,是因为嵌套条件中有太多的位置,如果不满足某个条件,这些位置将在不构建单元的情况下继续。在我的示例中,
总是构建的,因为它们不是有条件的。罗