web应用中使用PHP

尽管本章的主要目的是向你介绍 PHP 的基础知识,但以参考手册的方式进行介绍并不有趣,如果我们把官方文档中的内容复制粘贴下来,你还不如自己去那里阅读。考虑到本书的主要目的和你使用 PHP 编写 Web 应用程序的主要目标,让我们在你感到厌倦之前,向你展示如何尽快应用所学的一切知识。

为此,我们将开始建立网上书店的旅程。刚开始的时候,你可能看不到它的用处,但这只是因为我们还没有展示 PHP 的所有功能。

从用户处获取信息

让我们先创建一个主页。在这个页面中,我们要弄清楚用户是在找书还是只是路过。我们怎么才能知道呢?现在最简单的方法就是检查用户访问应用程序时使用的 URL,然后从中提取一些信息。

将这些内容保存为 index.php

<?php
$looking = isset($_GET['title']) || isset($_GET['author']);
?>
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Bookstore</title>
    </head>
    <body>
        <p>You lookin'? <?php echo (int) $looking; ?></p>
        <p>The book you are looking for is</p>
        <ul>
            <li><b>Title</b>: <?php echo $_GET['title']; ?></li>
            <li><b>Author</b>: <?php echo $_GET['author']; ?></li>
        </ul>
    </body>
</html>

现在访问链接 http://localhost:8000/?author=HarperLee&title=To%20Kill%20a%20Mockingbird 。您将看到该页面打印了您传递给 URL 的一些信息。

对于每个请求,PHP 会将来自查询字符串的所有参数存储在一个名为 $_GET 的数组中。数组中的每个键都是参数的名称,其关联值就是参数的值。因此,$_GET 包含两个条目:$_GET['author'] 包含 Harper Lee,$_GET['title'] 的值为 To Kill a Mockingbird。

在第一个突出显示的行中,我们为变量 $looking 赋值一个布尔值。如果 $_GET['title']$_GET['author'] 存在,则该变量为 true,否则为 false。之后,我们关闭了 PHP 标记,然后打印了一些 HTML,但正如你所看到的,我们实际上是将 HTML 与一些 PHP 代码混合在了一起。

另一个有趣的地方是第二行。在打印 $looking 的内容之前,我们对该值进行了转换。转换是指强迫 PHP 将一种类型的值转换为另一种类型的值。将布尔值转换为整数意味着,如果布尔值为真,结果值将为 1;如果布尔值为 false,结果值将为 0。由于 $_GET 包含有效的键,所以 $looking 为真,页面显示为 "1"。

