这是我之前的question的延续。
更新:谢谢Rasclatt的清洁脚本。它整体上比我原来的要好,所以我会改用它。
这就是数据库中的内容,显示了ACOL的记录。使用的查询与我在脚本中使用的查询相同。 ACOL的DATEIN于2015/01/30结束,并于2015/03/04开始
这是输出。橙色时间的行表示TIMEIN,红色表示TIMEOUT(数据库中未显示)。注意ACOL如何在二月份有记录,尽管数据库中没有。
正如您所看到的,正确的现有日期的某些时间与数据库中的那些日期相匹配(第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>
答案 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>";
?>