23、打造自己的待办事项列表应用

打造自己的待办事项列表应用

1. 显示数据库内容

首先,有一段原始的 HTML 代码,添加了一个 mysqli 连接对象:

<h1>Pi Todo List App</h1>
<?php
$mysqli = new mysqli('localhost', 'pi', 'raspberry', 'pi');
if ($mysqli->connect_error) {
    die('Connect Error (' . $mysqli->connect_errno . ') '
         . $mysqli->connect_error);
}
$mysqli->close();
?>
</body>
</html>

若没有错误,这段代码不会有太多显示。接下来,需要添加代码来显示待办事项列表。分为两部分:表格块和表头。以下是基本的 HTML 表格布局:

<table>
<tr>
<th>Description</th>
<th>Owner</th>
<th>Due Date</th>
<th>Location</th>
<th>Importance</th>
<th>Creator</th>
</tr>
...
</table>

此代码设置了表格及其第一行,均标记为表头元素。再添加 PHP 代码来显示 MySQL 表中的所有内容:

<?php
$result = $mysqli->query("SELECT * FROM todolist");
while($row = $result->fetch_assoc()){
    print "<tr>";
    print "<td>".$row["description"]."</td>";
    print "<td>".$row["owner"]."</td>";
    print "<td>".$row["date"]."</td>";
    print "<td>".$row["location"]."</td>";
    print "<td>".$row["importance"]."</td>";
    print "<td>".$row["creator"]."</td>";
    print "</tr>";
}
?>

PHP 部分的工作流程如下:
1. 创建一个新变量 $result ,它包含执行 mysqli 查询的输出,查询语句是 SELECT * FROM todolist
2. 在 while 循环中,通过 $result->fetch_assoc() 调用将结果的每一行逐一传递出来,并赋值给 row 变量。
3. 对于每一行,打印请求的每个字段的行值。

需要将上述代码添加回原始代码块,同时将 $mysqli->close(); 移到新块的底部,即在 PHP 段结束之前:

<body>
<h1>Pi Todo List App</h1>
<?php
$mysqli = new mysqli('localhost', 'pi', 'raspberry', 'pi');
if ($mysqli->connect_error) {
    die('Connect Error (' . $mysqli->connect_errno . ') '
         . $mysqli->connect_error);
}
?>
<table>
<tr>
<th>Description</th>
<th>Owner</th>
<th>Due Date</th>
<th>Location</th>
<th>Importance</th>
<th>Creator</th>
</tr>
<?php
$result = $mysqli->query("SELECT * FROM todolist");
while($row = $result->fetch_assoc()){
    print "<tr>";
    print "<td>".$row["description"]."</td>";
    print "<td>".$row["owner"]."</td>";
    print "<td>".$row["date"]."</td>";
    print "<td>".$row["location"]."</td>";
    print "<td>".$row["importance"]."</td>";
    print "<td>".$row["creator"]."</td>";
    print "</tr>";
}
$mysqli->close();
?>
</table>
</body>
</html>
2. 网站数据插入

现在 HTML 和 PHP 协同工作,生成完整页面内容。静态 HTML 提供框架,有两段 PHP 代码,一段用于建立连接,另一段从待办事项列表表中提取结果并添加到页面。基本显示功能正常后,需要添加一个表单来提交新内容。基本表单应包含要插入表中的每个元素的输入流,还需要一个特殊的隐藏元素,用于告诉处理器如何处理数据,这里使用变量 action 并按需赋值,最后需要一个提交元素将数据推送到服务器进行处理。表单代码如下:

...
</table>
<form action="index.php" method="POST">
<input type="hidden" name="action" value="insert" />
Description: <input name="description" /><br/>
Owner: <input name="owner" /><br/>
Date: <input name="date" /><br/>
Location: <input name="location" /><br/>
Importance: <input name="importance" /><br/>
Creator: <input name="creator" /><br/>
<input type="submit" />
</form>
</body>
</html>

此代码块可添加到表格下方,甚至可以用 <hr /> 标签分隔,这样就有一个显示内容的表格和一个添加新内容的区域。

按下提交按钮后,会回到当前页面,URL 会显示相关信息,这是动作块发送 CGI 命令在当前页面运行。因此需要在 PHP 中添加一些 CGI 处理来处理数据。

