PHPackages                             andy87/knockknock - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [HTTP &amp; Networking](/categories/http)
4. /
5. andy87/knockknock

ActiveLibrary[HTTP &amp; Networking](/categories/http)

andy87/knockknock
=================

PHP Facade Curl library - developed by and\_y87

1.3.0(1y ago)1146CC-BY-SA-4.0PHPPHP &gt;=8.0.0

Since Jun 9Pushed 1y ago1 watchersCompare

[ Source](https://github.com/andy87/knock-knock)[ Packagist](https://packagist.org/packages/andy87/knockknock)[ Docs](https://andy87.ru)[ RSS](/packages/andy87-knockknock/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (1)Dependencies (1)Versions (6)Used By (0)

KnockKnock
==========

[](#knockknock)

[![KnockKnock php curl facade](assets/logo/KnockKnockLogo_256.png)](assets/logo/KnockKnockLogo_256.png)

KnockKnock - это простая библиотека, реализующая Фасад и предоставляющая удобный интерфейс для выполнения запросов в PHP, используя расширение cURL. Она упрощает работу, предоставляя более высокоуровневый API и быстрый доступ к настройкам.

Цель: сделать простой и лёгкий в настройке компонента и запроса пакет.

P.S. я знаю про существование таких библиотек как: [Guzzle](https://github.com/guzzle/guzzle), [Client](https://github.com/yiisoft/yii2-httpclient) *(в моём любимом Yii2)*, но хотелось попробовать создать свою реализацию.
Без "лишних" данных, вызовов и настроек, nullWarningStyle - только то, что нужно: сухо, лаконично, минималистично.
*Разумеется, это не конкурент, а просто попытка создать что-то своё*

### Содержание:

[](#содержание)

- [Установка](#knockknock-setup)
- [Объект - Базовый класс](#knockknock-src-Operator)
- [Объект - Запрос](#knockknock-src-Request)
- [Объект - Ответ](#knockknock-src-Response)
- [Дополнительные возможности](#knockknock-src-feature)
- [Расширение на основе базового класса](#knockknock-extends)
- [Пример Custom реализации](#knockknock-Custom)
- [Тесты](#knockknock-tests)

---

  Установка
------------

[](#-----установка)

### Требования

[](#требования)

 - php 8.0
- ext cURL
- ext JSON

###  [Composer](https://getcomposer.org/download/)

[](#----composer)

 Добавление пакета в проект
--------------------------

[](#добавление-пакета-в-проект)

### Используя: консольные команды. *(Предпочтительней)*

[](#используя-консольные-команды-предпочтительней)

- при composer, установленном локально:

```
composer require andy87/knockknock
```

- при использовании composer.phar:

```
php composer.phar require andy87/knockknock
```

**Далее:** обновление зависимостей `composer update`

### Используя: файл `composer.json`

[](#используя-файл-composerjson)

Открыть файл `composer.json`
В раздел, ключ `require` добавить строку
`"andy87/knockknock": "*"`
**Далее:** обновление зависимостей `composer update`

Используя: подключение авто загрузчика
--------------------------------------

[](#используя-подключение-авто-загрузчика)

В месте, где необходимо использовать библиотеку, подключите авто загрузчик:

```
require_once 'путь/к/корню/проекта/autoload.php';
```

**Примечания:**

- Убедитесь, что путь к autoload.php правильный и соответствует структуре вашего проекта.

\- - - - -

---

Логика работы библиотеки (блок-схема)
-------------------------------------

[](#логика-работы-библиотеки-блок-схема)

  [![логика схемы работы приложения](assets/logicOperator.png)](assets/logicOperator.png)

### Простой пример работы.

[](#простой-пример-работы)

```
use andy87\knock_knock\lib\Method;
use andy87\knock_knock\lib\ContentType;
use andy87\knock_knock\core\Operator;
use andy87\knock_knock\core\Response;

// Получаем компонент реализующий отправку запросов
$operator = new Operator( $_ENV['API_HOST'] )->disableSSL();

/**
 * Краткая форма записи (с не очевидным объектом запроса)
 */
$content = $operator->send( $operator->constructRequest(Method::GET, 'info/me') )->content;

/**
 * Детальная форма записи с дополнительными возможностями
 */
$request = $operator->constructRequest(Method::GET, 'info/me'); // Создаём объект запроса
$request->setCurlInfo([ CURLINFO_CONTENT_TYPE ]); // Назначаем опции cURL
$response = $operator->send($request); // Отправляем запрос и получаем ответ

$content = $response->content; // Получаем данные ответа
$curlOptions = $response->request->curlOptions; // Получаем опции cURL

$output = ( $curlOptions[CURLINFO_CONTENT_TYPE] === ContentType::JSON ) ? json_decode( $content ) : $content;

print_r( $output );
```

\- - - - -

---

Базовый класс
-------------

[](#базовый-класс)

 *use [andy87\\knock\_knock\\core\\Operator](src/core/Operator.php);*

PHP Фасад\\Адаптер для отправки запросов через ext cURL

### ReadOnly свойства:

[](#readonly-свойства)

 - **commonRequest**
    - *Объект содержащий параметры, назначаемые всем исходящим запросам*
- **realRequest**
    - *Используемый запрос*
- **eventHandlers**
    - *Список обработчиков событий*
- **host**
    - *Хост, на который будет отправляться запросы*
- **logs**
    - *Список логов*

Возможности/фичи:

- Настройки параметров запросов
- Защита данных от перезаписи
- Обработчики событий
- Инкапсуляция
- Singleton
- логирование

#### ВАЖНЫЙ МОМЕНТ!

[](#важный-момент)

- В классах применяется инкапсуляция, поэтому для доступа к свойствам компонентов используются ReadOnly свойства.
- `CURL_OPTIONS` по умолчанию пустые! В большинстве случаев, для получения валидных ответов, требуется задать необходимые настройки.

"Получение" объекта/экземпляра класса
-------------------------------------

[](#получение-объектаэкземпляра-класса)

 Передавая параметры напрямую в конструктор:

```
$operator = new Operator( $_ENV['API_HOST'], $commonRequestParams );
```

Применяя, паттерн Singleton:

```
$operator = Operator::getInstance( $_ENV['API_HOST'], $commonRequestParams );
```

Методы возвращают объект(экземпляр класса `Operator`), принимая на вход два аргумента:

- `string $host` - хост
- `array $operatorConfig` - массив с настройками для всех исходящих запросов.

При создании объекта `Operator` будет вызван метод `init()`, который запускает пользовательские инструкции.
После выполнения `init()` запускается обработчик события привязанный к ключу `EVENT_AFTER_CONSTRUCT`

 Общие настройки запросов
--------------------------

[](#--общие-настройки-запросов)

Что бы указать настройки применяемые ко всем исходящим запросам, при создании объекта `Operator` передаётся массив (ключ - значение), с необходимыми настройками. Пример настройки:

```
// настройки для последующих исходящих запросов
$commonRequestParams = [
    Request::SETUP_PROTOCO => $_ENV['API_PROTOCOL'],
    Request::SETUP_CONTENT_TYPE => Request::CONTENT_TYPE_JSON,
    Request::SETUP_CURL_OPTIONS => [
        CURLOPT_HEADER => false,
        CURLOPT_RETURNTRANSFER => true
    ]
];
// Получаем компонент для отправки запросов
$operator = new Operator( $_ENV['API_HOST'], $commonRequestParams );

//Применяя, паттерн Singleton:
$operator = Operator::getInstance( $_ENV['API_HOST'], $commonRequestParams );
```

Доступные ключи для настройки(константы класса `Request`):

- `SETUP_PROTOCOL`
- `SETUP_HOST`
- `SETUP_METHOD`
- `SETUP_HEADERS`
- `SETUP_CONTENT_TYPE`
- `SETUP_DATA`
- `SETUP_CURL_OPTIONS`
- `SETUP_CURL_INFO`

Обработчики событий
-------------------

[](#обработчики-событий)

 ### Список событий

[](#список-событий)

 - `EVENT_AFTER_CONSTRUCT` после создания объекта knockKnock
- `EVENT_CREATE_REQUEST` после создания объекта запроса
- `EVENT_BEFORE_SEND` перед отправкой запроса
- `EVENT_CURL_Operator` перед отправкой curl запроса
- `EVENT_CREATE_RESPONSE` после создания объекта ответа
- `EVENT_AFTER_SEND` после получения ответа

##### Пример установки обработчиков событий

[](#пример-установки-обработчиков-событий)

 ```
$operator->setupEventHandlers([
    Operator::EVENT_AFTER_CONSTRUCT => function( Operator $operator ) {
        // ...
    },
    Operator::EVENT_CREATE_REQUEST => function( Operator $operator, Request $request ) {
        // ...
    },
    Operator::EVENT_BEFORE_SEND => function( Operator $operator, Request $request ) {
        // ...
    },
    Operator::EVENT_CURL_HANDLER => function( Operator $operator, resource $ch ) {
        // ...
    },
    Operator::EVENT_CREATE_RESPONSE => function( Operator $operator, Response $response ) {
        // ...
    },
    Operator::EVENT_AFTER_SEND => function( Operator $operator, Response $response ) {
        // ...
    }
]);
```

Первый аргумент - ключ события, второй - callback функция.

Все callback функции принимают первым аргументом объект/экземпляр класса `Operaotr`.
Вторым аргументом передаётся объект/экземпляр класса в зависимости от события:

- `Request` - для событий `EVENT_CREATE_REQUEST`, `EVENT_BEFORE_SEND`
- `Response` - для событий `EVENT_CREATE_RESPONSE`, `EVENT_AFTER_SEND`

\- - - - -

---

Запрос
======

[](#запрос)

*use [andy87\\knock\_knock\\core\\Request](src/core/Request.php);*

Объект запроса, содержащий данные для отправки запроса.

### ReadOnly свойства:

[](#readonly-свойства-1)

 - **protocol** - *протокол*
- **host** - *хост*
- **endpoint** - *конечная точка*
- **method** - *метод*
- **headers** - *заголовки*
- **contentType** - *тип контента*
- **data** - *данные*
- **curlOptions** - *опции cURL*
- **curlInfo** - *информация cURL*
- **params** - *параметры запроса*
- **url** - *полный URL*
- **params** - *все свойства в виде массива*
- **fakeResponse** - *установленные фэйковые данные ответа*
- **errors** - *лог ошибок*

### Создание объекта запроса

[](#создание-объекта-запроса)

 Передавая параметры напрямую в конструктор:

```
$request = new Request( 'info/me', [
    Request::METHOD => Method::POST,
    Request::DATA => [ 'client_id' => 34 ],
    Request::HEADERS => [ 'api-secret-key' => $_ENV['API_SECRET_KEY'] ],
    Request::CURL_OPTIONS => [ CURLOPT_TIMEOUT => 10 ],
    Request::CURL_INFO => [
        CURLINFO_CONTENT_TYPE,
        CURLINFO_HEADER_SIZE,
        CURLINFO_TOTAL_TIME
    ],
    Request::CONTENT_TYPE => ContentType::FORM_DATA,
]);
```

Методом, который вызывает *callback* функцию, привязанную к ключу `EVENT_CREATE_REQUEST`

```
$request = $operator->constructRequest(Method::GET, 'info/me', [
    Request::METHOD => Method::POST,
    Request::DATA => [ 'client_id' => 45 ],
    Request::HEADERS => [ 'api-secret-key' => $_ENV['API_SECRET_KEY'] ],
    Request::CURL_OPTIONS => [ CURLOPT_TIMEOUT => 10 ],
    Request::CURL_INFO => [
        CURLINFO_CONTENT_TYPE,
        CURLINFO_HEADER_SIZE,
        CURLINFO_TOTAL_TIME
    ],
    Request::CONTENT_TYPE => ContentType::FORM_DATA,
]);
```

Клонируя существующий объект запроса:

```
$request = $operator->constructRequest(Method::GET, 'info/me');

$response = $operator->send($request);

//Клонирование объекта запроса (без статуса отправки)
$cloneRequest = $request->clone();

// Отправка клона запроса
$response = $operator->setupRequest( $cloneRequest )->send();
```

###  Назначение/Изменение/Получение отдельных параметров запроса (set/get)

[](#----назначениеизменениеполучение-отдельных-параметров-запроса-setget)

 Таблица set/get методов для взаимодействия с отдельными свойствами запроса

ПараметрСеттерГеттерИнформацияПротоколsetProtocol( string $protocol )getProtocol(): string[протоколы](https://curl.se/docs/protdocs.html)ХостsetHost( string $host )getHost(): string---EndpointsetEndpoint( string $url )getEndpoint(): string---МетодsetMethod( string $method )getMethod(): string[методы](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods)ЗаголовкиsetHeaders( array $headers )getHeaders(): array[заголовки](https://ru.wikipedia.org/wiki/%D0%A1%D0%BF%D0%B8%D1%81%D0%BE%D0%BA_%D0%B7%D0%B0%D0%B3%D0%BE%D0%BB%D0%BE%D0%B2%D0%BA%D0%BE%D0%B2_HTTP)Тип контентаsetContentType( string $contentType )getContentType(): string[Тип контента](https://ru.wikipedia.org/wiki/%D0%A1%D0%BF%D0%B8%D1%81%D0%BE%D0%BA_MIME-%D1%82%D0%B8%D0%BF%D0%BE%D0%B2)ДанныеsetData( mixed $data )getData(): mixed---Опции cURLsetCurlOptions( array $curlOptions )getCurlOptions(): array[Опции cURL](https://www.php.net/manual/ru/function.curl-setopt.php)Информация cURLsetCurlInfo( array $curlInfo )getCurlInfo(): array[Информация cURL](https://www.php.net/manual/ru/function.curl-getinfo.php)Фэйковый ответsetFakeResponse( array $response )getFakeResponse(): array```
$request = $operator->constructRequest(Method::GET, 'info/me');

$request->setMethod( Method::GET );
$request->setData(['client_id' => 67]);
$request->setHeaders(['api-secret-key' => 'secretKey67']);
$request->setCurlOptions([
    CURLOPT_TIMEOUT => 10,
    CURLOPT_RETURNTRANSFER => true
]);
$request->setCurlInfo([
    CURLINFO_CONTENT_TYPE,
    CURLINFO_HEADER_SIZE,
    CURLINFO_TOTAL_TIME
]);
$request->setContentType( ContentType::JSON );

$protocol = $request->getPrococol(); // String
$host = $request->getHost(); // String
// ... аналогичным образом доступны и другие подобные методы для получения свойств запроса
```

### Назначение запроса с переназначением свойств

[](#назначение-запроса-с-переназначением-свойств)

 ```
$operator->setupRequest( $request, [
    Request::SETUP_HOST => $_ENV['API_HOST'],
    Request::SETUP_HEADERS => [
        'api-secret' => $_ENV['API_SECRET_KEY']
    ],
]);
```

`setupRequest( Request $request, array $options = [] ): self`

##### addError( string $error )

[](#adderror-string-error-)

Добавление ошибки в лог ошибок

```
$request = $operator->constructRequest(Method::GET, 'info/me');

$request->addError('Ошибка!');
```

\- - - - -

---

Ответ
=====

[](#ответ)

*use [andy87\\knock\_knock\\core\\Response](src/core/Response.php);*

Объект ответа, содержащий данные ответа на запрос.

### ReadOnly свойства

[](#readonly-свойства-2)

 - **content**
    - *данные ответа*
- **httpCode**
    - *код ответа*
- **request**
    - *объект запроса, содержащий данные о запросе*
- **curlOptions**
    - *быстрый доступ к request-&gt;curlOptions*
- **curlInfo**
    - *быстрый доступ к request-&gt;curlInfo*

### Создание объекта ответа

[](#создание-объекта-ответа)

 Передавая параметры напрямую в конструктор:

```
$response = new Response('{"id" => 806034, "name" => "and_y87"}', 200 );
```

Методом, который вызывает *callback* функцию, привязанную к ключу `EVENT_CREATE_RESPONSE`

```
$response = $operator->constructResponse([
    Response::CONTENT => [
        'id' => 806034,
        'name' => 'and_y87'
    ],
    Response::HTTP_CODE => 400,
], $request );
```

`constructResponse( array $responseParams, ?Request $request = null ): Response`

Отправка запроса
----------------

[](#отправка-запроса)

 `send( ?Request $request = null ): Response`Вызов возвращает объект/экземпляр класса `Response`.
Срабатывают callback функции, привязанные к ключам:

- `EVENT_AFTER_SEND`
- `EVENT_CREATE_RESPONSE`
- `EVENT_BEFORE_SEND`
- `EVENT_CURL_HANDLER`

```
$operator = new Operator( $_ENV['API_HOST'] );
$request = $operator->constructRequest(Method::GET, 'info/me');
$response = $operator->send($request);

// Аналог
$operator = new Operator( $_ENV['API_HOST'] );
$response = $operator->send( $operator->constructRequest(Method::GET, 'info/me') );
```

Нельзя повторно отправить запрос, выбрасывается исключение `RequestCompleteException`. Для повторной отправки запроса, необходимо создать новый объект запроса и использовать его:

```
$operator = new Operator( $_ENV['API_HOST'] );
$request = $operator->constructRequest(Method::GET, 'info/me');
$response = $operator->send($request);

// повторная отправка запроса
$response = $operator->send($request->clone());
```

Отправка запроса с фэйковым ответом
-----------------------------------

[](#отправка-запроса-с-фэйковым-ответом)

 ```
// параметры возвращаемого ответа
$fakeResponse = [
    Response::HTTP_CODE => 200,
    Response::CONTENT => '{"id" => 8060345, "nickName" => "and_y87"}'
];
$request->setFakeResponse( $fakeResponse );

$response = $operator->send( $request );
```

объект `$response` будет содержать в свойствах `content`, `httpCode` данные переданные в аргументе `$fakeResponse`

Данные в ответе
---------------

[](#данные-в-ответе)

 В созданный объект `Response`, чей запрос не был отправлен, разрешено задавать данные, используя методы группы `set`.

```
$response = $operator->send($request);

$response
    ->setHttpCode(200)
    ->setContent('{"id" => 8060345, "nickName" => "and_y87"}');
```

**Внимание!** Если данные в объекте уже существуют, повторно задать их нельзя выбрасывается `ParamUpdateException`.
В случае необходимости заменить данные, используется вызов метода `replace( string $key, mixed $value )` см. далее

###  Подмена данных

[](#----подмена-данных)

 Это сделано для явного действия, когда необходимо заменить данные в объекте `Response`. ```
$response = $operator->send($request);

$response
    ->replace( Response::HTTP_CODE, 200 )
    ->replace( Response::CONTENT, '{"id" => 8060345, "nickName" => "and_y87"}' );
```

Данные запроса из ответа
------------------------

[](#данные-запроса-из-ответа)

 Для получения из объекта `Response` данных запроса, необходимо обратиться к ReadOnly свойству `request`
и далее взаимодействовать с ним аналогично объекту `Request`

```
$operator = new Operator( $_ENV['API_HOST'] );
$response = $operator->setRequest( $operator->constructRequest(Method::GET, 'info/me') )->send();

// Получение компонента запроса
$request = $response->request;

$method = $request->method; // получение метода запроса
```

Получения свойств cURL запроса

```
$operator = new Operator( $_ENV['API_HOST'] );
$response = $operator->setRequest( $operator->constructRequest(Method::GET, 'info/me') )->send();

$response->request;

// Получение свойств через объект запроса
$curlOptions =  $response->request->curlOption;
$curlInfo =  $response->request->curlInfo;

//Вариант с использованием быстрого доступа
$curlOptions =  $response->curlOption;
$curlInfo =  $response->curlInfo;
```

### asArray()

[](#asarray)

 Преобразование в массив.

- преобразование данных ответа на запрос `asArray()`
- преобразование всего объекта в массив `asArray(true)`

```
$response = $operator->send($request)->asArray(); // $response
$array = $response->content; // Array$response
```

##### addError( string $error )

[](#adderror-string-error--1)

Добавление ошибки в лог ошибок

```
$request = $operator->constructRequest(Method::GET, 'info/me');

$response = $operator->send($request);

$response->addError('Ошибка!');
```

\- - - - -

---

\- - - - -

Дополнительные возможности
==========================

[](#дополнительные-возможности)

 ### SSL

[](#ssl)

 Функционал включения/отключения SSL верификации в объектах `Operaotr` &amp; `Request`.

В `curlOptions` добавляется ключ `CURLOPT_SSL_VERIFYPEER` и `CURLOPT_SSL_VERIFYHOST`.

`->disableSSL( bool $verifyPeer = false, int $verifyHost = 0 );`
`->enableSSL( bool $verifyPeer = true, int $verifyHost = 2 );`

`Operaotr` - для всех запросов

```
$operator = new Operator( $_ENV['API_HOST'] );
$operator->disableSSL();

$request = $operator->constructRequest(Method::GET, 'info/me');

$response = $operator->setupRequest( $request )->send();
```

`Request` - для конкретного запроса

```
$operator = new Operator( $_ENV['API_HOST'] )->disableSSL();

$request = $operator->constructRequest(Method::GET, 'info/me');
$request->enableSSL();

$response = $operator->setupRequest( $request )->send();
```

### Cookie

[](#cookie)

 В объекте `Operaotr` имеется функционал использования cookie.
`Operaotr` - для всех запросов

```
$operator = new Operator( $_ENV['API_HOST'] );

$cookie = $_ENV['COOKIE'];
$jar = $_ENV['COOKIE_JAR'];

$operator->useCookie( $cookie, $jar );
```

`$operator->useCookie( string $cookie, string $jar, ?string $file = null )`
по умолчанию `$file = null` и `$file` приравнивается к `$jar`

### Логирование

[](#логирование)

 Добавление сообщений во внутренний массив `logs`

```
$operator = new Operator( $_ENV['API_HOST'] );

$operator->addLog( 'Какое то сообщение' );
```

`$operator->addLog( string $message )`

\- - - - -

---

\- - - - -

Расширения на основе базового класса
====================================

[](#расширения-на-основе-базового-класса)

###  [ KnockKnockOctopus
 ![KnockKnockOctopus php curl facade](assets/logo/KnockKnockOctopus_320.png) ](docs/KnockKnock/KnockKnockOctopus.md)

[](#------------knockknockoctopus--------------------)

 Класс с функционалом простой реализации отправки запросов и минимальными настройками

#### Доступные методы.

[](#доступные-методы)

 get()post()put()patch()delete()head()options()trace()#### Каждый метод принимает два аргумента:

[](#каждый-метод-принимает-два-аргумента)

 АргументТипОбязательныйОписание$endpointstringДаURL запроса (без хоста)$paramsarrayНетДанные запроса в виде массива*P.S. host задаётся в конструкторе*#### Простой пример использования

[](#простой-пример-использования)

 ```
$knockKnockOctopus = new KnockKnockOctopus($_ENV['API_URL']);

$knockKnockOctopus->get( '/profile', [ 'id' => 806034 ] ); //GET запрос

$knockKnockOctopus->post( '/new', [  //POST запрос
    'name' => 'Новая новость',
    'content' => 'Текст новости'
]);
```

\- - - - -

###  [ KnockKnockSecurity
 ![KnockKnockSecurity php curl facade](assets/logo/KnockKnockSecurity_280.png) ](docs/KnockKnock/KnockKnockSecurity.md)

[](#------------knockknocksecurity--------------------)

 Расширяет класс [KnockKnockOctopus](docs/KnockKnock/KnockKnockOctopus.md), предоставляя доступ к функционалу для простой и
быстрой реализации авторизации, и настройки запросов.

```
$knockKnockSecurity = new KnockKnockSecurity($_ENV['API_URL']);

// Настройка параметров запроса по умолчанию
$knockKnockSecurity
    ->disableSSL()
    ->setupAuthorization( KnockKnockSecurity::TOKEN_BEARER, 'token' )
    ->setupHeaders([ 'X-Api-Key' => $_ENV['X_API_KEY'] ])
    ->setupContentType( ContentType::JSON )
    ->on( Operator::EVENT_AFTER_SEND, function( Operator $operator, Response $response ) =>
    {
        $logFilePath = $_SERVER['DOCUMENT_ROOT'] . '/api_log.txt';

        file_put_contents( $logFilePath, $response->content, FILE_APPEND );
    });

// Получение ответа на запрос методом `patch`
$responsePatch = $knockKnockSecurity->patch( 'product', [
    'price' => 1000
]);

$product = $responsePatch->asArray();

$price = $product['price'];

// Изменение типа контента на `application/json`, для следующего запроса
$knockKnockSecurity->useContentType( ContentType::JSON );

// Отправка POST запроса и получение ответа
$responsePost = $knockKnockSecurity->post( 'category', [
    'name' => 'Фреймворки'
]);

$response = json_decode( $responsePost->content );

$category_id = $response->id;
```

\- - - - -

---

\- - - - -

Custom реализация
=================

[](#custom-реализация)

 Custom реализация Базового класса, к примеру с добавлением логирования работающим "под капотом"

```
class KnockKnockYandex extends Operator
{
    private const LOGGER = 'logger';

    private string $host = 'https://api.yandex.ru/'

    private string $contentType = ContentType::JSON

    private YandexLogger $logger;

    /**
     * @return void
     */
    public function init(): void
    {
        $this->setupYandexLoggerEventHandlers();
    }

    /**
     * @param array $callbacks
     *
     * @return self
     */
    private function setupYandexLoggerEventHandlers( array $callbacks ): self
    {
        $this->on( self::AFTER_CREATE_REQUEST, function( Request $request ) =>
        {
            $logData = $this->getLogDataByRequest( $request );

            $this->addYandexLog( $logData );
        };

        $this->on(self::EVENT_AFTER_SEND, function( Response $response ) =>
        {
            $logData = $this->getLogDataByRequest( $response->request );

            $this->addYandexLog( $logData );
        };
    }

    /**
      * @param Request $request
      *
      * @return array
      */
    private function getLogDataByRequest( Request $request ): array
    {
        return $request->getParams();
    }

    /**
     * @param array $logData
     *
     * @return void
     */
    private function addYandexLog( array $logData ): bool
    {
        return $logger->log( $logData );
    }
}
```

###  Пример использования custom реализации

[](#----пример-использования-custom-реализации)

 ```
$knockKnockYandex = KnockKnockYandex::getInstanсe( $_ENV['API_HOST'], [
    KnockKnockYandex::LOGGER => new YandexLogger(),
]);

$response = $knockKnockYandex->setupRequest( 'profile', [
    Request::METHOD => Method::PATCH,
    Request::DATA => [ 'city' => 'Moscow' ],
]); // Логирование `afterCreateRequest`

$response = $knockKnockYandex->send(); // Логирование `afterSend`
```

\- - - - -

---

\- - - - -

Тесты
-----

[](#тесты)

 - tests: 100+
- assertions: 350+

###  Запуск тестов:

[](#----запуск-тестов)

 Нативный

```
vendor/bin/phpunit
```

Информационный

```
vendor/bin/phpunit --testdox
```

С логированием

```
vendor/bin/phpunit --log-junit "tests/logs/phpunit.xml"
```

Лицензия
--------

[](#лицензия)

  под лицензией CC BY-SA 4.0
Для получения дополнительной информации смотрите
Свободно для не коммерческого использования
С указанием авторства для коммерческого использования

[Packagist](https://packagist.org/packages/andy87/knockknock)

###  Health Score

27

—

LowBetter than 49% of packages

Maintenance32

Infrequent updates — may be unmaintained

Popularity12

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity49

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

708d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/548115774b8d117de69e58a5c7759f93d4cfcb37251e4eda2a41f46da85497b0?d=identicon)[andy87](/maintainers/andy87)

---

Top Contributors

[![andy87](https://avatars.githubusercontent.com/u/4658489?v=4)](https://github.com/andy87 "andy87 (158 commits)")

---

Tags

apiapi-clientapi-gatewayapi-wrappercurlcurl-librarycurlphphttpclientphpphp-libraryphp8phpcurlfacadeknock-knockand\_y87knockknock

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/andy87-knockknock/health.svg)

```
[![Health](https://phpackages.com/badges/andy87-knockknock/health.svg)](https://phpackages.com/packages/andy87-knockknock)
```

###  Alternatives

[stefangabos/zebra_curl

A high performance solution for making multiple HTTP requests concurrently, asynchronously from your PHP projects using cURL

21971.3k2](/packages/stefangabos-zebra-curl)[ismaeltoe/osms

PHP library wrapper of the Orange SMS API.

4540.0k](/packages/ismaeltoe-osms)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
