GraphQL vs REST在PHP中:2024年API该如何选择?

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

引言:REST还是GraphQL——速度与灵活性的永恒较量

\n

你好,开发者!如果你曾经用PHP编写过API,那么你一定遇到过这样的两难选择:使用经典的REST还是现代的GraphQL。这两种方法都解决同一个问题——在客户端和服务器之间传输数据,但实现方式截然不同。

\n

多年来,REST一直是事实上的标准:简单、易懂、可预测。但随着前端(React、Vue、移动应用)复杂性的增加,开发者们越来越频繁地抱怨过度获取(响应中包含过多数据)和获取不足(需要多次请求才能收集到所需信息)。这时,GraphQL登场了——这是一种查询语言,让客户端能够控制要获取哪些数据。

\n

在本文中,我们不会仅仅罗列理论。我们将以真实的PHP项目(Laravel和Symfony)为例,编写代码,看看哪个更快,哪个更方便。开始吧!

\n\n

1. PHP中的REST API:永不消亡的经典

\n

工作原理

\n

REST(表述性状态转移)是一种架构风格,其中每个资源(用户、文章、评论)都有其自己的URL地址。客户端发送HTTP请求(GET、POST、PUT、DELETE),服务器返回固定的数据结构,通常是JSON格式。

\n

一个典型的PHP REST端点示例(无框架):

\n
// index.php - 简单的REST API\nheader('Content-Type: application/json');\n\n$method = $_SERVER['REQUEST_METHOD'];\n$uri = $_SERVER['REQUEST_URI'];\n\nif ($method === 'GET' && $uri === '/api/users') {\n    $users = [\n        ['id' => 1, 'name' => '阿列克谢', 'email' => 'alex@example.com'],\n        ['id' => 2, 'name' => '玛丽亚', 'email' => 'maria@example.com']\n    ];\n    echo json_encode($users);\n}\n
\n

在Laravel中,这看起来更简单:

\n
// routes/api.php\nRoute::get('/users', function () {\n    return User::all(); // 自动序列化为JSON\n});\n
\n

REST的优点

\n
    \n
  • 缓存简单:HTTP缓存(ETag、Last-Modified)开箱即用。
  • \n
  • 易于调试:任何浏览器或curl都能显示响应。
  • \n
  • 稳定性:REST自2000年就已存在,文档和工具(Postman、Swagger)非常完善。
  • \n
\n

REST的缺点

\n
    \n
  • 过度获取:如果客户端只需要用户名,它仍然会获取到邮箱、电话、地址等信息。
  • \n
  • N+1问题:要获取用户及其文章,需要两次请求(GET /users/1, GET /users/1/posts)。
  • \n
\n\n

2. PHP中的GraphQL:客户端为王

\n

工作原理

\n

GraphQL不是数据库,而是客户端和服务器之间的一个层。客户端向一个端点(通常是/graphql)发送POST请求,请求体中描述了需要哪些字段和关联。服务器只返回所请求的内容——不多一个字节。

\n

使用webonyx/graphql-php库在PHP中的实现示例:

\n
// schema.php\nuse GraphQL\\Type\\Definition\\ObjectType;\nuse GraphQL\\Type\\Definition\\Type;\n\n$userType = new ObjectType([\n    'name' => 'User',\n    'fields' => [\n        'id' => Type::int(),\n        'name' => Type::string(),\n        'email' => Type::string(),\n    ]\n]);\n\n$queryType = new ObjectType([\n    'name' => 'Query',\n    'fields' => [\n        'user' => [\n            'type' => $userType,\n            'args' => ['id' => Type::int()],\n            'resolve' => function ($root, $args) {\n                return findUserById($args['id']); // 您的逻辑\n            }\n        ]\n    ]\n]);\n
\n

现在来看客户端的请求:

\n
// 请求                

博客

书籍推荐