rnr1721 / le7-api-request
le7 PHP MVC 框架或任何 PSR 项目的 API 客户端
Requires
- php: >=8.1
- psr/event-dispatcher: ^1.0
- psr/http-client: ^1.0
- psr/http-factory: ^1.0
- psr/http-message: ^2.0
Requires (Dev)
- nyholm/psr7: ^1.8
- php-http/mock-client: ^1.6
- phpunit/phpunit: ^10.0
- rnr1721/psr7-server: ^1.0
- vimeo/psalm: ^5.7
Suggests
- rnr1721/le7-http-client: Suggests installing a package that provides a compatible implementation of the PSR-18 ClientInterface for making HTTP requests. You can choose any compatible package that suits your needs.
README
le7 PHP MVC 框架或任何 PSR 项目的 API 客户端 这是一个简单的 PSR API 客户端实现
API 请求工具
此项目提供了一种简单的工具,用于简单地向 API 发送 HTTP 请求。它包括一个工厂类,用于创建 API 请求工具的实例。
它没有自己的 PSR ClientInterface 实现,您可以使用任何自己的。例如: https://github.com/rnr1721/le7-http-client
它能做什么?
- 使用任何 API 创建请求,创建 GET、POST、PUT、DELETE 请求
- 允许从响应中获取 ResponseInterface、数组或对象
- 内置将 JSON、XML 和 CSV 响应转换为对象或数组的转换器
- 允许创建从 ResponseInterface 到您的数据的自定义转换器
- 允许预定义设置以使用 DI 容器运行
- 使用不同的 httpClient (ClientInterface),在它们之间切换
- 获取最后请求的数据
- 使用事件,例如用于记录请求
- 设置全局头部和每个请求的头部
- 完全 PSR 兼容
要求
- PHP 8.0 或更高版本
- Composer(用于安装依赖项)
安装
- 通过 composer 安装
composer require rnr1721/le7-api-request
测试
composer test
用法
在此示例中,我使用 Nyholm PSR 库,但您可以使用任何其他库,例如 Guzzle。您还需要 ClientInterface 实现。我使用此实现: https://github.com/rnr1721/le7-http-client
use Core\Factories\HttpClientFactory; use Nyholm\Psr7\Factory\Psr17Factory; // Create PSR factories. Nyholm realisation is a single factory to all $psr17Factory = new Psr17Factory(); // Create httpClient (PSR ClientInterface implementation) $httpClient = new HttpClientFactory($psr17Factory); $factory = new HttpClientFactory( $psr17Factory, // UriFactoryInterface $psr17Factory, // RequestFactoryInterface $psr17Factory, // ResponseFactoryInterface $psr17Factory, // StreamFactoryInterface $httpClient // ClientInterface implementation ); $apiRequest = $factory->getApiRequest() $data = [ // Request data here ]; $headers = [ 'content-language' => 'ru' ]; // Get ResponseInterface for POST request $apiRequest->post('https://example.com/api', $data, $headers)->getResponse(); // Get array for GET request $apiRequest->get('https://example.com/api')->toArray(); // Get object for PUT request $apiRequest->put('https://example.com/api')->toObject(); // Get ResponseInterface for PUT request // You can use request() method for any request $apiRequest->request('PUT','https://example.com/api')->getResponse(); // Get array from response $apiRequest->request('POST','https://example.com', $data, $headers)->toArray(); // Get object from response $apiRequest->request('POST', 'https://example.com', $data, $headers)->toObject(); // This will return ResponseInterface of request $apiRequest->getResponse('POST', 'https://example.com', $data, $headers); // You can set Uri separately if you need it $apiRequest->setUri('https://example.com'); $apiRequest->getResponse('POST', null, $data, $headers); $apiRequest->get(); // Make something // Get last created request $apiRequest->getLast()->toArray();
头部
您可以使用全局头部,以及每个请求的头部。您可以在调用它时通过请求方法注入每个请求的头部,或通过 setHeader() & setHeaders() 方法。现在,您将看到如何设置全局头部,它将为所有请求添加
$headers = [ 'My-Great-Header' => 'header_value' // Array with headers ] // Set many headers for all requests in future $apiRequest->setGlobalHeaders($headers); // Set one global permanent header $apiRequest->setGlobalHeader('Content-Language', 'en');
也可以为一次性请求设置头部
$headers = [ 'My-Great-Header' => 'header_value' // Array with headers ] // Set many headers for next request only $apiRequest->setHeaders($headers); // Set one header for next request only $apiRequest->setHeader('Content-Language', 'en'); // Also you can set one-time header in method: $apiRequest->get('https://example.com', null, $headers);
发送文件使用 multipart/form-data
$data = [ 'name' => 'John Doe', 'email' => 'john.doe@example.com', 'file' => new SplFileInfo('/path/to/file.jpg') ]; $apiRequest->setContentType('multipart/form-data'); $response = $apiRequest->post('/upload', $data);
客户端设置
如果您使用的是我的 ClientInterface 实现, https://github.com/rnr1721/le7-http-client 您可以设置一些客户端选项
$apiRequest->setTimeout(5); //default 10 $apiRequest->setMaxRedirects(5); // Default is 3 $apiRequest->setFollowLocation(false); // Default is true
JSON 和 form-data
您可以创建这些请求的内容类型
- application/json
- application/x-www-form-urlencoded
- multipart/form-data
默认为 json,但您可以切换到 form-data
// This is content type for requests, // Default is application/json $apiRequest->setContentType('multipart/form-data')
另一种方法是设置头部。这将自动切换到针模式
转换器
默认情况下,您可以将接收到的 ResponseInterface 转换为数组或对象,如下所示
// Get array from response $apiRequest->request('POST', 'https://example.com', $data, $headers)->toArray();
// Get array from response $apiRequest->request('POST', 'https://example.com', $data, $headers)->toObject();
您还可以编写自己的转换器。它必须实现 ResponseConvertorInterface
<?php namespace Core\Interfaces; use Psr\Http\Message\ResponseInterface; interface ResponseConvertorInterface { public function get(?ResponseInterface $response = null): mixed; }
例如,您可以看到 ResponseArrayConverter 和 ResponseObjectConverter
您还可以在创建 ApiRequest 实例时注入转换器
$factory = new HttpClientFactory( $psr17Factory, // UriFactoryInterface $psr17Factory, // RequestFactoryInterface $psr17Factory, // ResponseFactoryInterface $psr17Factory, // StreamFactoryInterface $httpClient, // ClientInterface implementation ); // $convertor is ResponseConvertor instance $apiRequest = $factory->getApiRequest(null, $convertor);
多个 HTTP 客户端
您可以在不同的场景中使用不同的 ClientInterface。任何客户端都有自己的密钥。当您创建 ApiRequest 实例时,注入的 ClientInterface 的密钥为 'default'。由于某些原因,您可能需要添加 ClientInterface 实例。因此,您可以这样做
// We have created instance $newHttpClient; // ClientInterface // Add new ClientInterface and make it active $apiRequest->addHttpClient('new key', $newHttpClient, true); // Make our requests // Switch to default ClientInterface $apiRequest->setActiveHttpClient('default');
Uri 前缀
您可以通过两种方式设置 Uri 前缀以添加到所有 URL 之前
在创建 ApiRequest 实例时
$factory = new HttpClientFactory( $psr17Factory, // UriFactoryInterface $psr17Factory, // RequestFactoryInterface $psr17Factory, // ResponseFactoryInterface $psr17Factory, // StreamFactoryInterface $httpClient // ClientInterface implementation ); // $convertor is ResponseConvertor instance $apiRequest = $factory->getApiRequest('https://example.com'); // And now you can use it -it will be https://example.com/contacts/get $result = $apiRequest->setUri('/contacts/get')->get();
当您已经创建了实例
$apiRequest->setUriPrefix('https://example.com');
容器配置
在此示例中,我使用这些组件,但您可以使用任何其他组件
- 托比·诺尔姆 PSR-message 实现 https://github.com/Nyholm/psr7
- PHP-Di 依赖注入容器 https://php-di.org/
- 我对 ClientInterface 的实现 https://github.com/rnr1721/le7-http-client
- 可选:如果需要记录日志或其他操作,可以使用一些 PSR 事件调度器
<?php use Core\Interfaces\ApiRequestInterface; use Nyholm\Psr7\Factory\Psr17Factory; use Core\Factories\HttpClientFactory; use Core\Interfaces\HttpClientFactoryInterface; use Psr\Http\Client\ClientInterface; use Psr\Container\ContainerInterface; use function DI\factory; return [ ApiRequestInterface::class => factory(function (ContainerInterface $c) { /** @var HttpClientFactoryInterface $factory */ $factory = $c->get(HttpClientFactoryInterface::class); return $factory->getApiRequest('https://example.com/api'); }), HttpClientFactoryInterface::class => factory(function (ContainerInterface $c) { /** @var Psr17Factory $psr17factory */ $psr17factory = $c->get(Psr17Factory::class); return new HttpClientFactory( $psr17factory, // UriFactoryInterface $psr17factory, // RequestFactoryInterface $psr17factory, // ResponseFactoryInterface $psr17factory // StreamFactoryInterface $c->get(ClientInterface::class) // ClientInterface ); }), ClientInterface::class => factory(function (ContainerInterface $c) { /** @var Psr17Factory $psr17factory */ $psr17factory = $c->get(Psr17Factory::class); return new \Core\HttpClient\HttpClientCurl($psr17factory); }) ];
PSR 事件
您可以使用事件 AfterApiRequestEvent 来记录请求或以其他方式使用
use Core\Factories\HttpClientFactory; use Core\Events\AfterApiRequestEvent; use Psr\EventDispatcher\EventDispatcherInterface; use Nyholm\Psr7\Factory\Psr17Factory; // Create PSR factories. Nyholm realisation is a single factory to all $psr17Factory = new Psr17Factory(); $factory = new HttpClientFactory( $psr17Factory, // UriFactoryInterface $psr17Factory, // RequestFactoryInterface $psr17Factory, // StreamFactoryInterface $httpClient, // ClientInterface implementation if not default ); $apiRequest = $factory->getApiRequest(); // Register the AfterApiRequestEvent $eventDispatcher->addListener(AfterApiRequestEvent::class, function (AfterApiRequestEvent $event) { // Processing event, for example logging $response = $event->getResponse(); $method = $event->getMethod(); $uri = $event->getUri(); $data = $event->getData(); $headers = $event->getHeaders(); // log response // ... }); // Send the request and get response $response = $apiRequest->request('GET', 'https://example.com');