文件系统
正如你可能已经注意到的,与其他语言相比,PHP 自带的大量本地函数可以帮助你更轻松地管理数组和字符串。文件系统是 PHP 尽可能简化的另一个领域。函数列表中有 80 多个不同的函数,因此我们在这里只介绍比较可能用到的函数。
读文件
在我们的代码中,我们定义了一个书籍列表。到目前为止,我们只有三本书,但你可以猜到,如果我们想让这个应用程序变得有用,那么这个列表就会越来越多。将信息存储在代码中根本不现实,因此我们必须开始考虑将其外部化。
如果我们从将代码与数据分离的角度考虑,就没有必要继续使用 PHP 数组来定义书籍。使用语言限制较少的系统可以让不懂 PHP 的人也能编辑文件内容。这方面有很多解决方案,如 CSV 或 XML 文件,但如今在网络应用程序中最常用的数据表示系统之一是 JSON。PHP 允许使用几个函数将数组转换为 JSON,反之亦然:json_encode
和 json_decode
。很简单吧?
将以下内容保存到 books.json 中:
[
{
"title": "To Kill A Mockingbird",
"author": "Harper Lee",
"available": true,
"pages": 336,
"isbn": 9780061120084
},
{
"title": "1984",
"author": "George Orwell",
"available": true,
"pages": 267,
"isbn": 9780547249643
},
{
"title": "One Hundred Years Of Solitude",
"author": "Gabriel Garcia Marquez",
"available": false,
"pages": 457,
"isbn": 9785267006323
}
]
前面的代码片段是数组在 PHP 中的 JSON 表示。现在,让我们用 file_get_contents
函数读取这些信息,并用 json_decode
将其转换为 PHP 数组。用这两行替换数组:
$booksJson = file_get_contents('books.json');
$books = json_decode($booksJson, true);
只需一个函数,我们就能将 JSON 文件中的所有内容以字符串形式存储到一个变量中。通过该函数,我们将 JSON 字符串转换为数组。json_decode
中的第二个参数告诉 PHP 将其转换为数组,否则就会使用对象,这一点我们尚未涉及。
在 PHP 函数中引用文件时,需要知道是使用绝对路径还是相对路径。使用相对路径时,PHP 会尝试在 PHP 脚本所在的同一目录中查找文件。如果找不到,PHP 会尝试在 include_path
指令中定义的其他目录中查找,但这是需要避免的。相反,可以使用绝对路径,这样可以确保引用不会被误解。我们来看两个例子:
$booksJson = file_get_contents('/home/user/bookstore/books.json');
$booksJson = file_get_contents(__DIR__, '/books.json');
常量 __DIR__
包含当前 PHP 文件的目录名,如果我们在文件名前加上它,就会得到一个绝对路径。事实上,尽管你可能认为自己写下整个路径更好,但使用 __DIR__
可以让你把程序移到其他地方,而不需要修改代码中的任何内容,因为它的内容始终与脚本的目录一致,而第一个例子中的硬编码路径将不再有效。
写文件
让我们为应用程序添加一些功能。想象一下,我们希望允许用户选取他或她正在寻找的图书,但前提是该图书必须可用。如果你还记得,我们是通过查询字符串来识别图书的。这样做不太现实,所以我们可以在图书列表中添加链接,这样当你点击一个链接时,查询字符串就会包含该图书的信息。
<?php require_once 'functions.php' ?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Bookstore</title>
</head>
<body>
<p><?php echo loginMessage(); ?></p>
<?php
$booksJson = file_get_contents('books.json');
$books = json_decode($booksJson, true);
if (isset($_GET['title'])) {
echo '<p>Looking for <b>' . $_GET['title'] . '</b></p>';
} else {
echo '<p>You are not looking for a book?</p>';
}
?>
<ul>
<?php foreach ($books as $book): ?>
<li>
<a href="?title=<?php echo $book['title']; ?>">
<?php echo printableTitle($book); ?>
</a>
</li>
<?php endforeach; ?>
</ul>
</body>
</html>
如果在浏览器中试用前面的代码,就会发现列表中包含链接,点击链接后,页面会以新标题作为查询字符串的一部分刷新。现在让我们检查一下这本书是否可用,如果可用,则将其可用字段更新为 false
。在 functions.php
中添加以下函数:
function bookingBook(array &$books, string $title): bool {
foreach ($books as $key => $book) {
if ($book['title'] == $title) {
if ($book['available']) {
$books[$key]['available'] = false;
return true;
} else {
return false;
}
}
}
return false;
}
当代码开始变得复杂时,我们就必须注意了。该函数接收一个图书数组和一个书名,并返回一个布尔值,如果可以预订则为 true
,否则为 false
。此外,图书数组是通过引用传递的,这意味着对该数组的所有更改也会影响原始数组。尽管我们之前不鼓励这样做,但在本例中,这是一种合理的方法。
我们遍历整个图书数组,每次都会询问当前图书的标题是否与我们要查找的图书一致。只有在符合的情况下,我们才会检查该书是否可用。如果是,我们会将可用性更新为 false
并返回 true
,这意味着我们预订了这本书。如果图书不可用,我们将只返回 false
。
最后,请注意 foreach
定义了 $key
和 $book
。我们这样做是因为 $book
变量是 $books
数组的副本,如果我们编辑它,原来的数组不会受到影响。相反,我们还需要该书的键,所以在编辑数组时,我们使用 $books[$key]
而不是 $book
。
我们可以从 index.php
文件中使用这个函数:
//...
echo '<p>Looking for <b>' . $_GET['title'] . '</b></p>';
if (bookingBook($books, $_GET['title'])) {
echo 'Booked!';
} else {
echo 'The book is not available...';
}
} else {
//...
请在浏览器中试用。点击可用图书,您将收到 "已预订" 信息。我们就快完成了!我们只差最后一部分:将这些信息持久保存回文件系统。为此,我们必须构建新的 JSON 内容,然后将其写回 books.json
文件。当然,只有在图书可用的情况下才能这样做。
function updateBooks(array $books) {
$booksJson = json_encode($books);
file_put_contents(__DIR__ . '/books.json', $booksJson);
}
json_encode
函数的作用与 json_decode
相反:它接收一个数组或任何其他变量,并将其转换为 JSON 格式。file_put_contents
函数用于向作为第一个参数引用的文件写入作为第二个参数发送的内容。您知道如何使用该函数吗?
//...
if (bookingBook($books, $_GET['title'])) {
echo 'Booked!';
updateBooks($books);
} else {
echo 'The book is not available...';
}
//...
文件与数据库
在 JSON 文件中存储信息比在代码中存储信息要好,但仍不是最佳选择。在第 5 章 "使用数据库" 中,您将学习如何在数据库中存储应用程序的数据,这是一个更好的解决方案。 |
其它文件系统函数
如果想让应用程序更强大,可以检查 books.json
文件是否存在、是否有读写权限和/或之前的内容是否是有效的 JSON。为此,您可以使用一些 PHP 函数:
-
file_exists:该函数获取文件路径,并返回布尔值:文件存在时为
true
,否则为false
。 -
is_writable: 该函数的作用与
file_exists
相同,但会检查文件是否可写。
您可以在 http://uk1.php.net/manual/en/book.filesystem.php 中找到完整的函数列表。您可以找到用于移动、复制或删除文件、创建目录、赋予权限和所有权等的函数。