PHPackages                             ioncurly/vetmanager-api-gateway - 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. [API Development](/categories/api)
4. /
5. ioncurly/vetmanager-api-gateway

ActiveLibrary[API Development](/categories/api)

ioncurly/vetmanager-api-gateway
===============================

Vetmanager API Gateway

2.4.1(1y ago)0189↓100%2[1 issues](https://github.com/ionov-e/vetmanager-api-gateway/issues)[2 PRs](https://github.com/ionov-e/vetmanager-api-gateway/pulls)GPL-3.0-or-laterPHPPHP &gt;=8.1CI passing

Since Apr 19Pushed 5mo ago1 watchersCompare

[ Source](https://github.com/ionov-e/vetmanager-api-gateway)[ Packagist](https://packagist.org/packages/ioncurly/vetmanager-api-gateway)[ Docs](https://github.com/ionov-e/vetmanager-api-gateway)[ RSS](/packages/ioncurly-vetmanager-api-gateway/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (10)Dependencies (8)Versions (41)Used By (0)

Vetmanager Api Gateway
======================

[](#vetmanager-api-gateway)

[![Vetmanager Logo](https://camo.githubusercontent.com/a84f3689e4f805f404bf7804e87ae0b534ffb0e77f60f88acde9307bcf893bcb/68747470733a2f2f7665746d616e616765722e72752f77702d636f6e74656e742f7468656d65732f7665746d616e616765722f696d616765732f6865616465724c6f676f2e737667)](https://camo.githubusercontent.com/a84f3689e4f805f404bf7804e87ae0b534ffb0e77f60f88acde9307bcf893bcb/68747470733a2f2f7665746d616e616765722e72752f77702d636f6e74656e742f7468656d65732f7665746d616e616765722f696d616765732f6865616465724c6f676f2e737667)

[![CI](https://github.com/ionov-e/vetmanager-api-gateway/actions/workflows/ci.yml/badge.svg)](https://github.com/ionov-e/vetmanager-api-gateway/actions/workflows/ci.yml)[![SonarCloud](https://camo.githubusercontent.com/11c08fbf12783d58be12eeb65fb6cd003bcff41e9a5c3664b411f17cd630ca16/68747470733a2f2f736f6e6172636c6f75642e696f2f6170692f70726f6a6563745f6261646765732f6d6561737572653f70726f6a6563743d696f6e6f762d655f7665746d616e616765722d6170692d67617465776179266d65747269633d616c6572745f737461747573)](https://sonarcloud.io/summary/new_code?id=ionov-e_vetmanager-api-gateway)[![Coverage](https://camo.githubusercontent.com/17aaf6a58b6f66dcda2da7e24422043ef9bd6260f7bd7184ddbb9f5f74f918cd/68747470733a2f2f736f6e6172636c6f75642e696f2f6170692f70726f6a6563745f6261646765732f6d6561737572653f70726f6a6563743d696f6e6f762d655f7665746d616e616765722d6170692d67617465776179266d65747269633d636f766572616765)](https://sonarcloud.io/summary/new_code?id=ionov-e_vetmanager-api-gateway)[![Bugs](https://camo.githubusercontent.com/ac063e418fd5c927d08526110350e2bc970400d29f041480446bb39190740863/68747470733a2f2f736f6e6172636c6f75642e696f2f6170692f70726f6a6563745f6261646765732f6d6561737572653f70726f6a6563743d696f6e6f762d655f7665746d616e616765722d6170692d67617465776179266d65747269633d62756773)](https://sonarcloud.io/summary/new_code?id=ionov-e_vetmanager-api-gateway)[![Code Smells](https://camo.githubusercontent.com/ad0146a0e6a315b751aa01c90cec6092a61fba583db34df11cba90e79b91f494/68747470733a2f2f736f6e6172636c6f75642e696f2f6170692f70726f6a6563745f6261646765732f6d6561737572653f70726f6a6563743d696f6e6f762d655f7665746d616e616765722d6170692d67617465776179266d65747269633d636f64655f736d656c6c73)](https://sonarcloud.io/summary/new_code?id=ionov-e_vetmanager-api-gateway)[![PHP Version](https://camo.githubusercontent.com/1f28f2b4faa0e0f1224d8870dbbc65deeea67e3391cd0be5ca39bb23feddf1cc/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048502d382e312b2d3737374242343f6c6f676f3d706870266c6f676f436f6c6f723d7768697465)](https://www.php.net/)[![License](https://camo.githubusercontent.com/1da42cac5e225b91d17ee3c0c7f33bb8f215a907fa3d16e7658576bbc6261349/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d47504c2d2d332e302d2d6f722d2d6c617465722d626c75652e737667)](https://spdx.org/licenses/GPL-3.0-or-later.html)

Помощник для работы с АПИ Ветменеджера. Берет на себя:

1. авторизация;
2. получение данных и представление их в виде объектов и типизированных свойств этих объектов;
3. удобное получения связанных моделей с помощью методов полученных объектов (моделей);
4. отправка новых моделей, редактирование, удаление;
5. удобство для реализации кеширования: возможность предоставление модели в виде массива, и создание модели из массива;
6. унификация работы с моделями вне зависимости от способа получения.

[Используется в основе библиотека для составления Query для АПИ-запросов Vetmanager](https://github.com/otis22/vetmanager-rest-api) - тут же документация к использованию классов для сложных АПИ-запросов: Builder и PagedQuery

[Vetmanager REST API Docs](https://help.vetmanager.cloud/article/3029)

[Vetmanager REST API Postman Collection](https://www.postman.com/vetmanager/workspace/vetmanager-api/collection/23836400-17133b76-0f52-4bb4-8b38-28a64781074e)

[Официальный сайт Vetmanager.ru](https://vetmanager.ru/)

Для чего?
---------

[](#для-чего)

С помощью этой библиотеки удобно получать данные с АПИ Ветменеджера. Данные приходят в виде Active Records. Каждый Active Record связан с одним или с несколькими другими Active Records. Пример кода:

```
$apiGateway = VetmanagerApiGateway\ApiGateway::fromSubdomainAndApiKey('subDomain', 'apiKey', true);
$invoice = $apiGateway->getInvoice()->getById(7);      // Получение модели Счета по ID 7
$invoiceDiscount = $invoice->getDiscount();            // Получение скидки из Счета
$petBreedTitle = $invoice->getPetBreed()->getTitle();  // Получение названия типа питомца из счета
$pet = $invoice->getPet();                             // Получение модели Питомца из Счета
$petAlias = $pet->getAlias();                          // Получение клички Питомца из Счета
```

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

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

```
composer require ioncurly/vetmanager-api-gateway
```

Короткое оглавление
-------------------

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

- [Начало работы/Конфигурация подключения](#header_connection)
- [Первоначальное получение объектов](#header_get)
    1. [По ID](#get_by_id)
    2. [Всех](#get_all)
    3. [По Query](#get_by_query)
    4. [Другими способами](#get_by_custom)
- [Создание новых моделей](#header_post)
    1. [С помощью фасада и массива](#post_with_facades)
    2. [С помощью Active Record и сеттеров](#post_with_active_records)
- [Редактирование моделей](#header_put)
    1. [С помощью фасада и массива](#put_with_facades)
    2. [С помощью Active Record и сеттеров](#put_with_active_records)
- [Удаление моделей](#header_delete)
    1. [С помощью фасада и массива](#delete_with_facades)
    2. [С помощью Active Record и сеттеров](#delete_with_active_records)
- [Пример представления данных](#header_dtos)
- [Связанные запросы](#header_interconnections)
- [Работа как с первоначальными массивами, кэширование](#header_decoded_json)
- [Дополнительные особенности](#header_additional)
    1. [Объект FullName](#additional_full_name)
    2. [Объект FullPhone](#additional_full_phone)
    3. [Возможность онлайн записи в клинике](#additional_online_sign_up)
- [Немного об устройстве библиотеки](#additional_info)

Подробное использование:
------------------------

[](#подробное-использование)

### Начало работы/Конфигурация подключения

[](#начало-работыконфигурация-подключения-)

Простыми словами, объект ApiGateway - связующее звено с работой с АПИ Ветменеджера. Больше ничего создавать не нужно будет

1. С помощью субдомена и АПИ ключа ```
    $subDomain = 'kras-best';   // субдомен клиники в ветменеджер
    $apiKey = 'xXdfxfsfsdffsf'; // АПИ ключ к домену в ветменеджер
    $isProduction = true;       // рабочий или тестовый сервер будет использоваться
    $apiGateway = VetmanagerApiGateway\ApiGateway::fromSubdomainAndApiKey($subDomain, $apiKey, $isProduction);
    ```
2. С помощью полного пути к серверу и АПИ ключа ```
    $apiGateway = VetmanagerApiGateway\ApiGateway::fromFullUrlAndApiKey('https://xxx', 'apiKey', true);
    ```
3. С помощью субдомена, имени АПИ-сервиса и АПИ ключа (для специальных внутренних сервисов) ```
    $apiGateway = VetmanagerApiGateway\ApiGateway::fromSubdomainAndServiceNameAndApiKey('subDomain', 'serviceName', 'apiKey', true);
    ```
4. С помощью полного пути к серверу, имени АПИ-сервиса и АПИ ключа (для специальных внутренних сервисов) ```
    $apiGateway = VetmanagerApiGateway\ApiGateway::fromFullUrlAndServiceNameAndApiKey('https://xxx', 'serviceName', 'apiKey', true);
    ```

### Первоначальное получение объектов

[](#первоначальное-получение-объектов-)

Вся логика получения **Active Record** вынесена в соответсвующий **Facade**. Вот пример получения клиента по ID:

```
$apiGateway = VetmanagerApiGateway\ApiGateway::fromSubdomainAndApiKey('subDomain', 'apiKey', true);
$clientFacade = $apiGateway->getClient(); // выделение фасада в переменную лишь для наглядности
$client = $clientFacade->getById(33);
```

То есть в этой библиотеке для каждого вида **Active Record** существует свой **Facade**. В **Facade** выделена логика работы АПИ-запросов и получения из ответов **Active Record**. Например, в **Facade** для **Active Record** Client содержится метод получения соответствующего **Active Record** по ID. Так же в **Facade** содержатся и другие методы получения (в том числе - через более сложные запросы - например, через фильтры).

Существуют **Active Records**, которые могут быть получены лишь с помощью конкретного АПИ-запроса. Например, MedicalCardByClient можно получить лишь по ID клиента. Недоступные методы получения в соответствующем фасаде просто не существуют

```
$apiGateway = VetmanagerApiGateway\ApiGateway::fromSubdomainAndApiKey('subDomain', 'apiKey', true);
$medicalCards = $apiGateway->getMedicalCardByClient()->getByClientId(33);
```

#### Получение объекта по ID

[](#получение-объекта-по-id-)

```
$apiGateway = VetmanagerApiGateway\ApiGateway::fromSubdomainAndApiKey('subDomain', 'apiKey', true);
$client = $apiGateway->getClient()->getById(33);
```

#### Получение всех объектов

[](#получение-всех-объектов-)

Всегда возвращает массив моделей. Даже когда 1 объект получаем - обращаемся к нему через массив.

```
$apiGateway = VetmanagerApiGateway\ApiGateway::fromSubdomainAndApiKey('subDomain', 'apiKey', true);
$invoices = $apiGateway->getInvoice()->getAll(maxLimitOfReturnedModels: 20); // В параметре можем дописать лимит возвращаемых моделей (иначе 100 по умолчанию)
if (!empty($invoices)) {
    $invoiceDescription = $invoices[0]->getDescription();
}
```

#### Получение объекта по Query запросу

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

Точно так же как и получение всех моделей, Query запросы всегда возвращают массив объектов. То есть даже когда 1 объект возвращается - обращаемся к нему через массив.

Ниже перечислены 3 варианта одного и того же запроса

1. С помощью **Query Builder**

    [Ссылка на используемую библиотеку с большим количество примеров использования Builder](https://github.com/otis22/vetmanager-rest-api)

    ```
    $apiGateway = VetmanagerApiGateway\ApiGateway::fromSubdomainAndApiKey('subDomain', 'apiKey', true);
    $comboManualItems = $apiGateway->getComboManualItem()->getByQueryBuilder(
            (new Otis22\VetmanagerRestApi\Query\Builder())
                ->where('value', '7')
                ->where('combo_manual_id', '1'),
            1 // Опциональный параметр - лимит возвращаемых моделей
    );
    ```
2. С помощью **PagedQuery**

    [Ссылка на используемую библиотеку с большим количество примеров использования PagedQuery](https://github.com/otis22/vetmanager-rest-api)

    С помощью этого объекта удобнее работать с пагинацией.

    ```
    $apiGateway = VetmanagerApiGateway\ApiGateway::fromSubdomainAndApiKey('subDomain', 'apiKey', true);
    $comboManualItems = $apiGateway->getComboManualItem()->getByPagedQuery(
            (new Otis22\VetmanagerRestApi\Query\Builder())
                ->where('value', '7')
                ->where('combo_manual_id', '1')
                ->top(1) // Лимит возвращаемых моделей
    );
    ```
3. С помощью **Get Parameters** в виде строки

    Сюда можно передать все те же Get-параметры, используемые в коллекции Postman. Более подробно о фильтрах, сортировке и т.д. здесь - [Vetmanager REST API Docs](https://help.vetmanager.cloud/article/3029)

    ```
    $apiGateway = VetmanagerApiGateway\ApiGateway::fromSubdomainAndApiKey('subDomain', 'apiKey', true);
    $comboManualItems = $apiGateway->getComboManualItem()->getByGetParametersAsString(
            "filter=[{'property':'combo_manual_id', 'value':'1'},{'property':'value', 'value':'7'}]&limit=1"
    );
    ```

#### Альтернативные способы получения для конкретных моделей

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

```
use VetmanagerApiGateway\DTO\ComboManualName\NameEnum;
$apiGateway = VetmanagerApiGateway\ApiGateway::fromSubdomainAndApiKey('subDomain', 'apiKey', true);
$clinicLanguage = $apiGateway->getProperty()->getByClinicIdAndPropertyName($clinicId = 13, $property = 'lang')->getTitle();
$clientMedicalCards = $apiGateway->getMedicalCardByClient()->getByClientId(77);
$petVaccinations = $apiGateway->getMedicalCardAsVaccination()->getByPetId(11);
$admissionType = $apiGateway->getComboManualItem()->getByAdmissionTypeId(11);
$admissionTypeTitle = $admissionType->getTitle(); // Пример использования содержимого модели
$result = $apiGateway->getComboManualItem()->getByAdmissionResultId(11);
$petColor = $apiGateway->getComboManualItem()->getByPetColorId(11);
$vaccineType = $apiGateway->getComboManualItem()->getByVaccineTypeId(11);
$admissionResult13 = $apiGateway->getComboManualItem()->getOneByValueAndComboManualName(13, NameEnum::AdmissionResult);
$admissionResultManual = $apiGateway->getComboManualName()->getByNameAsString('admission_result');
$admissionResultManualId = $apiGateway->getComboManualName()->getIdByNameAsString('admission_result');
$admissionResultManual = $apiGateway->getComboManualName()->getByNameAsEnum(NameEnum::AdmissionResult);
$admissionResultManualId = $apiGateway->getComboManualName()->getIdByNameAsEnum(NameEnum::AdmissionResult);
$clientAdmissions = $apiGateway->getAdmission()->getByClientId(40);
$petAdmissions = $apiGateway->getAdmission()->getByPetId(88);
```

### Создание новых моделей

[](#создание-новых-моделей-)

#### С помощью фасада и массива

[](#с-помощью-фасада-и-массива-)

```
$apiGateway = VetmanagerApiGateway\ApiGateway::fromSubdomainAndApiKey('subDomain', 'apiKey', true);

// Отправляет новый город и возвращает объект (соответствующий Active Record) с созданной моделью от АПИ
$newCity = $apiGateway->getCity()->createNewUsingArray(["title" => "New City", "type_id" => "1"]);
echo $newCity->getId(); // Получим новый присвоенный ID. Можно и другие свойства так же получить
```

#### С помощью Active Record и сеттеров

[](#с-помощью-active-record-и-сеттеров-)

```
$apiGateway = VetmanagerApiGateway\ApiGateway::fromSubdomainAndApiKey('subDomain', 'apiKey', true);
$newEmptyCity = $apiGateway->getCity()->getNewEmpty();
$cityWithSetValues = $newEmptyCity->setTitle("New City")->setTypeId(1);
$newCity = $cityWithSetValues->create();
echo $newCity->getId(); // Получим новый присвоенный ID. Можно и другие свойства так же получить
```

### Редактирование моделей

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

#### С помощью фасада и массива

[](#с-помощью-фасада-и-массива--1)

```
$apiGateway = VetmanagerApiGateway\ApiGateway::fromSubdomainAndApiKey('subDomain', 'apiKey', true);
// Отправляет массив данных для изменения модели и возвращает объект (соответствующий Active Record) с созданной моделью от АПИ
$updatedCity = $apiGateway->getCity()->updateUsingIdAndArray(13, ["title" => "New City", "type_id" => "1"]);
// В $updatedCity будет модель полученная из ответа по АПИ
echo $updatedCity->getTitle(); // Получим "New City". Можно и другие свойства так же получить
```

#### С помощью Active Record и сеттеров

[](#с-помощью-active-record-и-сеттеров--1)

```
$apiGateway = VetmanagerApiGateway\ApiGateway::fromSubdomainAndApiKey('subDomain', 'apiKey', true);
$city = $apiGateway->getCity()->getById(13);
$updatedCity = $city->setTitle("New City")->update();
// Без вызова update - модель не отправится
// В $updatedCity будет модель полученная из ответа по АПИ
echo $updatedCity->getTitle(); // Получим "New City". Можно и другие свойства так же получить
```

### Удаление моделей

[](#удаление-моделей-)

#### С помощью фасада

[](#с-помощью-фасада-)

```
$apiGateway = VetmanagerApiGateway\ApiGateway::fromSubdomainAndApiKey('subDomain', 'apiKey', true);
$apiGateway->getCity()->delete(13);
```

#### С помощью Active Record

[](#с-помощью-active-record-)

```
$apiGateway = VetmanagerApiGateway\ApiGateway::fromSubdomainAndApiKey('subDomain', 'apiKey', true);
$city = $apiGateway->getCity()->getById(13);
$city->delete();
```

### Пример представления данных модели

[](#пример-представления-данных-модели-)

Получать каждое свойство через гет-метод. Типизация в каждом методе есть

```
$apiGateway = VetmanagerApiGateway\ApiGateway::fromSubdomainAndApiKey('subDomain', 'apiKey', true);
$client = $apiGateway->getClient()->getById(13);
$clientEmail = $client->getEmail(); // Объявлено, что только строка, возможно пустая
$clientCityId = $client->getCityId(); // Объявлено, что только int или null может прийти
$clientDateRegister = $client->getDateRegisterAsDateTime()?->format('Y-m-d H:i:s'); //dateRegister содержит DateTime (или null, если отсутствует дата)
$clientName = $client->getFullName()->getInitials(); // FullName - вспомогательный объект для удобного форматирования имени
$clientStatus = $client->getStatusAsEnum(); // Возвращается одно из возможных значений соответствующего Enum
```

### Пример связанных запросов

[](#пример-связанных-запросов-)

Есть свойства объекта, которые вместо скалярных данных, возвращают другие объекты или массив объектов.

```
$apiGateway = VetmanagerApiGateway\ApiGateway::fromSubdomainAndApiKey('subDomain', 'apiKey', true);
$client = $apiGateway->getClient()->getById(13);
$clientStreet = $client->getStreet(); // В переменной будет null или Модель Улицы
$streetName = $clientStreet?->getTitle() ?? ''; // Название улицы или пустая строка
$clientPets = $client->getPetsAlive(); // Массив с Моделями Питомцев
$firstPet = (!empty($client->petsAlive)) ? $clientPets[0] : null; // Будет Питомец или null
$firstPetName = $firstPet?->getColor()?->getTitle() : ''; // Получение названия цвета питомца или пустая строка, если нет
```

#### Пример обращения посложнее:

[](#пример-обращения-посложнее)

```
$apiGateway = VetmanagerApiGateway\ApiGateway::fromSubdomainAndApiKey('subDomain', 'apiKey', true)->getClient()->getById(13)->getMedicalCards();
$firstMedicalCardOfClient = !empty($clientMedicalCards) ? $clientMedicalCards[0] : null;
$middleNameOfFirstMedicalCardDoctor = $firstMedicalCardOfClient?->getUser()?->getMiddleName();
```

Та же запись, но с дополнительными переменными для понимания:

```
$apiGateway = VetmanagerApiGateway\ApiGateway::fromSubdomainAndApiKey('subDomain', 'apiKey', true); // Получение объекта ApiGateway
$clientFacade = $apiGateway->getClient(); // Получение фасада для моделей Клиента с разными методами для работы с ними
$client = $clientFacade->getById(13); // Получение через АПИ-запрос используя ID модель Клиента (1ый АПИ запрос)
$clientMedicalCards = $client->getMedicalCards(); // Получение всех карт Клиента (2ой АПИ запрос)
$firstMedicalCardOfClient = !empty($clientMedicalCards) ? $clientMedicalCards[0] : null; // Получим первую карту Клиента или null, если нет карт
$firstMedicalCardDoctor = $firstMedicalCardOfClient?->getUser(); // Получение модели Доктора из медицинской карты (3ий запрос)
$middleNameOfFirstMedicalCardDoctor = $firstMedicalCardDoctor?->getMiddleName(); // Получение отчества доктора из первой Карты Клиента
```

### Нормализация объектов (приведение в массив)

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

С помощью этих методов несложно реализовать **кеширование** модели.

Каждый раз, когда нужно сделать повторяющийся одинаковый запрос:

1 - Попытаться получить уже закешированный объект в виде массива.

- Если нашелся кеш:

    2 - создать объект из этого кеша.
- Если не нашелся кеш:

    2 - сделать АПИ запрос на получение объекта

    3 - в кеш закинуть модель в виде массива для следующей PHP сессии

#### Получение модели в виде массива

[](#получение-модели-в-виде-массива)

Возвращаются данные в том же виде, в котором и были получены по АПИ

```
$apiGateway = VetmanagerApiGateway\ApiGateway::fromSubdomainAndApiKey('subDomain', 'apiKey', true);
$clientAsArray = $apiGateway->getClient()->getById(13)->getAsArray();
// Получим массив модели вида: ["id" => "1", "address" => "", "home_phone" => "3322122", ... ]
```

#### Создание объекта из данных в виде массива

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

1. Получение одного объекта из закешированного массива модели (в виде \['id' =&gt; '12', '...' =&gt; ...\]). ```
    $apiGateway = VetmanagerApiGateway\ApiGateway::fromSubdomainAndApiKey('subDomain', 'apiKey', true);
    $client = $apiGateway->getClient()->fromSingleModelAsArray($cachedClientAsArray);
    ```
2. Получение массива объектов из массива таких массивов с моделямм ```
    $apiGateway = VetmanagerApiGateway\ApiGateway::fromSubdomainAndApiKey('subDomain', 'apiKey', true);
    $clients = $apiGateway->getClient()->fromMultipleModelsAsArrays($cachedClientAsArray);
    // Дальше продолжаем использовать будто получили массив моделей как обычно
    $firstClientId = $clients[0]->getId();
    ```

### Дополнительные особенности

[](#дополнительные-особенности-)

#### Вспомогательный объект FullName

[](#вспомогательный-объект-fullname-)

Например, у моделей User и Client есть геттер для FullName. У объекта FullName есть методы возвращающие полное имя в разном формате:

```
$clientFullName = VetmanagerApiGateway\ApiGateway::fromSubdomainAndApiKey('subDomain', 'apiKey', true)->getClient()->getById(9)->getFullName();
echo $clientFullName->getFullStartingWithFirst();// Возвращает: "Имя Отчество Фамилия"
echo $clientFullName->getFullStartingWithLast(); // Возвращает: "Фамилия Имя Отчество"
echo $clientFullName->getLastPlusInitials();     // Возвращает: "Фамилия И. О."
echo $clientFullName->getInitials();             // Возвращает: "Ф. И. О."
```

Если, предположим, отчества не будет, то каждый из методов просто пропустит слово без создания лишних пробелов, точек и т.д.

#### Вспомогательный объект FullPhone

[](#вспомогательный-объект-fullphone-)

Например, у модели Клиники есть метод возвращающий FullPhone. У FullPhone есть метод возвращающий телефон с кодом страны и выбранной маской номера, например в виде: +7(918)-277-21-21

```
$clinicFullPhone = VetmanagerApiGateway\ApiGateway::fromSubdomainAndApiKey('subDomain', 'apiKey', true)->getClinic()->getById(9)->getFullPhone();
echo $clinicFullPhone->getAsMaskedWithCountryCode(); // Выведет телефона в виде +7(918)-277-21-21
echo $clinicFullPhone; // То же самое, что и прошлая строка - _toString() вызывает тот же метод
echo $clinicFullPhone->mask; // Подобные маски могут вернуться: '(___)-__-__-__', '(__)___-____' или '____-____'
echo $clinicFullPhone->countryCode; // +7 или +38 и т.д.
```

#### Узнать возможность онлайн записи в клинике

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

Несколько вариантов. Возвращается bool:

```
$apiGateway = VetmanagerApiGateway\ApiGateway::fromSubdomainAndApiKey('subDomain', 'apiKey', true)
$bool1 = $apiGateway->getProperty()->getIsOnlineSigningUpAvailableForClinic(13); // Один АПИ-запрос
$bool2 = $apiGateway->getClinic()->getIsOnlineSigningUpAvailable(13);            // Один АПИ-запрос
$bool3 = $apiGateway->getClinic()->getById(13)->getIsOnlineSigningUpAvailable(); // Два АПИ-запроса
```

### Немного об устройстве библиотеки

[](#немного-об-устройстве-библиотеки-)

#### Используемые библиотеки

[](#используемые-библиотеки)

- **Symfony Serializer** - Для создания DTO из массива данных (десериализованный JSON) и обратного процесса ( нормализации)
- **Guzzle HTTP client** - Для всех используемых запросов
- **vetmanager-rest-api** - Помощник с Query-запросами АПИ Ветменджера

    Только при разработке:
- **PSALM**
- **PHPUnit**

#### Внутренние особенности

[](#внутренние-особенности)

Для большинства моделей АПИ Ветменджер кроме запрашиваемой модели отдает и содержимое других связанных моделей. Это также зависит от вида запроса - например, при запросе по ID обычно приходит наибольшее число связанных моделей. Для пользователя этой библиотеки это скрыто: в любом случае вне зависимости от какой вида **Active Record** получен - все методы и связи с другими моделями доступны. А как именно при вызове метода будут получаться данные: из уже полученных данных или при помощи дополнительного запроса - это тоже берет на себя библиотека.

Вот пример для понимания устройства. Но для использования это вовсе неважно. В использовании каждый из полученных **Active Record**идентичен (так как обладают одним и тем же набором доступных методов, которые просто реализованы по-разному):

```
$apiGateway = VetmanagerApiGateway\ApiGateway::fromSubdomainAndApiKey('subDomain', 'apiKey', true);
/** @var VetmanagerApiGateway\Facade\Client $clientFacade Содержит методы связанные с моделью для осуществления АПИ-запросов и созданию Active Records */
$clientFacade = $apiGateway->getClient();
/** @var VetmanagerApiGateway\ActiveRecord\Client\ClientOnly[] $clients Содержит в себе DTO Client и связи со связанным Active Records*/
$clients = $clientFacade->getAll();
/** @var VetmanagerApiGateway\ActiveRecord\Client\ClientPlusTypeAndCity $client Содержит в себе DTO для моделей Client, Client Type, City */
$client = $clientFacade->getById(33);
```

Разработка
----------

[](#разработка)

### Первый запуск

[](#первый-запуск)

1. Копируем файл окружения из примера ```
    cp .env.example .env
    ```
2. Заполняем `.env`
3. Устанавливаем библиотеки ```
    docker compose run php-fpm composer install
    ```

### Проверка тестов

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

Запуск всех тестов (юнит и интеграционные)

```
docker compose run php-fpm composer test-all
```

Запуск юнит-тестов

```
docker compose run php-fpm composer test-unit
```

Запуск интеграционных-тестов (будут вызовы к АПИ Ветменджер - токен и домен должны быть в .env)

```
docker compose run php-fpm composer test-integration
```

### Проверка стиля кода

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

Проверка стиля кода без исправления (dry-run)

```
docker compose run php-fpm composer style-check
```

Исправление стиля кода автоматически

```
docker compose run php-fpm composer style-fix
```

### Статический анализ кода

[](#статический-анализ-кода)

Запуск Psalm для статического анализа кода

```
docker compose run php-fpm composer psalm
```

Запуск Psalm с выводом отчета в JSON файл

```
docker compose run php-fpm composer psalm-json
```

### Анализ кода с SonarQube

[](#анализ-кода-с-sonarqube)

Проект интегрирован с [SonarCloud](https://sonarcloud.io/) для непрерывного анализа качества кода.

Анализ кода автоматически запускается при:

- push в ветку `master`
- при создании Pull Request через GitHub Actions

#### Генерация отчетов покрытия кода

[](#генерация-отчетов-покрытия-кода)

Отчеты покрытия кода генерируются автоматически в GitHub Actions workflow. Если нужно сгенерировать отчеты локально для проверки:

```
docker compose run php-fpm composer test-coverage
```

Это создаст файлы `coverage.xml` и `test-results.xml`, которые будут использованы при автоматическом анализе в GitHub Actions.

###  Health Score

38

—

LowBetter than 85% of packages

Maintenance53

Moderate activity, may be stable

Popularity13

Limited adoption so far

Community12

Small or concentrated contributor base

Maturity65

Established project with proven stability

 Bus Factor1

Top contributor holds 99.2% 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

Every ~11 days

Total

37

Last Release

689d ago

Major Versions

1.0.16 → 2.0.02023-08-15

### Community

Maintainers

![](https://www.gravatar.com/avatar/e45758d8572bb646e8980ae618a914a14113b07a3c5da72ecf2796aada32fe79?d=identicon)[ionov-e](/maintainers/ionov-e)

---

Top Contributors

[![ionov-e](https://avatars.githubusercontent.com/u/82158159?v=4)](https://github.com/ionov-e "ionov-e (256 commits)")[![otis22](https://avatars.githubusercontent.com/u/378373?v=4)](https://github.com/otis22 "otis22 (1 commits)")[![parazeet](https://avatars.githubusercontent.com/u/47498507?v=4)](https://github.com/parazeet "parazeet (1 commits)")

###  Code Quality

TestsPHPUnit

Static AnalysisPsalm

Code StylePHP CS Fixer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/ioncurly-vetmanager-api-gateway/health.svg)

```
[![Health](https://phpackages.com/badges/ioncurly-vetmanager-api-gateway/health.svg)](https://phpackages.com/packages/ioncurly-vetmanager-api-gateway)
```

###  Alternatives

[sylius/sylius

E-Commerce platform for PHP, based on Symfony framework.

8.4k5.6M650](/packages/sylius-sylius)[craftcms/cms

Craft CMS

3.6k3.6M2.6k](/packages/craftcms-cms)[googleads/googleads-php-lib

Google Ad Manager SOAP API Client Library for PHP

67410.3M25](/packages/googleads-googleads-php-lib)[fschmtt/keycloak-rest-api-client-php

PHP client to interact with Keycloak's Admin REST API.

4684.7k2](/packages/fschmtt-keycloak-rest-api-client-php)[mapado/rest-client-sdk

Rest Client SDK for hydra API

1125.9k2](/packages/mapado-rest-client-sdk)

PHPackages © 2026

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