如何在我的 php 日历代码中每天显示多个事件

How to show more than one event per day in my php calendar code

提问人:veeger9 提问时间:7/20/2023 最后编辑:DarkBeeveeger9 更新时间:7/25/2023 访问量:75

问:

我的日历写得很好,但是如果我在同一天添加另一个事件,它只会显示数据库中记录的第一个事件。我需要能够在同一天显示多个事件。

我尝试在从数据库中提取信息的代码中使用 for/next 循环和 while 循环。任何一个都不适用于代码的编写方式。此链接将向您显示所写的工作日历: Grims World 博客 这是我的代码:

<?php
$cMonth = isset($_REQUEST["month"]) ? $cMonth = intval($_REQUEST["month"]) : $cMonth = date("m");
$cYear = isset($_REQUEST["year"]) ? $cYear = intval($_REQUEST["year"]) : $cYear = date("Y");
$prev_year = $cYear;
$prev_year2 = $cYear-1;
$next_year = $cYear;
$next_year2 = $cYear+1;
$prev_month = $cMonth-1;
$next_month = $cMonth+1;
 if ($cMonth == 12 ) {
    $next_month = 1;
    $next_year = $next_year2;
 } elseif ($cMonth == 1 ) {
    $prev_month = 12;
    $prev_year = $prev_year2;
}
$short_days = array('1'=>'Sun', '2'=>'Mon', '3'=>'Tue', '4'=>'Wed', '5'=>'Thu', '6'=>'Fri', '7'=>'Sat');
$day=date('d');
$endDate=date('t',mktime(0,0,0,$cMonth,$day,$cYear));
echo "<table width='100%' align='center' border='0' cellpadding='0' cellspacing='5'><tr bgcolor='white'>\n";
echo "<td align='left'><a class='caldate3' href='".$_SERVER['PHP_SELF']."?month=$prev_month&amp;year=$prev_year' title='Previous Month'>&nbsp;<big>&laquo;&laquo;</big>&nbsp;Prev</a></td>\n";
echo "<td align='center'><a class='mcaldate2' href='#' title='Current Month'>&nbsp;".date("F Y",strtotime($cYear."-".$cMonth."-01"))."&nbsp;</a></td>\n";
echo "<td align='right'><a class='caldate3' href='".$_SERVER['PHP_SELF']."?month=$next_month&amp;year=$next_year' title='Next Month'>Next&nbsp;<big>&raquo;&raquo;</big>&nbsp;</a></td></tr>\n";
echo "<tr><td colspan='3' height='5'></td>\n";
echo "</tr></table>\n";
echo "<table width='100%' align='center' border='0' cellpadding='0' cellspacing='0'><tr><td class='norm'>\n";
echo "<table width='100%' align='center' border='0' cellpadding='2' cellspacing='1'><tr bgcolor='#000' height='20'>\n";
    foreach ($short_days as $key=>$val) {
echo "<td width='14%' align='center'><span style='font-size:14px; color:#ffff00;'><b>".$val."</b></span></td>\n"; 
        }
echo "</tr><tr>\n";
$s=date('w', mktime (0,0,0,$cMonth,1,$cYear));
for ($ds=1; $ds<=$s; $ds++) {
echo "<td class='norm' height='20' align='center' valign='middle'></td>\n";
    }
for ($d=1; $d<=$endDate; $d++) {
if (date('w',mktime (0,0,0,$cMonth,$d,$cYear)) == 0) {
    echo "</tr><tr>\n";
    }
$events = mysqli_query($connect, "SELECT * FROM `posts` WHERE SUBSTR(date,7,4)='$cYear' AND month='$cMonth' AND day='$d'");
$rows  = mysqli_fetch_assoc($events);
        $post_id = $rows['id'];
        $post_title = $rows['title'];
        $evday = $rows['day'];
if ($evday) {
echo "<td height='20' class='event' align='center' valign='middle'>\n";
    } elseif ($d == $day && $cMonth == date('m')) {
echo "<td height='20' class='today' align='center' valign='middle'>\n";
    } else {
echo "<td height='20' class='norm' align='center' valign='middle'>\n";
}
if ($d == $day && $cMonth == date('m') && $d <> $evday) {
$d = str_pad($d,2,'0',STR_PAD_LEFT);
echo "<span class='cal2'><a class='cal2' href='#' title='Today'>$d</a></span>\n";
    } elseif ($d == $day && $cMonth == date('m') && $d == $evday) {
$d = str_pad($d,2,'0',STR_PAD_LEFT);
echo "<a class='cal2' href='post.php?id=$post_id' title='Today - $post_title'>$d</a>\n";
    } elseif ($evday) {
$d = str_pad($d,2,'0',STR_PAD_LEFT);
echo "<a class='ecal' href='post.php?id=$post_id' title='$post_title'>$d</a>\n";
    } else {
$d = str_pad($d,2,'0',STR_PAD_LEFT);
echo "<span class='noevt'>$d</span>\n";
    }
echo "</td>\n";
if (date('w',mktime (0,0,0,$cMonth,$d,$cYear)) == 6) {
echo "</tr>";
    }
}
echo "</table></td></tr><tr><td height='8'></td>\n";
echo "</tr></table>\n";
echo "</td></tr></table>\n";
?>
PHP MySQLI

