GraphQL vs REST在PHP中:架构之争还是不同任务的工具?
\n\n当你再次打开代码编辑器,为你的PHP应用编写一个新端点时,一种似曾相识的感觉挥之不去。又要创建控制器?又要写验证逻辑?或许,是时候尝试点新东西了?在PHP开发世界中,GraphQL与REST之间的争论,就像“Laravel”与“Symfony”的永恒之争——每个人都声嘶力竭地捍卫自己的技术栈。但让我们坦诚地说:这两种方法都不是信仰,而是工具。今天,我们将把它们拆解成一个个零件,看看真实的代码,并决定何时PHP的REST API是你的选择,何时又该关注PHP中的GraphQL。
\n\n快速入门:它们是什么?
\n\nREST(表述性状态转移)是一种架构风格,建立在资源和HTTP方法的原则之上。你访问/api/users,获得用户列表。想要单个用户?加上/api/users/42。一切都很逻辑、可预测且简单。
GraphQL是一种由Facebook创建的查询语言。你不受URL的束缚。你向一个统一的端点(例如/graphql)发送一个请求,并说:“给我用户42的名字、他最近的5篇帖子以及每篇帖子下的点赞数。”服务器只返回你所请求的内容。不多一个字节。
看起来,GraphQL在得分上胜出。但先别急着抛弃老牌的REST。每种方法都有其陷阱,尤其是在PHP开发的背景下。
\n\n架构对比:从理论到代码
\n\nREST:经典之作
\n\n在PHP中,REST通过路由实现。像Laravel或Symfony这样的框架能优雅地做到这一点。以下是Laravel中一个典型REST控制器的示例:
\n\n<?php\n\nnamespace App\\Http\\Controllers\\Api;\n\nuse App\\Models\\User;\nuse Illuminate\\Http\\Request;\n\nclass UserController extends Controller\n{\n public function index()\n {\n return User::all();\n }\n\n public function show($id)\n {\n $user = User::with('posts.comments')->findOrFail($id);\n return response()->json($user);\n }\n\n public function store(Request $request)\n {\n $validated = $request->validate([\n 'name' => 'required|string',\n 'email' => 'required|email|unique:users',\n ]);\n\n $user = User::create($validated);\n return response()->json($user, 201);\n }\n}\n\n优点显而易见:缓存简单(HTTP缓存、Varnish)、URL结构清晰、工具支持广泛(Postman、Swagger)。缺点——过度获取和欠获取的问题。如果前端只需要用户名,而你在响应中返回了模型的所有字段——这就是过度获取。如果需要用户名和好友列表,而你却发出了两个请求——这就是欠获取。
\n\nGraphQL:带有陷阱的灵活性
\n\n要在PHP中实现GraphQL,有一些优秀的库:webonyx/graphql-php(纯PHP)和lighthouse-php/lighthouse(用于Laravel)。以下是使用graphql-php的schema和resolver示例:
\n\n<?php\n\nuse GraphQL\\GraphQL;\nuse GraphQL\\Type\\Definition\\ObjectType;\nuse GraphQL\\Type\\Definition\\Type;\nuse GraphQL\\Type\\Schema;\n\n$userType = new ObjectType([\n 'name' => 'User',\n 'fields' => [\n 'id' => Type::int(),\n 'name' => Type::string(),\n 'email' => Type::string(),\n 'posts' => [\n 'type' => Type::listOf($postType),\n 'resolve' => function ($user) {\n return getPostsByUserId($user['id']);\n }\n ],\n ],\n]);\n\n$queryType = new ObjectType([\n 'name' => 'Query',\n 'fields' => [\n 'user' => [\n 'type' => $userType,\n 'args' => [\n