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 文件做数据库的问题:无法并发写、无索引查询慢、数据越多越慢。

📖 小节

📝 作业

  1. 创建一个 settings.json 配置文件,用 PHP 读取并显示所有配置项。
  2. 写一个简单的 JSON API:/users 返回所有用户,/users/1 返回 ID=1 的用户,用 GET 参数模拟。
  3. 给注册系统加上邮件验证功能:注册时生成验证 token(存文件/数据库),发送验证邮件(本地用 mail() 或 SMTP 测试)。
Web-Tutorial.com

Web-Tutorial 技术团队

由多位开发者共同维护的编程教程平台。每篇教程由对应领域的开发者编写和审核,确保内容准确可靠。如发现任何问题,欢迎向我们反馈。

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