评论

1赞 CBroe 7/20/2023
mysqli_fetch_assoc从结果集中提取行。您只在同一天从多个事件中获取第一个事件,因为您只获取第一个事件。您需要循环查询在该位置返回的所有记录。
0赞 ADyson 7/20/2023
mysqli_fetch_assoc仅返回一行(根据文档)。如果需要多行,请遍历它,直到它返回 null(根据文档中的示例)。php.net/manual/en/mysqli-result.fetch-assoc.php。或者考虑改用mysqli_fetch_all。再。。。文档:php.net/manual/en/mysqli-result.fetch-all.php
0赞 veeger9 7/20/2023
@ADyson在阅读了有关fetch_all的手册后,我想出了这个,需要知道它是否有效以及如何显示结果。$rows = mysqli_fetch_all($events, mysqli_assoc);foreach ($rows$row) { ($post_id => $row['id'], $post_title => $row['title'], $evday => $row['day']);code
0赞 ADyson 7/20/2023
如果你想知道它的作用,为什么不测试它呢?但此代码将遍历查询结果中的所有行。每次循环时,它都会为变量分配一些值,但下次运行时会覆盖它们。因此,如果你想对数据做任何事情,显然需要在循环中发生。或者,在循环之外,您可以通过其属性之一找到特定行,并使用它。取决于上下文是什么。似乎您正在尝试填充日历,因此也许首先您需要确定哪些行出现在哪个日期?

答:

-1赞 Nicholas 7/20/2023 #1

如果 SQL 查询正确并返回有效结果,请使用:$events

while($row = mysqli_fetch_assoc($events))
{
    # output events
    echo '<pre>';
    print_r($row);
    echo '</pre>';
}

根据 php 文档,该函数从结果集中获取一行数据并将其作为关联数组返回。每次后续调用此函数都将返回结果集中的下一行(如果没有更多行,则返回 null),因此我们需要使用循环循环遍历结果集。(虽然有结果......执行此操作)。mysqli_fetch_assocwhile()

为了进一步改进代码,您可以先使用内置函数检查是否有任何结果。如果给定日历日期上没有任何事件,则无需循环遍历结果,因此我们可以跳过该结果。mysqli_num_rows

您的代码可能如下所示:

$sql = "SELECT *
        FROM posts
        WHERE SUBSTR(date,7,4)='$cYear' AND month='$cMonth' AND day='$d'
        ";
$results = mysqli_query($connect, $sql);
if(mysqli_num_rows($results)) // only if there are results
{
    while($row = mysqli_fetch_assoc($results))
    {           
        $post_id = $row['id'];
        $post_title = $row['title'];
        // ...
        
        # output
        echo '<p>'.$post_title.'</p>';
    }
}

注意 - 我已将您的变量更改为 ,只是为了一般最佳实践目的和一致性,但从技术上讲,这不是必需的。$events$results

另外 - 考虑在 SQL(文档)中使用该子句,以便在结果集中按时间顺序对事件进行排序。
另外 - 考虑对 SQL 查询使用预准备语句,这样更安全。
ORDER BY

评论

0赞 Community 7/25/2023
您的答案可以通过其他支持信息进行改进。请编辑以添加更多详细信息,例如引文或文档,以便其他人可以确认您的答案是正确的。您可以在帮助中心找到有关如何写出好答案的更多信息。
0赞 DarkBee 7/25/2023
你为什么不指出代码容易受到SQL注入的攻击,而是直接修复有问题的代码呢?
0赞 Nicholas 7/25/2023
@DarkBee 嗨,我正在回答他的问题,即:如何显示 1 个以上的事件。通过使用循环,可以循环显示结果。当前代码仅获取 1 个事件,我正在解释。你能澄清一下我应该说什么吗?
0赞 DarkBee 7/25/2023
使用预准备语句,而不仅仅是复制易受攻击的 SQL?
0赞 Nicholas 7/25/2023
@DarkBee 它超越了问题。我可以重写整个日历并提出诸如转义和避免 REQUEST 变量之类的事情,但这不是一个安全问题,所以我只是把它作为保持主题的提示。