前端工程师学 PHP:从零到 RESTful API + MVC 分层

背景

作为前端工程师,我一直想拓展后端能力。PHP 是最容易入门的服务端语言之一,语法和 JavaScript 相似,学习曲线平缓。用一个下午的时间,我从零学完了 PHP 基础,并进阶到前后端分离 API。

学习路径

1
PHP 基础语法 → 表单处理 → PDO + MySQL → RESTful API → CORS → Token 认证 → MVC 分层

PHP 基础:和 JavaScript 的对比

JS PHP 说明
let name = "test" $name = "test" PHP 变量必须 $ 前缀
str + str str . str PHP 用 . 拼接字符串
=== === PHP 也有严格相等
obj.prop $obj->prop PHP 对象用 ->
arr.push(x) $arr[] = x PHP 数组追加语法
foreach foreach ($arr as $item) 类似但需 $

关键认知转变:PHP 是请求级生命周期——每次请求开始时变量都是空的,请求结束后进程就退出(不像 Node.js 常驻内存)。

PDO + MySQL:安全的数据库操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 连接数据库
function db(): PDO {
static $pdo = null;
if ($pdo === null) {
$pdo = new PDO(
"mysql:host=127.0.0.1;dbname=learnphp;charset=utf8mb4",
"root", "password"
);
}
return $pdo;
}

// 预处理语句防 SQL 注入
$stmt = db()->prepare("SELECT * FROM messages WHERE name LIKE ?");
$stmt->execute(["%$search%"]);
$messages = $stmt->fetchAll();

预处理语句是把 SQL 模板和数据分开发送,数据库先编译模板,再填入参数。参数不会被当作 SQL 执行,彻底杜绝 SQL 注入。

RESTful API 设计

方法 路径 含义
GET /messages 获取列表
POST /messages 创建留言
DELETE /messages?id=1 删除留言(需认证)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 统一 JSON 响应
function jsonOut(int $code, string $message, $data = null, int $http = 200): void {
http_response_code($http);
echo json_encode([
"code" => $code,
"message" => $message,
"data" => $data
]);
exit;
}

// 获取 JSON 请求体
function inputJson(): array {
return json_decode(file_get_contents("php://input"), true) ?? [];
}

CORS:跨域请求处理

前端和 API 不同域名时,浏览器会发 CORS 预检(OPTIONS 请求)。简单请求(GET/POST 无自定义头)直接通过,复杂请求需要预检。

1
2
3
4
5
6
7
8
9
10
function handleCORS(): void {
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: GET, POST, DELETE, OPTIONS");
header("Access-Control-Allow-Headers: Content-Type, Authorization");

if ($_SERVER["REQUEST_METHOD"] === "OPTIONS") {
http_response_code(204);
exit;
}
}

Bearer Token 认证

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function requireAuth(): array {
$header = $_SERVER["HTTP_AUTHORIZATION"] ?? "";
if (!preg_match("/^Bearer\s+(.+)$/", $header, $m)) {
jsonOut(1, "未登录", null, 401);
}
$token = $m[1];

$stmt = db()->prepare(
"SELECT id, username FROM users WHERE token = ? AND token_expires_at > NOW()"
);
$stmt->execute([$token]);
$user = $stmt->fetch();
if (!$user) {
jsonOut(2, "token 无效或过期", null, 401);
}
return $user;
}

登录时用 random_bytes(32) 生成 64 字符随机 token,存到 users 表。这种 opaque token 比 JWT 更适合学习场景——简单直观,不引入额外库。

密码存储用 bcrypt:

1
2
$hash = password_hash($password, PASSWORD_DEFAULT);  // 注册时
password_verify($password, $user["password_hash"]); // 登录时验证

MVC 分层重构

从单文件 API 重构到 MVC 分层:

1
2
3
4
5
6
7
8
9
api/v2/
├── index.php # 前端控制器 + 路由表
├── models/
│ ├── Message.php # 数据层(SQL)
│ └── User.php
├── controllers/
│ ├── MessageController.php # 业务层(HTTP + 规则)
│ └── UserController.php
└── common.php # 公共工具(DB/CORS/jsonOut)

Model 层只管 SQL,不碰 HTTP。Controller 层处理请求解析、业务校验、响应格式。

1
2
3
4
5
6
7
8
9
// 路由表(前端控制器)
$routes = [
"messages" => [
"GET" => [$controller, "index"],
"POST" => [$controller, "store"],
"DELETE" => [$controller, "destroy"],
],
];
($routes[$path][$method])(); // 分发

依赖注入:从外层组装对象图,传入内部:

1
2
$messageModel = new Message(db());
$controller = new MessageController($messageModel);

这让你理解了 Laravel 的核心概念——Eloquent ORM、路由文件、Controller、中间件、服务容器,都是你手写原型的标准化版本。

总结

前端工程师学 PHP 的优势:

  • 语法相似度高($ 前缀、. 拼接是最大差异)
  • HTTP 概念相通(请求/响应/状态码/Header)
  • MVC 分层思想和其他框架一致
  • 异步思维转变后,同步阻塞模型反而更简单

最难的不是语言本身,而是服务端思维:请求级生命周期、并发处理、进程管理。但这些理解后,PHP 就是最直观的后端入门选择。