TLDR;
Есть простой способ зарегистрировать все запросы Guzzle, передав второй параметр Client, после чего он будет регистрировать все запросы. Но это некрасиво, если у вас есть много методов, использующих Guzzle Client для отправки запроса на сторонний сервер. Я сделал это с помощью сервисного контейнера Laravel.
Долгий путь через сервисный контейнер Laravel
Когда я использовал клиент Guzzle в своем проекте и использовал обработчик для регистрации всех запросов, он выглядел хорошо. Но позже было много методов во многих разных классах, поэтому мне приходилось везде писать логику логгера. Затем я подумал, почему бы не использовать Laravel Service Container, привязать объект один раз и использовать его везде.
Вот как я это сделал. В вашем методе загрузки AppServiceContainer.php
мы добавим весь наш код. А затем в контроллерах мы будем использовать наш объект Client.
Добавьте эти операторы использования поверх файла AppServiceContainer.php
.
use GuzzleHttp\Client;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\MessageFormatter;
use GuzzleHttp\Middleware;
use Illuminate\Support\ServiceProvider;
use Monolog\Handler\RotatingFileHandler;
use Monolog\Logger;
Добавьте приведенный ниже код в метод boot
вашего AppServiceContainer.php.
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
$this->app->bind('GuzzleClient', function () {
$messageFormats = [
'REQUEST: {method} - {uri} - HTTP/{version} - {req_headers} - {req_body}',
'RESPONSE: {code} - {res_body}',
];
$stack = HandlerStack::create();
collect($messageFormats)->each(function ($messageFormat) use ($stack) {
// We'll use unshift instead of push, to add the middleware to the bottom of the stack, not the top
$stack->unshift(
Middleware::log(
with(new Logger('guzzle-log'))->pushHandler(
new RotatingFileHandler(storage_path('logs/guzzle-log.log'))
),
new MessageFormatter($messageFormat)
)
);
});
return function ($config) use ($stack){
return new Client(array_merge($config, ['handler' => $stack]));
};
});
}
Объяснение
Если вы заметили приведенный выше код, в первой строке метода загрузки мы сообщаем Laravel, что хотим зарегистрировать этот код как GuzzleClient в вашем сервисном контейнере.
В последнем операторе return мы возвращаем функцию, которая примет один аргумент $config
. Мы использовали эту функцию в качестве прокси, чтобы мы могли передать ей аргумент и использовать его в клиентском объекте.
return function ($config) use ($stack){
return new Client(array_merge($config, ['handler' => $stack]));
};
Остальная часть кода создает объект-обработчик Guzzle для записи всех запросов в файл с именем guzzle-log.log
с использованием объекта Logger библиотеки Monolog. Если у вас включены ежедневные журналы, к имени файла будет добавлена дата, например guzzle-log-2019-08-11.log
. Применение
Мы привязали наш объект к сервисному контейнеру, теперь пришло время использовать этот контейнер везде в нашем коде и сделать его чистым.
В демонстрационных целях я использовал его непосредственно в файле routes/web.php
. Вы можете использовать где угодно.
Route::get('/', function () {
$client = app('GuzzleClient')(['base_uri' => 'http://httpbin.org/']);
$request = $client->get('get',[
'query' => ['foo'=>'bar', 'baz' => 'baz2'] ,
'headers' => [ 'accept' => 'application/json']
]);
$response = json_decode((string) $request->getBody());
return response()->json($response);
});
Как видите, я создаю объект $client
с помощью помощника app()
. Также вы можете передать любой допустимый массив аргументов, который поддерживает клиент Guzzle, в качестве второго параметра. Здесь я прошел base_uri
.
Источник: http://shyammakwana.me/laravel/laravel-log-guzzle-requests-to-file-using-service-container.html
person
shyammakwana.me
schedule
17.08.2019