logo

额外区块类型 (EBT) - 全新的布局构建器体验❗

额外区块类型 (EBT) - 样式化、可定制的区块类型:幻灯片、标签页、卡片、手风琴等更多类型。内置背景、DOM Box、JavaScript 插件的设置。立即体验布局构建的未来。

演示 EBT 模块 下载 EBT 模块

❗额外段落类型 (EPT) - 全新的 Paragraphs 体验

额外段落类型 (EPT) - 类似的基于 Paragraph 的模块集合。

演示 EPT 模块 滚动

滚动

PHP课程 - 第2课 - 文件操作:打开、写入与读取。

09/10/2025, by Ivan

在上一课中,我们已经为我们的留言簿、博客或聊天室搭建了框架。现在只需继续添加功能。在本课中,我们将学习如何将我们的内容写入文件,并从文件中读取内容。

PHP 提供了大量用于文件操作的函数,我们只会学习其中一部分。因为在实际项目中,你的网站大多数情况下会将数据保存到数据库中(我非常确定),而不是写入文件。不过,了解文件操作的原理有助于理解 PHP 的基本机制。之后我们会学习如何操作数据库。

如果你还没有上节课创建的那些文件,请先返回上一课并下载它们。

现在让我们进入添加记录的表单:

/index.php?admin=1

我们将通过这个表单来添加内容。要处理提交的数据,我们需要在 index.php 页面上检查是否存在 $_POST 变量。检查方法非常简单:

if($_POST){

}

是不是很简单?现在我们要在大括号内编写对 $_POST 数组的处理逻辑。但我们不会直接在这里写所有逻辑,而是将其放入我们的类中,并通过对象的方法来调用。在 index.php 文件中这样写:

if($_POST){
 $obj->write($_POST);
}

而在 simpleCMS.php 文件中,我们将实现 write() 方法:

  public function write($p) { // 写入消息的方法
  
  }  

为什么这样做?因为这样可以简化 index.php 文件的代码。index.php 只负责控制流程,而具体的数据处理和输出应该放在类文件中。这样的结构清晰明了,不仅方便他人阅读代码,也方便自己维护。

我们先从最简单的操作开始——打印 $_POST 数组内容:

  public function write($p) { // 写入消息的方法
     print_r($p);
  }  

正如你所见,我们使用了本地变量 $p,虽然传入的是全局变量 $_POST。我们不直接操作全局变量是为了让方法更通用,比如将来我们可能希望从 XML 文件中导入数据,而不仅仅是表单提交。

现在填写表单并提交后,你将看到如下数组:

Array ( [title] => Иван [bodytext] => Привет, Мир! )

如果你的表单内容不同,数组值也会不同。我们打印数组是为了知道有哪些键名可以使用,这里是 $p['title']$p['bodytext']。了解这些之后,我们就可以将数据写入文件了。

PHP 写入文件

在写入文件之前,必须先“打开文件以进行写入”。打开文件意味着将文件与一个 PHP 变量关联。文件在 PHP 中被表示为一种 resource(资源)类型。我们来看一个例子:

  public function write($p) { // 写入消息的方法
	$message = fopen("messages/file.txt","w"); 
	print_r($message);
  }  

我在 messages 文件夹中创建了一个 file.txt 文件。提交表单后,你会看到如下输出:

Resource id #4

Resource 是变量 $message 的类型,而数字 4 表示该资源在内存中的 ID。对 $message 的任何操作都会影响文件本身。我们将按行写入文件,以便以后可以按行读取:

  public function write($p) { // 写入消息的方法
	$message = fopen("messages/file.txt","w"); 
	fputs ($message, $p['title']. "\r\n");
	fputs ($message, $p['bodytext']);
  }  

双引号中的 \r\n 表示换行符(在单引号中可能不起作用)。写入后的文件内容如下:

Иван
Привет, Мир!

完成文件操作后,记得关闭文件以释放内存:

  public function write($p) { // 写入消息的方法
	$message = fopen("messages/file.txt","w");  // 打开文件
	fputs ($message, $p['title']. "\r\n");
	fputs ($message, $p['bodytext']);
	fclose ($message); // 关闭文件
  }  

你可能注意到,每次重新写入文件时内容都会被覆盖。这取决于 fopen() 函数的第二个参数。我们可以控制文件打开的方式:

$message = fopen("messages/file.txt","r");  // 仅以读取模式打开文件
  1. r – 只读模式。
  2. r+ – 读写模式。
  3. w – 创建一个新空文件(若文件已存在则会被覆盖)。
  4. w+ – 读写模式,但若文件存在则清空其内容。
  5. a – 以追加方式写入文件,指针移动到文件末尾。
  6. a+ – 读写并追加模式,指针在文件末尾,原内容保留。

如上所述,当以参数 w 打开文件时,会创建一个新文件。我们可以使用 time() 函数生成基于时间的唯一文件名。

time() 函数返回自 1970 年 1 月 1 日起的秒数。

代码如下:

  public function write($p) { // 写入消息的方法
	$message = fopen('messages/'.time(),"w");  // 打开文件
	fputs ($message, $p['title']. "\r\n");
	fputs ($message, $p['bodytext']. "\r\n");
	fputs ($message, time());
	fclose ($message); // 关闭文件
  }  

这样每一秒都会创建一个新文件,文件名为时间戳。添加新记录后,新的文件将出现在 messages 文件夹中。接下来我们来读取文件内容。

PHP 读取文件

要读取文件,需以只读模式打开文件(参数为 r)。所有文件都在 messages 文件夹中,我们将使用 while 循环读取全部文件。

通过 opendir() 函数打开目录:

	if (is_dir('messages')) { // 检查目录是否存在
		if ($dh = opendir('messages')) { // 打开目录读取
			while (($file = readdir($dh)) !== false) { // 当文件存在时循环读取
				// 执行操作
			}
			closedir($dh); // 关闭目录
		}
	}  

函数 readdir() 返回文件名,存储在变量 $file 中。循环结束后关闭目录释放内存。

现在我们可以读取文件了,改进 display_public() 方法如下:

  public function display_public() { // 输出消息的方法
    $content = '';
	if (is_dir('messages')) { // 检查目录是否存在
		if ($dh = opendir('messages')) { // 打开目录读取
			while (($file = readdir($dh)) !== false) { // 遍历文件
			  if(substr($file, -4) == '.txt'){ // 只读取 .txt 文件
				$filename = 'messages/' . $file; // 文件完整路径
			    $message = fopen($filename, 'r'); // 打开文件
				$title = fgets($message); // 读取第一行
				$body = fgets($message);  // 读取第二行
				$time = fgets($message);  // 读取第三行
				print '<div class="post">';
				print '<span class="time">' . date('d-m-Y', $time) . '</span><h2>' . $title . '</h2>';
			    print '<p>' . $body . '</p>';
				print '</div>';
				fclose($message); // 关闭文件
			  }	
			}
			closedir($dh); // 关闭目录
		}
	}   	
	$content .= '<p><a href="/index.php?admin=1">添加新消息</a></p>';
    return $content;
  }

我在每一行都添加了注释,若有不明白的地方请在评论中提问,我会详细解释。

在实际开发中,你可能不会用逐行读取文件的方式存储内容,但理解这些基本的文件操作函数对掌握 PHP 的底层机制非常有帮助。

下面是当前网站的源代码示例。