引言:API 不是魔法,而是工具
\n当您的 PHP 网站不再只是一个静态页面,而是开始与外部世界(如 Telegram 机器人、支付网关或您自己的移动应用)通信时,您将不可避免地接触到 API(应用程序编程接口)。这只是一个契约:“如果你以这种格式向我发送请求,我将返回数据给你。”如今在 PHP 领域,有三个主要参与者:经典的 REST、灵活的 GraphQL 和激进的 gRPC。该如何选择?让我们通过实际示例来探讨。
\n本文面向那些已经会用 PHP 编写代码并希望拓宽视野的开发者。我们不会简单地复制文档,而是以解决实际问题的开发者的视角来审视每种协议。
\n\nPHP 中的 REST API:久经考验的经典
\nREST(表述性状态转移)不是一种协议,而是一种架构风格。它使用 HTTP 方法(GET、POST、PUT、DELETE)来处理资源。如果您曾经写过 file_get_contents('https://api.example.com/users'),那么您已经使用过 REST 了。
为什么 REST 仍然是王者?
\n- \n
- 简单性:任何 HTTP 客户端都可以使用它。 \n
- 缓存:可以在 HTTP 级别缓存 GET 请求。 \n
- 广泛支持:从 curl 到专门的库。 \n
使用 Guzzle 的 PHP REST 客户端示例
\nGuzzle 库是 PHP 中 HTTP 请求的事实标准。通过 Composer 安装:composer require guzzlehttp/guzzle。
<?php\nrequire 'vendor/autoload.php';\n\nuse GuzzleHttp\\Client;\n\n$client = new Client([\n 'base_uri' => 'https://jsonplaceholder.typicode.com/',\n 'timeout' => 5.0,\n]);\n\n// GET 请求\n$response = $client->get('posts/1');\n$post = json_decode($response->getBody(), true);\necho "帖子标题: " . $post['title'] . PHP_EOL;\n\n// POST 请求\n$response = $client->post('posts', [\n 'json' => [\n 'title' => '新帖子',\n 'body' => '帖子正文',\n 'userId' => 1\n ]\n]);\necho "创建的帖子 ID: " . json_decode($response->getBody(), true)['id'];\n?>\n我们做了什么?只是发送了 HTTP 请求。REST 不需要专门的库——甚至可以使用带上下文的 file_get_contents(),但 Guzzle 提供了便捷的错误处理、中间件和流式传输。
什么时候 REST 不是最佳选择?
\n如果您需要获取关联数据(例如,帖子 + 作者 + 评论),REST 会迫使您发出多个请求。这时,GraphQL 就登场了。
\n\nPHP 中的 GraphQL:只请求你需要的内容
\nGraphQL 是一种由 Facebook 开发的查询语言。客户端自己描述响应的结构。一个请求,一个响应,没有数据过多或不足的问题。
\nGraphQL 在 PHP 中如何工作?
\n服务端:webonyx/graphql-php 库(安装:composer require webonyx/graphql-php)。客户端:一个带有 JSON 主体的普通 HTTP POST 请求。
来自 PHP 的 GraphQL 请求示例
\n<?php\nrequire 'vendor/autoload.php';\n\nuse GuzzleHttp\\Client;\n\n$client = new Client(['base_uri' => 'https://countries.trevorblades.com/']);\n\n$query = '\nquery GetCountry {\n country(code: "RU") {\n name\n capital\n currency\n languages {\n name\n }\n }\n}';\n\n$response = $client->post('', [\n 'json' => ['query' => $query]\n]);\n\n$data = json_decode($response->getBody(), true);\necho "国家: " . $data['data']['country']['name'] . PHP_EOL;\necho "首都: " . $data['data']['country']['capital'] . PHP_EOL;\necho "货币: " . $data['data']['country']['currency'] . PHP_EOL;\necho "语言: ";\nforeach ($data['data']['country']['languages'] as $lang) {\n echo $lang['name'] . " ";\n}\n?>