如何通过一个RESTful API项目案例展示PHP如何输出JSON数据

wen PHP项目 49

本文目录导读:

如何通过一个RESTful API项目案例展示PHP如何输出JSON数据

  1. 项目结构
  2. 基础配置
  3. JSON响应工具类
  4. 图书模型
  5. API路由处理
  6. 数据库表结构
  7. 入口文件
  8. 使用示例
  9. 关键JSON输出技术总结

我来通过一个完整的图书管理系统API案例,展示PHP如何输出JSON数据。

项目结构

book-api/
├── index.php          # 入口文件
├── config/
│   └── database.php   # 数据库配置
├── api/
│   ├── books.php      # 图书API路由
│   └── response.php   # JSON响应工具类
└── models/
    └── Book.php       # 图书模型

基础配置

database.php - 数据库配置

<?php
// config/database.php
class Database {
    private $host = 'localhost';
    private $db_name = 'book_store';
    private $username = 'root';
    private $password = '';
    private $conn;
    public function getConnection() {
        $this->conn = null;
        try {
            $this->conn = new PDO(
                "mysql:host={$this->host};dbname={$this->db_name}",
                $this->username,
                $this->password
            );
            $this->conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        } catch(PDOException $e) {
            echo json_encode(['error' => $e->getMessage()]);
        }
        return $this->conn;
    }
}

JSON响应工具类

response.php - JSON输出工具