之前设置了提交方法为 POST ,还有另一种方法是 GET 。两者区别在于, GET 会在网页地址中显示内容数据,而 POST 会隐藏数据。可以将 POST 改为 GET 并按下提交按钮进行验证。

PHP 有特殊变量可自动填充 CGI 请求的数据,可访问的三个特殊变量是 _POST _GET _REQUEST 。处理 CGI 的步骤如下:
1. 检查 action 变量是否设置并包含数据。
2. 若 action 已设置,使用 switch 语句确定要执行的操作。
3. 根据操作类型,拆分输出的其余部分并对数据库执行所需操作。
4. 在主页面加载之前执行这些操作,可自动显示最新数据。

CGI 代码如下:

if(isset($_REQUEST["action"])){
switch($_REQUEST["action"]){
    case "insert":
        $SQL="INSERT INTO todolist (description, owner, date, location, importance, creator) 
VALUES (";
        $SQL=$SQL."'".$_REQUEST["description"]."',";
        $SQL=$SQL."'".$_REQUEST["owner"]."',";
        $SQL=$SQL."'".$_REQUEST["date"]."',";
        $SQL=$SQL."'".$_REQUEST["location"]."',";
        $SQL=$SQL."'".$_REQUEST["importance"]."',";
        $SQL=$SQL."'".$_REQUEST["creator"]."'";
        $SQL=$SQL.");";
if ($mysqli->query($SQL)=== FALSE) {
    printf("Error – Unable to insert data to table " . $mysqli->error);
}
        break;
    case "delete":
        print "Delete function yet to be added!";
        break;
}
}
插入数据库的操作步骤
  1. 创建并构建 SQL 命令,先确定 INSERT 语句的框架、表名和要写入的字段。
  2. 逐个添加变量到语句中,每个变量需用单引号括起来,末尾加逗号。
  3. 例如: $SQL=$SQL."'".$_REQUEST["description"]."',"; ,将当前 SQL 值与新变量组合。
  4. 需注意,上述代码不安全,可使用 mysqli_real_escape_string 函数对变量进行安全检查。
  5. 创建 SQL 变量后,调用 mysqli 查询函数插入数据,并检查查询执行是否失败。
  6. 将此代码块添加到第一个 PHP 块中,页面流程变为:绘制页面标题、创建数据库连接并执行 CGI 操作、显示待办事项列表内容、显示最终表单。

以下是操作流程的 mermaid 流程图:

graph TD;
    A[开始] --> B[创建数据库连接];
    B --> C{检查action变量是否设置};
    C -- 是 --> D{确定action值};
    D -- insert --> E[构建插入SQL语句];
    E --> F[执行插入操作];
    F --> G{插入是否成功};
    G -- 是 --> H[显示最新数据];
    G -- 否 --> I[输出插入错误信息];
    D -- delete --> J[提示删除功能待添加];
    C -- 否 --> H;
    H --> K[结束];
    I --> K;
    J --> K;
3. 删除条目

添加功能正常后,需要创建删除功能。有两种方法:
1. 为每一行添加一个表单和删除选项,需逐个删除。
2. 使用一系列复选框,删除所有勾选的元素,这种方法更灵活。

为实现删除功能,需要进行两项更改:
1. 在表格周围添加一个删除表单,包含隐藏字段 action ,值为 delete ,表单下方有提交按钮,为每个元素添加复选框。
2. 在表格表头行的开头添加一个空元素。

以下是添加复选框后的表单代码:

...
<h1>Pi Todo List App</h1>
<form action="index.php" method="POST">
<input type="hidden" name="action" value="delete" />
<table>
<tr>
<td></td>
...
</tr>
<?php
$result = $mysqli->query("SELECT * FROM todolist");
while($row= $result->fetch_assoc()){
    print "<tr>";
    print "<td><input type='checkbox' name='checkboxes[]' value='".$row["idnumber"]."' /></td>";
    print "<td>".$row["description"]."</td>";
    print "<td>".$row["owner"]."</td>";
    print "<td>".$row["date"]."</td>";
    print "<td>".$row["location"]."</td>";
    print "<td>".$row["importance"]."</td>";
    print "<td>".$row["creator"]."</td>";
    print "</tr>";
}
$mysqli->close();
?>
</table>
<input type="submit"/>
</form>
...
从数据库中删除数据

最后,需要在 case 语句中添加删除处理代码。逻辑与插入语句类似,创建一个 SQL 变量,然后迭代添加要删除的 idnumber 。具体步骤如下:
1. 使用 for 循环遍历 _REQUEST['checkboxes'] 变量的每个元素。
2. 在循环中,每次取出数组的第 $i 个元素,并在末尾添加 or
3. 使用 rtrim 函数去除最后一个 or
4. 执行查询操作并检查是否有错误。

删除处理代码如下:

$SQL="DELETE FROM todolist WHERE";
for($i=0; $i < count($_REQUEST['checkboxes']); $i++){
    $SQL=$SQL . " idnumber=" . $_REQUEST['checkboxes'][$i] . " or";
}
$SQL= rtrim($SQL, "or");
if ($mysqli->query($SQL)== FALSE) {
printf("Error Unable to delete value " . $mysqli->error);
}
4. 故障排除

在开发过程中,可能会遇到一些问题,可按以下方法进行排查:
1. 按顺序进行代码更改,然后重新加载页面。
2. 使用 view source 命令查看 PHP 生成的完整 HTML,检查值是否正确显示。
3. 若无法正常显示,查看错误日志(配置 Apache 时的日志文件),该文件会列出所有 PHP 错误。
4. 确保引号正确开闭,语句末尾有分号,括号正确匹配且无重叠。
5. PHP 和网页开发很多时候需要反复尝试,可使用 print 语句输出变量,诊断 SQL 语句问题。
6. 可直接测试向 SQL 插入和删除值,了解系统运行情况和问题原因。

5. 后续改进方向

目前已开发出一个功能完整的待办事项列表应用,可进行显示、添加和删除条目操作。后续还可以进行以下改进:
- 为每个插入值添加 isset() 检查,确保插入的不是空白值。
- 使用 mysqli_real_escape_string 函数包装插入值,提高待办事项列表的安全性,防止恶意 SQL 查询。

通过以上步骤,你可以打造一个功能丰富且安全的待办事项列表应用。

打造自己的待办事项列表应用

6. 代码结构总结

为了更清晰地理解整个待办事项列表应用的代码结构,我们可以将其主要部分进行总结,如下表所示:
| 功能模块 | 代码位置 | 主要功能 |
| ---- | ---- | ---- |
| 数据库连接 | $mysqli = new mysqli('localhost', 'pi', 'raspberry', 'pi'); | 建立与数据库的连接 |
| 数据显示 | $result = $mysqli->query("SELECT * FROM todolist"); 及后续 while 循环 | 从数据库中查询待办事项数据并显示在 HTML 表格中 |
| 数据插入 | switch 语句中的 case "insert" | 根据表单提交的数据构建插入 SQL 语句并执行插入操作 |
| 数据删除 | switch 语句中的 case "delete" | 根据勾选的复选框构建删除 SQL 语句并执行删除操作 |

7. 详细操作流程梳理

下面我们通过一个更详细的 mermaid 流程图来展示整个应用的操作流程:

graph LR
    classDef startend fill:#F5EBFF,stroke:#BE8FED,stroke-width:2px
    classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px
    classDef decision fill:#FFF6CC,stroke:#FFBC52,stroke-width:2px

    A([开始]):::startend --> B(创建数据库连接):::process
    B --> C{检查是否有 action 请求}:::decision
    C -->|有| D{action 值是什么}:::decision
    D -->|insert| E(构建插入 SQL 语句):::process
    E --> F(执行插入操作):::process
    F --> G{插入是否成功}:::decision
    G -->|是| I(查询并显示待办事项列表):::process
    G -->|否| H(输出插入错误信息):::process
    D -->|delete| J(构建删除 SQL 语句):::process
    J --> K(执行删除操作):::process
    K --> L{删除是否成功}:::decision
    L -->|是| I
    L -->|否| M(输出删除错误信息):::process
    C -->|无| I
    H --> N(结束):::startend
    M --> N
    I --> O(显示插入新事项表单):::process
    O --> P(等待用户操作):::process
    P -->|提交插入表单| C
    P -->|提交删除表单| C
    P -->|无操作| Q(页面保持显示):::process
    Q --> P
8. 安全性深入分析

在前面提到了使用 mysqli_real_escape_string 函数来提高应用的安全性,下面我们详细说明如何使用该函数。

插入数据时的安全性改进

在插入数据时,对用户输入的数据进行转义处理,示例代码如下:

if(isset($_REQUEST["action"])){
    switch($_REQUEST["action"]){
        case "insert":
            $description = mysqli_real_escape_string($mysqli, $_REQUEST["description"]);
            $owner = mysqli_real_escape_string($mysqli, $_REQUEST["owner"]);
            $date = mysqli_real_escape_string($mysqli, $_REQUEST["date"]);
            $location = mysqli_real_escape_string($mysqli, $_REQUEST["location"]);
            $importance = mysqli_real_escape_string($mysqli, $_REQUEST["importance"]);
            $creator = mysqli_real_escape_string($mysqli, $_REQUEST["creator"]);

            $SQL="INSERT INTO todolist (description, owner, date, location, importance, creator) 
            VALUES ('$description', '$owner', '$date', '$location', '$importance', '$creator');";
            if ($mysqli->query($SQL)=== FALSE) {
                printf("Error – Unable to insert data to table " . $mysqli->error);
            }
            break;
        case "delete":
            print "Delete function yet to be added!";
            break;
    }
}

检查插入值是否为空

为了避免插入空白数据,在插入操作前添加 isset() 检查,代码如下:

if(isset($_REQUEST["action"])){
    switch($_REQUEST["action"]){
        case "insert":
            if(isset($_REQUEST["description"]) && !empty($_REQUEST["description"]) &&
               isset($_REQUEST["owner"]) && !empty($_REQUEST["owner"]) &&
               isset($_REQUEST["date"]) && !empty($_REQUEST["date"]) &&
               isset($_REQUEST["location"]) && !empty($_REQUEST["location"]) &&
               isset($_REQUEST["importance"]) && !empty($_REQUEST["importance"]) &&
               isset($_REQUEST["creator"]) && !empty($_REQUEST["creator"])) {

                $description = mysqli_real_escape_string($mysqli, $_REQUEST["description"]);
                $owner = mysqli_real_escape_string($mysqli, $_REQUEST["owner"]);
                $date = mysqli_real_escape_string($mysqli, $_REQUEST["date"]);
                $location = mysqli_real_escape_string($mysqli, $_REQUEST["location"]);
                $importance = mysqli_real_escape_string($mysqli, $_REQUEST["importance"]);
                $creator = mysqli_real_escape_string($mysqli, $_REQUEST["creator"]);

                $SQL="INSERT INTO todolist (description, owner, date, location, importance, creator) 
                VALUES ('$description', '$owner', '$date', '$location', '$importance', '$creator');";
                if ($mysqli->query($SQL)=== FALSE) {
                    printf("Error – Unable to insert data to table " . $mysqli->error);
                }
            } else {
                printf("Error – Please fill in all fields.");
            }
            break;
        case "delete":
            print "Delete function yet to be added!";
            break;
    }
}
9. 性能优化建议

除了安全性,性能也是一个重要的方面。以下是一些性能优化的建议:
- 数据库索引 :在 todolist 表的常用查询字段(如 idnumber date 等)上创建索引,可以加快查询速度。例如,在 MySQL 中可以使用以下语句创建索引:

CREATE INDEX idx_idnumber ON todolist (idnumber);
CREATE INDEX idx_date ON todolist (date);
  • 分页显示 :如果待办事项列表数据量较大,可采用分页显示的方式,减少一次性查询和显示的数据量。可以通过修改 SQL 查询语句,使用 LIMIT OFFSET 关键字实现分页,示例代码如下:
$page = isset($_GET['page']) ? (int)$_GET['page'] : 1;
$limit = 10; // 每页显示 10 条记录
$offset = ($page - 1) * $limit;

$result = $mysqli->query("SELECT * FROM todolist LIMIT $offset, $limit");
while($row = $result->fetch_assoc()){
    // 显示数据
}
10. 总结

通过以上步骤,我们成功打造了一个功能丰富的待办事项列表应用,包括数据的显示、插入和删除功能。同时,我们还对应用的安全性和性能进行了深入分析,并给出了相应的改进建议。在实际开发中,我们可以根据具体需求进一步扩展和优化这个应用,例如添加更多的字段、实现排序功能、优化用户界面等。希望本文能对你开发类似的应用有所帮助。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值