PHP:嵌套的If条件混淆(显示错误)
这是我上一篇文章的延续 更新:感谢Rasclatt提供更简洁的脚本。总体而言,它比我原来的版本要好,所以我将改用它 这是数据库中的内容,显示ACOL的记录。使用的查询与我在脚本中使用的查询相同。ACOL的DATEIN于2015年1月30日结束,并于2015年3月4日开始PHP:嵌套的If条件混淆(显示错误),php,multidimensional-array,Php,Multidimensional Array,这是我上一篇文章的延续 更新:感谢Rasclatt提供更简洁的脚本。总体而言,它比我原来的版本要好,所以我将改用它 这是数据库中的内容,显示ACOL的记录。使用的查询与我在脚本中使用的查询相同。ACOL的DATEIN于2015年1月30日结束,并于2015年3月4日开始 这是输出。带有橙色时间的行表示TIMEIN,而红色表示超时(未显示在db上)。请注意,ACOL有2月份的记录,尽管数据库中没有记录。 如您所见,正确的现有日期的一些时间与数据库中的时间(第4、17)匹配,但有些时间完全丢失。
这是输出。带有橙色时间的行表示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%正确的,您之所以得到这个结果,是因为嵌套条件中有太多的位置,如果不满足某个条件,这些位置将在不构建单元的情况下继续。在我的示例中,
总是构建的,因为它们不是有条件的。罗