综合练习
带 PDO 与表单校验的小型 API。
40 分钟
综合练习
整合本 track 所学:构建带 PDO、表单校验与 JSON API 的「课时管理」小项目,作为毕业验收。复习 php-essentials;路径 /roadmaps/php。
学习目标
- 完成可运行的课时 CRUD API 与简单管理页
- 实践 PDO 预处理、Session 鉴权与输入校验
- 通过 Pest 测试与 PHPCS 检查
需求说明
GET /api/lessons?track=php-advanced-essentials:返回该 track 下所有课时 JSONPOST /api/lessons:创建课时(需登录 Session),字段slug、title、track- 所有写操作校验 slug 格式(小写字母、数字、连字符)
- 密码用
password_hash存储;登录后写 Session
核心实现
<?php
declare(strict_types=1);
session_start();
header('Content-Type: application/json; charset=utf-8');
$pdo = new PDO('mysql:host=127.0.0.1;dbname=coderoadmap;charset=utf8mb4');
$method = $_SERVER['REQUEST_METHOD'];
$uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
match (true) {
$method === 'GET' && $uri === '/api/lessons' => listLessons($pdo),
$method === 'POST' && $uri === '/api/lessons' => createLesson($pdo),
default => respond(404, ['error' => 'not found']),
};
function listLessons(PDO $pdo): never {
$track = $_GET['track'] ?? '';
$stmt = $pdo->prepare('SELECT slug, title FROM lessons WHERE track_slug = ?');
$stmt->execute([$track]);
respond(200, $stmt->fetchAll(PDO::FETCH_ASSOC));
}
function createLesson(PDO $pdo): never {
if (!isset($_SESSION['user_id'])) {
respond(401, ['error' => 'login required']);
}
$body = json_decode(file_get_contents('php://input'), true) ?? [];
$slug = trim($body['slug'] ?? '');
if (!preg_match('/^[a-z0-9-]+$/', $slug)) {
respond(422, ['error' => 'invalid slug']);
}
$stmt = $pdo->prepare('INSERT INTO lessons (slug, title, track_slug) VALUES (?, ?, ?)');
$stmt->execute([$slug, $body['title'] ?? '', $body['track'] ?? '']);
respond(201, ['slug' => $slug]);
}
function respond(int $code, array $data): never {
http_response_code($code);
echo json_encode($data, JSON_UNESCAPED_UNICODE);
exit;
}
练习
- 完成 API 并通过 Pest 测试
- 运行 PHPCS(PSR-12)无报错
- 写 README 并在路线图选定下一节点