如果我们尝试在不发送任何信息的情况下访问同一页面(如 http:// localhost:8000),浏览器会提示 您在找一本书吗? 根据 PHP 配置的设置,您会看到两条通知消息,抱怨您试图访问不存在的数组键。

类型转换与类型杂耍

我们已经知道,当 PHP 需要一个特定类型的变量时,它会尝试转换它,这就是所谓的 "类型杂耍"。但 PHP 是非常灵活的,所以有时必须由你来指定所需的类型。当使用 echo 打印时,PHP 会尝试将得到的所有内容转换成字符串。由于布尔型 false 的字符串版本是空字符串,这对我们的应用程序没有用处。首先将布尔值转换为整数,可以确保我们看到一个值,即使它只是一个 0

HTML 表单

HTML 表单是收集用户信息最常用的方法之一。表单由一系列字段(在 HTML 世界中称为输入)和最后的提交按钮组成。在 HTML 中,表单标签包含两个属性:action(表单提交位置)和 method(指定表单使用的 HTTP 方法(GET 或 POST))。让我们看看它是如何工作的。将以下内容保存为 login.html,然后访问 http://localhost:8000/login.html

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Bookstore - Login</title>
    </head>
    <body>
        <p>Enter your details to login:</p>
        <form action="authenticate.php" method="post">
            <label>Username</label>
            <input type="text" name="username" />
            <label>Password</label>
            <input type="password" name="password" />
            <input type="submit" value="Login"/>
        </form>
    </body>
</html>

前面代码中定义的表单包含两个字段,一个是用户名,另一个是密码。可以看到,它们是通过属性名来标识的。如果您尝试提交该表单,浏览器将显示 "未找到页面"(Page Not Found)信息,因为它正试图访问 http://localhost:8000/authenticate.php ,但网络服务器找不到它。那我们就来创建它吧:

<?php
    $submitted = !empty($_POST);
?>
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Bookstore</title>
    </head>
    <body>
        <p>Form submitted? <?php echo (int) $submitted; ?></p>
        <p>Your login info is</p>
        <ul>
            <li><b>username</b>: <?php echo $_POST['username']; ?></li>
            <li><b>password</b>: <?php echo $_POST['password']; ?></li>
        </ul>
    </body>
</html>

$_GET 一样,$_POST 也是一个数组,其中包含 POST 收到的参数。在前面这段代码中,我们首先询问该数组是否为空—​注意!操作符。然后,我们就像在 index.php 中一样显示收到的信息。注意 $_POST 数组的键是每个输入字段的参数名称值。

当我们希望浏览器记住一些数据时,例如您是否登录了网络应用程序、您的基本信息等,我们就会使用 CookieCookie 存储在客户端,并在请求时作为头信息发送到服务器。由于 PHP 面向的是网络应用程序,因此它允许你以非常简单的方式管理 Cookie

关于 Cookie 和 PHP,有几件事你需要知道。您可以使用 setcookie 函数编写 cookie,该函数接受多个参数:

  • 作为字符串的 cookie 的有效名称。

  • cookie 的值—仅限字符串或可转换为字符串的值。该参数是可选的,如果不设置,PHP 将实际删除 cookie

  • 作为时间戳的到期时间。如果未设置,则浏览器关闭后 cookie 将被删除。

时间戳

计算机使用不同的方法来描述日期和时间,其中一种非常常见的方法,尤其是在 Unix 系统中,就是使用时间戳。它们表示自 1970 年 1 月 1 日以来经过的秒数。例如,表示 2015 年 10 月 4 日下午 6:30 时的时间戳为 1,443,954,637,即自该日期以来的秒数。使用 PHP 的 time 函数可以获取当前的时间戳。

还有其他与安全相关的参数,但不在本节讨论范围之内。还要注意的是,只有在应用程序没有输出之前,即在 HTML、echo 调用和任何其他类似函数发送输出之前,才能设置 cookie。

要读取客户端发送给我们的 cookie,我们只需访问数组 $_COOKIE。它的工作原理与其他两个数组相同,因此数组的键将是 cookie 的名称,数组的值将是它们的值。

Cookie 的一个非常常见的用途是验证用户身份。根据应用程序所需的安全级别,有几种不同的方法可以做到这一点。让我们尝试实现一种非常简单但不安全的方法(请勿用于实时网络应用程序)。在不改变 HTML 的情况下,用以下内容更新 authenticate.php 文件的 PHP 部分:

<?php
    setcookie('username', $_POST['username']);
    $submitted = !empty($_POST);
?>

index.php 中的 body 标签做同样的处理:

<body>
    <p>You are <?php echo $_COOKIE['username']; ?></p>
    <p>Are you looking for a book? <?php echo (int) $lookingForBook;?></p>
    <p>The book you are looking for is</p>
    <ul>
        <li><b>Title</b>: <?php echo $_GET['title']; ?></li>
        <li><b>Author</b>: <?php echo $_GET['author']; ?></li>
    </ul>
</body>

如果您再次访问 http://localhost:8000/login.html ,尝试登录,(在同一浏览器中)打开一个新标签页,并转到 http://localhost:8000 主页,您就会看到浏览器仍然会记住您的用户名。

其它超全局变量

$_GET$_POST$_COOKIE 是被称为 superglobals 的特殊变量。还有其他一些超级全局变量,如 $_SERVER$_ENV,它们会提供额外的信息。第一个超全局变量会显示头信息、访问路径以及与请求相关的其他信息。第二个变量包含运行应用程序的机器的环境变量。您可以在 http://php.net/manual/es/language.variables.superglobals.php 上查看这些数组及其元素的完整列表。

一般来说,使用 superglobals 非常有用,因为它可以让你从用户、浏览器和请求等方面获取信息。这在编写需要与用户交互的网络应用程序时具有不可估量的价值。但是,能力越大,责任越大,在使用这些数组时应非常小心。这些值大多来自用户本身,可能会导致安全问题。