Symfony HttpClient
教程展示了如何使用HttpClient
组件在 Symfony 中创建 HTTP 请求。 该组件提供使用 API 的工具,并支持同步和异步操作。
有关更多信息,请阅读官方 HttpComponent 文档。
Symfony
Symfony 是一组可重用的 PHP 组件和一个用于 Web 项目的 PHP 框架。 Symfony 于 2005 年发布为免费软件。Symfony 的原始作者是 Fabien Potencier。 Symfony 受到 Spring 框架的极大启发。
在示例中,我们将使用httpbin.org
和http://jsonplaceholder.typicode.com/
在线服务。
$ composer require symfony/http-client
$ composer require symfony/var-dumper
我们安装了HttpClient
和var-dumper
组件。
HttpClient
GET 请求
HTTP 定义了一组请求方法,以指示要对给定资源执行的所需操作。 GET 请求用于从指定资源请求数据。 使用 GET 的请求应仅检索数据,而对数据没有其他影响。
注意:建议使用 HTTP 方法的目的和影响; 这些不是严格的规则。 这就是我们前面说过 GET 方法不应对数据产生影响的原因。 实际上,这并不总是遵循的。
get_request.php
<?php
require('vendor/autoload.php');
use Symfony\Component\HttpClient\HttpClient;
$httpClient = HttpClient::create();
$response = $httpClient->request('GET', 'http://webcode.me');
$statusCode = $response->getStatusCode();
echo $statusCode . "\n";
$contentType = $response->getHeaders()['content-type'][0];
echo $contentType . "\n";
$content = $response->getContent();
echo $content . "\n";
该示例创建HttpClient
,并向指定的网页发出 GET 请求。
注意:响应始终是异步的,因此对方法的调用将立即返回,而不是等待接收响应。 有诸如
getStatusCode()
和getContent()
之类的阻塞方法,它们会等到接收到完整的响应内容为止。
$httpClient = HttpClient::create();
$response = $httpClient->request('GET', 'http://webcode.me');
我们用HttpClient::create()
创建一个HttpClient
。 使用request()
方法生成 GET 请求。
$statusCode = $response->getStatusCode();
echo $statusCode . "\n";
我们使用getStatusCode()
方法获取状态代码。
$contentType = $response->getHeaders()['content-type'][0];
echo $contentType . "\n";
从响应的标题中,我们获得内容类型。
$content = $response->getContent();
echo $content . "\n";
最后,我们使用getContent()
方法获得页面的内容。
$ php get_request.php
200
text/html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My html page</title>
</head>
<body>
<p>
Today is a beautiful day. We go swimming and fishing.
</p>
<p>
Hello there. How are you?
</p>
</body>
</html>
这是输出。
HttpClient
用户代理
创建HttpClient
时,我们可以传递一些选项,例如标头值。
user_agent.php
<?php
require('vendor/autoload.php');
use Symfony\Component\HttpClient\HttpClient;
$httpClient = HttpClient::create(['headers' => [
'User-Agent' => 'PHP console app',
]]);
$response = $httpClient->request('GET', 'https://httpbin.org/user-agent');
echo $response->getContent() . "\n";
我们连接到httpbin.org
网站,该网站是用于测试 HTTP 请求&响应的在线工具。
$httpClient = HttpClient::create(['headers' => [
'User-Agent' => 'PHP console app',
]]);
在标题数组中,我们添加User-Agent
选项。
$response = $httpClient->request('GET', 'https://httpbin.org/user-agent');
我们将 GET 请求发送到https://httpbin.org/user-agent
URL,该 URL 返回请求的用户代理选项。
HttpClient toArray()
toArray()
方法通常将响应主体解码为数组,并从 JSON 有效负载解码为数组。
content_array.php
<?php
require('vendor/autoload.php');
use Symfony\Component\HttpClient\HttpClient;
$httpClient = HttpClient::create();
$response = $httpClient->request('GET',
'https://jsonplaceholder.typicode.com/posts/2/');
dump($response->toArray());
该示例向jsonplaceholder.typicode.com
在线服务网站发出 GET 请求,该网站以 JSON 格式返回 ID 为 2 的帖子。
dump($response->toArray());
我们转储toArray()
方法的输出。
$ php content_array.php
array:4 [
"userId" => 1
"id" => 2
"title" => "qui est esse"
"body" => """
est rerum tempore vitae\n
sequi sint nihil reprehenderit dolor beatae ea dolores neque\n
fugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\n
qui aperiam non debitis possimus qui neque nisi nulla
"""
]
这是输出。
HttpClient
POST 数据
发布请求用于将数据发送到服务器。 数据位于 HTTP 请求的请求正文中。
发布请求永远不会被缓存,它们不会保留在浏览器历史记录中,也无法被添加书签,并且数据长度没有限制。
post_data.php
<?php
require('vendor/autoload.php');
use Symfony\Component\HttpClient\HttpClient;
$httpClient = HttpClient::create();
$response = $httpClient->request('POST', 'https://httpbin.org/post', [
'body' => ['msg' => 'Hello there']
]);
echo $response->getContent();
在示例中,我们在 POST 请求中将消息变量发送到指定的 URL。 在响应对象中,我们找到了 POST 请求中发送的数据。
$ php post_data.php
{
"args": {},
"data": "",
"files": {},
"form": {
"msg": "Hello there"
},
...
}
这是输出。
HttpClient
重定向
URL 重定向是将请求从一页转发到另一页的过程。 当 Web 浏览器尝试打开已重定向的 URL 时,将打开一个具有其他 URL 的页面。 一个 URL 可能有多个重定向。
使用重定向的原因:
- URL 缩短
- 防止在移动网页时断开链接
- 允许属于同一所有者的多个域名引用一个网站
- 隐私保护
- HTTP 到 HTTP 的过渡
- 恶意目的,例如网络钓鱼攻击或恶意软件分发
发出请求时,HttpClient
遵循重定向,最多 20 个。 max_redirects
属性用于配置此行为。 值 0 表示不遵循任何重定向。
redirect.php
<?php
require 'vendor/autoload.php';
use Symfony\Component\HttpClient\HttpClient;
$httpClient = HttpClient::create();
$response = $httpClient->request('GET', 'https://httpbin.org/redirect/4', [
'max_redirects' => 3,
]);
echo $response->getStatusCode();
我们将 GET 请求发送到重定向四次的 URL,同时将max_redirects
属性设置为三。 这意味着我们获得 302 重定向状态代码。 如果我们增加max_redirects
值,我们应该得到 200。
HttpClient
查询参数
查询参数是统一资源定位器(URL)的一部分,该 URL 将值分配给指定的参数。 这是将数据发送到目标服务器的一种方法。
http://example.com/api/users?name=John%20Doe&occupation=gardener
查询参数在?
字符之后指定。&
分隔了多个字段。 特殊字符(例如空格)被编码。 在上面的字符串中,空格用%20
值编码。
Symfony HttpClient
在将值包含在 URL 中之前会自动对其进行编码。
query_params.php
<?php
require('vendor/autoload.php');
use Symfony\Component\HttpClient\HttpClient;
$httpClient = HttpClient::create();
$response = $httpClient->request('GET', 'https://httpbin.org/get', [
'query' => [
'name' => 'John Doe',
],
]);
echo $response->getContent();
我们将name
字段发送到https://httpbin.org/get
URL。 在响应中,我们返回了 URL 参数。
$ php query_params.php
{
"args": {
"name": "John Doe"
},
"headers": {
"Accept-Encoding": "deflate, gzip",
"Host": "httpbin.org",
"User-Agent": "Symfony HttpClient/Curl"
},
...
}
这是输出。
使用 httpbin 的 Docker 容器
httpbin.org
还提供了一个用于测试的 Docker 容器。
$ docker run -p 80:80 kennethreitz/httpbin
我们运行容器。
docker_ex.php
<?php
require 'vendor/autoload.php';
use Symfony\Component\HttpClient\HttpClient;
$httpClient = HttpClient::create();
$response = $httpClient->request('GET', 'http://localhost:80/anything',
[
'json' => ['message' => 'Hello there'],
]);
dump($response->toArray());
在示例中,我们使用 httpbin 的服务连接到容器。 localhost:80/anything
返回传递给请求的任何内容。
HTTP 基本认证
HTTP 基本认证是一种简单的质询和响应机制,其中服务器从客户端请求凭据。 客户端在授权标头中将凭据传递给服务器。 认证信息不以任何方式加密或哈希。 它使用 Base64 算法编码。 因此,仅将 HTTP 基本认证与HTTPS
一起使用才被认为是安全的。
HTTP 基本认证使用 HTTP 标头中的标准字段,从而无需握手。
authenticate.php
<?php
require('vendor/autoload.php');
use Symfony\Component\HttpClient\HttpClient;
$httpClient = HttpClient::create([
'auth_basic' => ['user7', 'passwd']
]);
$response = $httpClient->request('GET',
'https://httpbin.org/basic-auth/user7/passwd');
echo $response->getStatusCode();
dump($response);
在示例中,我们使用 HTTP 基本认证。
$httpClient = HttpClient::create([
'auth_basic' => ['user7', 'passwd']
]);
HTTP 基本认证通过auth_basic
选项指定。 所有请求将使用相同的凭据。
$response = $httpClient->request('GET',
'https://httpbin.org/basic-auth/user7/passwd');
不要与 URL 中的用户名和密码混淆; 这仅用于在 httpbin 的服务中进行测试。
HttpClient
流数据
自 HTTP 1.1 以来,块传输编码是一种流数据传输机制。 在分块传输编码中,数据流被分为一系列不重叠的块。
块彼此独立地发送和接收。 每个块之前都有其大小(以字节为单位)。
在 Symfony HttpClient
中,流传输是通过stream()
完成的。
streaming.php
<?php
require 'vendor/autoload.php';
use Symfony\Component\HttpClient\HttpClient;
$httpClient = HttpClient::create();
$url = 'https://download.freebsd.org/ftp/releases/amd64/amd64/ISO-IMAGES/12.0/FreeBSD-12.0-RELEASE-amd64-mini-memstick.img';
$response = $httpClient->request('GET', $url, [
'buffer' => false,
]);
if (200 !== $response->getStatusCode()) {
throw new \Exception('Failed to create a request');
}
$fileHandler = fopen('freebsd-12.0-amd64-mini-memstick.iso', 'w');
foreach ($httpClient->stream($response) as $chunk) {
fwrite($fileHandler, $chunk->getContent());
}
在示例中,我们下载了 FreeBSD ISO 映像。
$response = $httpClient->request('GET', $url, [
'buffer' => false,
]);
我们创建一个对指定 URL 的 GET 请求; (可选)我们可以关闭内存缓冲。
$fileHandler = fopen('freebsd-12.0-amd64-mini-memstick.iso', 'w');
foreach ($httpClient->stream($response) as $chunk) {
fwrite($fileHandler, $chunk->getContent());
}
我们以块的形式获取响应内容,并将其保存在文件中。
Symfony HttClient
Webapp 示例
在下面的示例中,我们创建一个 Symfony Web 应用,该应用使用HttpClient
生成请求。 我们使用HttpClientInterface
注入HttpClient
。
该应用向https://jsonplaceholder.typicode.com/users
发出 GET 请求,该请求返回十个用户。
$ composer create-project symfony/skeleton symfapp
$ cd symfapp
$ composer require annotations
$ composer require maker server --dev
$ composer require symfony/http-client
我们创建一个新的 Symfony 框架应用并安装一些依赖项。
config/packages/framework.yaml
framework:
...
http_client:
max_host_connections: 5
default_options:
max_redirects: 3
在framework.yaml
文件中,我们可以配置HttpClient
。
$ php bin/console make:controller DataController
我们创建一个新的控制器。
src/Controller/DataController.php
<?php
namespace App\Controller;
use App\Service\UserService;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
class DataController extends AbstractController
{
/**
* @Route("/data", name="data")
*/
public function index(UserService $userService): Response
{
$data = $userService->getUsers();
return $this->json($data);
}
}
DataController
注入UserService
,调用其getUsers()
方法以检索数据。 数据作为 JSON 返回给调用方。
src/Service/UserService.php
<?php
namespace App\Service;
use Symfony\Contracts\HttpClient\HttpClientInterface;
class UserService
{
private $httpClient;
public function __construct(HttpClientInterface $httpClient)
{
$this->httpClient = $httpClient;
}
public function getUsers(): Array
{
$response = $this->httpClient->request('GET',
'https://jsonplaceholder.typicode.com/users');
$data = $response->getContent();
$decoded = json_decode($data);
return $decoded;
}
}
这是UserService.
public function __construct(HttpClientInterface $httpClient)
{
$this->httpClient = $httpClient;
}
我们用HttpClientInterface
注入 HttpClient。
public function getUsers(): Array
{
$response = $this->httpClient->request('GET',
'https://jsonplaceholder.typicode.com/users');
$data = $response->getContent();
$decoded = json_decode($data);
return $decoded;
}
我们生成一个 GET 请求,解码数据并返回它。
$ php bin/console server:run
我们运行该应用并导航到localhost:8000/data
。
在本教程中,我们使用了 Symfony HttpClient
组件。
您可能也对以下相关教程感兴趣: Symfony 简介, Symfony 验证教程, Symfony 服务教程, Symfony 表单教程 , PHP 教程或列出所有 Symfony 教程。