<?php
// api/response.php
class Response {
    // 设置响应头
    public static function setHeaders() {
        header("Access-Control-Allow-Origin: *");
        header("Content-Type: application/json; charset=UTF-8");
        header("Access-Control-Allow-Methods: GET, POST, PUT, DELETE");
        header("Access-Control-Max-Age: 3600");
        header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");
    }
    // 成功响应
    public static function success($data, $message = 'Success', $code = 200) {
        http_response_code($code);
        echo json_encode([
            'status' => 'success',
            'code' => $code,
            'message' => $message,
            'data' => $data,
            'timestamp' => date('Y-m-d H:i:s')
        ], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
        exit;
    }
    // 错误响应
    public static function error($message, $code = 400, $errors = []) {
        http_response_code($code);
        echo json_encode([
            'status' => 'error',
            'code' => $code,
            'message' => $message,
            'errors' => $errors,
            'timestamp' => date('Y-m-d H:i:s')
        ], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
        exit;
    }
}

图书模型

Book.php - 数据访问层

<?php
// models/Book.php
class Book {
    private $conn;
    private $table = 'books';
    public $id;
    public $title;
    public $author;
    public $isbn;
    public $price;
    public $category;
    public $created_at;
    public function __construct($db) {
        $this->conn = $db;
    }
    // 获取所有图书
    public function getAll() {
        $query = "SELECT * FROM {$this->table} ORDER BY created_at DESC";
        $stmt = $this->conn->prepare($query);
        $stmt->execute();
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }
    // 获取单本图书
    public function getById($id) {
        $query = "SELECT * FROM {$this->table} WHERE id = :id";
        $stmt = $this->conn->prepare($query);
        $stmt->bindParam(':id', $id);
        $stmt->execute();
        return $stmt->fetch(PDO::FETCH_ASSOC);
    }
    // 创建图书
    public function create($data) {
        $query = "INSERT INTO {$this->table} 
                  (title, author, isbn, price, category) 
                  VALUES (:title, :author, :isbn, :price, :category)";
        $stmt = $this->conn->prepare($query);
        $stmt->bindParam(':title', $data['title']);
        $stmt->bindParam(':author', $data['author']);
        $stmt->bindParam(':isbn', $data['isbn']);
        $stmt->bindParam(':price', $data['price']);
        $stmt->bindParam(':category', $data['category']);
        if($stmt->execute()) {
            return $this->conn->lastInsertId();
        }
        return false;
    }
    // 更新图书
    public function update($id, $data) {
        $query = "UPDATE {$this->table} 
                  SET title = :title, 
                      author = :author, 
                      isbn = :isbn, 
                      price = :price, 
                      category = :category 
                  WHERE id = :id";
        $stmt = $this->conn->prepare($query);
        $stmt->bindParam(':id', $id);
        $stmt->bindParam(':title', $data['title']);
        $stmt->bindParam(':author', $data['author']);
        $stmt->bindParam(':isbn', $data['isbn']);
        $stmt->bindParam(':price', $data['price']);
        $stmt->bindParam(':category', $data['category']);
        return $stmt->execute();
    }
    // 删除图书
    public function delete($id) {
        $query = "DELETE FROM {$this->table} WHERE id = :id";
        $stmt = $this->conn->prepare($query);
        $stmt->bindParam(':id', $id);
        return $stmt->execute();
    }
    // 搜索图书
    public function search($keyword) {
        $query = "SELECT * FROM {$this->table} 
                  WHERE title LIKE :keyword 
                  OR author LIKE :keyword 
                  OR isbn LIKE :keyword";
        $keyword = "%{$keyword}%";
        $stmt = $this->conn->prepare($query);
        $stmt->bindParam(':keyword', $keyword);
        $stmt->execute();
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }
}

API路由处理

books.php - 主API文件

<?php
// api/books.php
require_once '../config/database.php';
require_once '../models/Book.php';
require_once 'response.php';
// 设置响应头
Response::setHeaders();
// 处理预检请求
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
    http_response_code(200);
    exit;
}
// 数据库连接
$database = new Database();
$db = $database->getConnection();
$book = new Book($db);
// 获取请求方法
$method = $_SERVER['REQUEST_METHOD'];
// 解析URL获取ID参数
$request_uri = $_SERVER['REQUEST_URI'];
$path_parts = explode('/', trim($request_uri, '/'));
$id = end($path_parts);
$id = is_numeric($id) ? (int)$id : null;
// 获取请求体数据
$input_data = json_decode(file_get_contents("php://input"), true);
// 路由处理
switch ($method) {
    case 'GET':
        // 获取所有图书或单本图书
        if ($id) {
            $result = $book->getById($id);
            if ($result) {
                Response::success($result, '图书获取成功');
            } else {
                Response::error('图书不存在', 404);
            }
        } else {
            // 检查是否有搜索参数
            if (isset($_GET['search'])) {
                $result = $book->search($_GET['search']);
                Response::success($result, '搜索结果');
            } else {
                $result = $book->getAll();
                Response::success($result, '图书列表获取成功');
            }
        }
        break;
    case 'POST':
        // 创建图书 - 显示不同JSON输出方式
        if ($input_data) {
            // 方法1: 验证输入
            $validation = validateBookData($input_data);
            if (!$validation['valid']) {
                Response::error('数据验证失败', 422, $validation['errors']);
            }
            // 方法2: 输出创建请求的JSON格式
            echo json_encode([
                'debug' => [
                    'received_data' => $input_data,
                    'content_type' => $_SERVER['CONTENT_TYPE'],
                    'method' => $method
                ]
            ], JSON_PRETTY_PRINT);
            // 实际创建操作
            $new_id = $book->create($input_data);
            if ($new_id) {
                $new_book = $book->getById($new_id);
                Response::success($new_book, '图书创建成功', 201);
            } else {
                Response::error('创建失败', 500);
            }
        } else {
            Response::error('请提供图书数据', 400);
        }
        break;
    case 'PUT':
        // 更新图书
        if ($id && $input_data) {
            $validation = validateBookData($input_data);
            if (!$validation['valid']) {
                Response::error('数据验证失败', 422, $validation['errors']);
            }
            if ($book->update($id, $input_data)) {
                $updated_book = $book->getById($id);
                Response::success($updated_book, '图书更新成功');
            } else {
                Response::error('更新失败', 500);
            }
        } else {
            Response::error('请提供图书ID和数据', 400);
        }
        break;
    case 'DELETE':
        // 删除图书
        if ($id) {
            if ($book->delete($id)) {
                Response::success(null, '图书删除成功');
            } else {
                Response::error('删除失败', 500);
            }
        } else {
            Response::error('请提供图书ID', 400);
        }
        break;
    default:
        Response::error('不支持的请求方法', 405);
}
?>

数据库表结构

-- 创建数据库
CREATE DATABASE IF NOT EXISTS book_store;
USE book_store;
-- 创建图书表
CREATE TABLE books (
    id INT AUTO_INCREMENT PRIMARY KEY,VARCHAR(255) NOT NULL,
    author VARCHAR(255) NOT NULL,
    isbn VARCHAR(20) UNIQUE NOT NULL,
    price DECIMAL(10, 2) NOT NULL,
    category VARCHAR(100),
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 插入测试数据
INSERT INTO books (title, author, isbn, price, category) VALUES
('PHP编程入门', '张三', '978-7-111-11111-1', 59.00, '编程语言'),
('JavaScript高级编程', '李四', '978-7-111-22222-2', 69.00, '前端开发'),
('数据结构与算法', '王五', '978-7-111-33333-3', 79.00, '计算机科学'),
('Python数据分析', '赵六', '978-7-111-44444-4', 89.00, '数据分析');

入口文件

index.php - 入口和路由

<?php
// index.php - API入口文件
// 错误处理设置
error_reporting(E_ALL);
ini_set('display_errors', 0);
ini_set('log_errors', 1);
// 自定义异常处理
function exception_handler($exception) {
    Response::error('服务器内部错误', 500);
}
set_exception_handler('exception_handler');
// 数据验证函数
function validateBookData($data) {
    $errors = [];
    if (empty($data['title'])) {
        $errors[] = '书名不能为空';
    }
    if (empty($data['author'])) {
        $errors[] = '作者不能为空';
    }
    if (empty($data['isbn'])) {
        $errors[] = 'ISBN不能为空';
    }
    if (!isset($data['price']) || !is_numeric($data['price'])) {
        $errors[] = '价格必须是数字';
    }
    return [
        'valid' => empty($errors),
        'errors' => $errors
    ];
}
// 路由到API处理器
require_once 'api/books.php';
?>

使用示例

GET请求 - 获取所有图书

curl http://localhost/book-api/api/books.php

响应JSON:

{
    "status": "success",
    "code": 200,
    "message": "图书列表获取成功",
    "data": [
        {
            "id": 1,
            "title": "PHP编程入门",
            "author": "张三",
            "isbn": "978-7-111-11111-1",
            "price": "59.00",
            "category": "编程语言",
            "created_at": "2024-01-15 10:30:00"
        }
    ],
    "timestamp": "2024-01-15 14:30:00"
}

POST请求 - 创建图书

curl -X POST http://localhost/book-api/api/books.php \
  -H "Content-Type: application/json" \
  -d '{"title":"Node.js入门","author":"钱七","isbn":"978-7-111-55555-5","price":"49.00","category":"后端开发"}'

错误响应示例

{
    "status": "error",
    "code": 422,
    "message": "数据验证失败",
    "errors": ["书名不能为空", "价格必须是数字"],
    "timestamp": "2024-01-15 14:35:00"
}

关键JSON输出技术总结

  1. 设置Content-Type头header("Content-Type: application/json; charset=UTF-8")

  2. JSON编码选项

    • JSON_UNESCAPED_UNICODE:支持中文
    • JSON_PRETTY_PRINT:格式化输出
    • JSON_NUMERIC_CHECK:数字类型转换
  3. 状态码设置http_response_code(200)

  4. 输入获取json_decode(file_get_contents("php://input"), true)

  5. 错误处理:统一的JSON格式错误响应

这个完整的案例展示了如何在实际项目中高效地使用PHP输出JSON数据,包括错误处理、数据验证和格式化输出等最佳实践。

抱歉,评论功能暂时关闭!