PHP: JSON与邮件
JSON 是 Web 世界的通用语言——前端后端对话靠它、API 传输靠它、配置文件也用它。邮件是 Web 应用的必配功能——注册验证、密码重置、通知提醒。这节课全包。
1. JSON 基础
PHP
<?php
// PHP 数组/对象 → JSON 字符串
$data = [
'name' => '小明',
'age' => 25,
'skills' => ['PHP', 'MySQL', 'JavaScript'],
'isActive' => true,
'score' => null,
];
$json = json_encode($data);
echo $json;
// {"name":"小明","age":25,"skills":["PHP","MySQL","JavaScript"],"isActive":true,"score":null}
?>
(1) json_encode 常用选项
PHP
<?php
$data = ['name' => '小明', 'age' => 25, 'score' => null];
// 美化输出(人类可读)
echo json_encode($data, JSON_PRETTY_PRINT);
/*
{
"name": "小明",
"age": 25,
"score": null
}
*/
// 不转义 Unicode(中文正常显示)
echo json_encode($data, JSON_UNESCAPED_UNICODE);
// {"name":"小明","age":25,"score":null}
// 组合使用
echo json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
// 处理 null(PHP 8.3+)
echo json_encode($data, JSON_UNESCAPED_UNICODE, JSON_INVALID_UTF8_IGNORE);
?>
| 选项 | 效果 |
|---|---|
JSON_PRETTY_PRINT |
缩进格式化 |
JSON_UNESCAPED_UNICODE |
中文不转 \uXXXX |
JSON_UNESCAPED_SLASHES |
/ 不转 \/ |
JSON_NUMERIC_CHECK |
数字字符串转数字 |
JSON_FORCE_OBJECT |
空数组输出 {} |
2. json_decode — JSON 解析
PHP
<?php
$json = '{"name":"小明","age":25,"skills":["PHP","MySQL"]}';
// 默认返回对象
$obj = json_decode($json);
echo $obj->name; // 小明
echo $obj->skills[0]; // PHP
// 第二个参数 true → 返回关联数组
$arr = json_decode($json, true);
echo $arr['name']; // 小明
// 错误处理
$badJson = '{name: 小明}'; // 缺双引号
$result = json_decode($badJson);
if (json_last_error() !== JSON_ERROR_NONE) {
echo "JSON 解析错误:" . json_last_error_msg();
// JSON 解析错误:Syntax error
}
// PHP 7.3+ 更简洁的写法
$result = json_decode($badJson);
echo json_last_error_msg();
?>
▶ 示例:读取和写入 JSON 文件
PHP
<?php
// === 写 JSON 文件 ===
$config = [
'app_name' => 'MyBlog',
'version' => '1.2.0',
'database' => [
'host' => 'localhost',
'name' => 'myblog',
],
'features' => ['blog', 'comments', 'search'],
];
$json = json_encode($config, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
file_put_contents('config.json', $json, LOCK_EX);
echo "配置文件已写入 ✅";
// === 读 JSON 文件 ===
$json = file_get_contents('config.json');
$config = json_decode($json, true);
echo "应用名称:{$config['app_name']}<br>";
echo "数据库主机:{$config['database']['host']}<br>";
echo "功能列表:" . implode(', ', $config['features']) . "<br>";
?>
▶ 示例:REST API 模拟
PHP
<?php
// api.php — 简单的 JSON API
header('Content-Type: application/json; charset=utf-8');
$method = $_SERVER['REQUEST_METHOD'];
$path = $_GET['path'] ?? '';
$users = [
['id' => 1, 'name' => '小明', 'email' => 'x@x.com'],
['id' => 2, 'name' => '小红', 'email' => 'h@h.com'],
];
if ($method === 'GET' && $path === 'users') {
echo json_encode(['status' => 'ok', 'data' => $users], JSON_UNESCAPED_UNICODE);
} elseif ($method === 'GET' && preg_match('/users\/(\d+)/', $path, $m)) {
$id = (int)$m[1];
$user = $users[$id - 1] ?? null;
if ($user) {
echo json_encode(['status' => 'ok', 'data' => $user], JSON_UNESCAPED_UNICODE);
} else {
http_response_code(404);
echo json_encode(['status' => 'error', 'message' => '用户不存在']);
}
} elseif ($method === 'POST' && $path === 'users') {
$input = json_decode(file_get_contents('php://input'), true);
// 这里正常会写入数据库
echo json_encode(['status' => 'ok', 'message' => '用户创建成功']);
} else {
http_response_code(404);
echo json_encode(['status' => 'error', 'message' => '未知接口']);
}
?>
3. 发送邮件
(1) mail() 基础
PHP
<?php
$to = "user@example.com";
$subject = "=?UTF-8?B?" . base64_encode("密码重置通知") . "?="; // 中文标题编码
$message = "您好,请点击以下链接重置密码:\n\n";
$message .= "https://myblog.com/reset?token=abc123";
$headers = "From: noreply@myblog.com\r\n";
$headers .= "Content-Type: text/plain; charset=UTF-8\r\n";
if (mail($to, $subject, $message, $headers)) {
echo "邮件发送成功 ✅";
} else {
echo "邮件发送失败 ❌";
}
?>
💡 提示:
mail() 需要服务器配置好 sendmail/Postfix。本地 XAMPP 默认没有——测试邮件功能最好用 SMTP(下一节)。
▶ 示例:验证邮件 HTML 格式
PHP
<?php
function sendVerificationEmail(string $to, string $token): bool {
$subject = "=?UTF-8?B?" . base64_encode("请验证您的邮箱") . "?=";
// HTML 邮件
$message = "<html><body>";
$message .= "<h2>欢迎注册 MyBlog!</h2>";
$message .= "<p>请点击以下链接验证您的邮箱:</p>";
$message .= "<a href='https://myblog.com/verify?token={$token}'>验证邮箱</a>";
$message .= "<p>如果链接无法点击,请复制以下地址:</p>";
$message .= "<p>https://myblog.com/verify?token={$token}</p>";
$message .= "</body></html>";
$headers = "From: noreply@myblog.com\r\n";
$headers .= "MIME-Version: 1.0\r\n";
$headers .= "Content-Type: text/html; charset=UTF-8\r\n";
return mail($to, $subject, $message, $headers);
}
$token = bin2hex(random_bytes(32));
sendVerificationEmail('user@example.com', $token);
?>
4. PHPMailer(推荐)
mail() 简单但限制多。PHPMailer 是 PHP 邮件的事实标准:
BASH
# 安装
composer require phpmailer/phpmailer
PHP
<?php
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
require 'vendor/autoload.php';
function sendEmailSMTP(string $to, string $subject, string $body): bool {
$mail = new PHPMailer(true);
try {
// 服务器设置
$mail->isSMTP();
$mail->Host = 'smtp.gmail.com'; // SMTP 服务器
$mail->SMTPAuth = true;
$mail->Username = 'your@gmail.com'; // 发送邮箱
$mail->Password = 'app-password'; // 应用专用密码
$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
$mail->Port = 587;
$mail->CharSet = 'UTF-8';
// 收发人
$mail->setFrom('your@gmail.com', 'MyBlog');
$mail->addAddress($to);
// 内容
$mail->isHTML(true);
$mail->Subject = $subject;
$mail->Body = $body;
$mail->AltBody = strip_tags($body); // 纯文本备用
$mail->send();
return true;
} catch (Exception $e) {
echo "邮件发送失败:{$mail->ErrorInfo}";
return false;
}
}
sendEmailSMTP(
'user@example.com',
'密码重置通知',
'<h3>MyBlog 密码重置</h3><p>点击<a href="#">这里</a>重置密码。</p>'
);
?>
💡 提示: 用 Gmail 测试时:开启两步验证 → 生成应用专用密码 → 使用该密码(不是你的 Gmail 登录密码)。直接写真密码 Gmail 会拒收。
5. 邮件最佳实践
PHP
<?php
class MailService {
public function sendWelcome(string $email, string $username): bool {
$subject = "欢迎加入 MyBlog";
$body = file_get_contents(__DIR__ . '/templates/welcome.html');
$body = str_replace('{{username}}', htmlspecialchars($username), $body);
return sendEmailSMTP($email, $subject, $body);
}
public function sendPasswordReset(string $email, string $token): bool {
$link = "https://myblog.com/reset?token={$token}";
$subject = "密码重置";
$body = "
<h3>密码重置请求</h3>
<p>点击以下链接重置密码(有效期 1 小时):</p>
<a href='{$link}'>{$link}</a>
<p>如果您没有请求重置密码,请忽略此邮件。</p>
";
return sendEmailSMTP($email, $subject, $body);
}
public function sendNotification(string $email, string $title, string $message): bool {
$subject = "📢 {$title}";
$body = "<h3>{$title}</h3><p>{$message}</p>";
return sendEmailSMTP($email, $subject, $body);
}
}
?>
❓ 常见问题
Q JSON 为什么比 XML 流行?
A 轻量(少标签)、原生被 JavaScript 支持(
JSON.parse)、可读性好。PHP 中 json_encode/json_decode 一行搞定,而 XML 要好几步。Q
mail() 和 SMTP 库怎么选?A 本地开发用
mail() 方便(如果配好了),生产环境用 SMTP 库(PHPMailer)——它有更好错误处理、支持附件、支持多收件人、不受服务器 mail 配置影响。Q JSON 文件做数据库可以吗?
A 少量数据、单用户场景可以(如配置文件)。多用户并发读写、复杂查询必须用 MySQL。JSON 文件做数据库的问题:无法并发写、无索引查询慢、数据越多越慢。
📖 小节
json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT)序列化json_decode($json, true)解析(true=数组,默认=对象)json_last_error_msg()检查解析错误mail()简单但需服务器配置,中文标题要base64_encode- 生产环境用 SMTP(PHPMailer),支持附件、HTML、加密
- JSON 文件适合单用户配置、API 传输;多用户数据用数据库
📝 作业
- 创建一个
settings.json配置文件,用 PHP 读取并显示所有配置项。 - 写一个简单的 JSON API:
/users返回所有用户,/users/1返回 ID=1 的用户,用 GET 参数模拟。 - 给注册系统加上邮件验证功能:注册时生成验证 token(存文件/数据库),发送验证邮件(本地用
mail()或 SMTP 测试)。