定制 kenny-mgn/profitbase-php-client 二次开发

按需修改功能、优化性能、对接业务系统,提供一站式技术支持

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

kenny-mgn/profitbase-php-client

最新稳定版本:1.0.1

Composer 安装命令:

composer require kenny-mgn/profitbase-php-client

包简介

Guzzle-based PHP client for the Profitbase API with access token handling and rate limit control.

README 文档

README

CI Latest Stable Version License PHPStan Code Style

Содержание

Описание

Profitbase API Client for PHP – это обёртка над HTTP-клиентом Guzzle, предназначенная для взаимодействия с Profitbase API. Данный пакет реализует автоматическое управление токеном доступа (access token): его первоначальное получение, обновление по истечении срока действия и троттлинг запросов для соблюдения ограничений частоты обращений (rate limit) к Profitbase API.

Требования

  • PHP >= 8.1
  • PHP Extensions: curl, json

Установка

composer require kenny-mgn/profitbase-php-client

Быстрый старт

use KennyMgn\ProfitbaseClient\ProfitbaseClient;

try {  
    $client = ProfitbaseClient::create('your-api-key', 'https://pbXXXXX.profitbase.ru/api/v4/json');  
    $response = $client->houses();  
  
    $jsonString = $response->getBody()->getContents();  
    $arrayResult = json_decode($jsonString, associative: true);  
} catch (Throwable $throwable) {  
    echo $throwable->getMessage();  
}

Методы запросов к Profitbase API возвращают ответ в виде ResponseInterface. Основные методы:

# HTTP статус ответа
$response->getStatusCode();

# Тело ответа
$body = $response->getBody();

# Читаем всё содержимое в память
$jsonString = $body->getContents();

Query-параметры

Во всех методах обращения к Profitbase API можно передавать дополнительные query-параметры через массив $queryParams.

Если эндпоинт имеет стандартные параметры, они обычно уже вынесены в сигнатуру метода, например:

public function specialOffers(
    ?bool $isArchived = null,
    ?bool $isDiscounted = null,
    array $queryParams = []
)

Параметры $isArchived и $isDiscounted — основные, определённые в методе.

Массив $queryParams позволяет добавлять любые другие query-параметры для гибкости, даже если эндпоинт сейчас их не принимает.

Передача множественных значений в query-параметрах

В Profitbase API для передачи нескольких значений одного параметра query string должен иметь вид:

?ids[]=1&ids[]=2&ids[]=3

В данном пакете это достигается созданием массива вида:

$queryParams = ['ids[]' => [1, 2, 3]];

Библиотека автоматически преобразует такой массив в правильный формат query string для запроса к API.

Пример использования:

$client = ProfitbaseClient::create($apiKey, $baseEndpoint);  
$response = $client->properties(['status[]' => ['AVAILABLE', 'BOOKED']]);

Конфигурация HTTP-клиента (Guzzle)

При создании экземпляра клиента ProfitbaseClient можно передавать массив $httpClientConfig с дополнительными параметрами конфигурации Guzzle. Любые переданные параметры переопределяют стандартные настройки HTTP-клиента,
что позволяет гибко управлять поведением соединений, таймаутами, заголовками и другими опциями.

Пример создания клиента с кастомной конфигурацией:

$client = ProfitbaseClient::create(
    $apiKey,
    $baseEndpoint,
    [
        'timeout' => 20,
        'headers' => ['X-Custom-Header' => 'value'],
    ]
);

Все доступные параметры Guzzle можно найти в официальной документации: Guzzle Request Options.

Потоковый режим

По умолчанию клиент работает в потоковом режиме, позволяющем обрабатывать данные по мере их поступления и использовать библиотеки вроде cerbero/json-parser для порционной обработки больших JSON-ответов.

use Cerbero\JsonParser\JsonParser;  
use KennyMgn\ProfitbaseClient\ProfitbaseClient;

try {  
    $client = ProfitbaseClient::create($apiKey, $baseEndpoint);  
    $response = $client->houses();  
  
    $stream = $response->getBody();  
    JsonParser::parse($stream)->traverse(function (mixed $value, string|int $key, JsonParser $parser) {  
        // Действия
    });  
} catch (Throwable $throwable) {  
    echo $throwable->getMessage();  
}

Чтобы создать экземпляр клиента не в потоковом режиме, передайте параметр конфигурации stream => false:

$client = ProfitbaseClient::create($apiKey, $baseEndpoint, ['stream' => false]);

Ограничение частоты запросов (Rate Limit)

Profitbase API ограничивает частоту обращений: не более одного запроса в секунду от одного клиента. Чтобы соблюдать это требование, класс ProfitbaseClient включает встроенный механизм ограничения количества запросов. По умолчанию между последовательными запросами выдерживается пауза в 1 секунду.

Интервал можно изменить методом:

$client->limitRequestRateTo(2);

Асинхронность и многопоточность

Класс ProfitbaseClient реализован синхронно — все запросы выполняются последовательно в одном потоке. Он не поддерживает асинхронные вызовы или параллельное выполнение запросов из коробки.

Если вы попытаетесь выполнять несколько запросов одновременно (например, из разных потоков или процессов), ограничение на уровне PHP-кода не сможет их синхронизировать — в этом случае ограничение частоты запросов нужно обеспечивать самостоятельно.

Методы доступа к Profitbase API

Раздел описывает публичные методы класса ProfitbaseClient, соответствующие эндпоинтам Profitbase API, с указанием HTTP-метода, пути и поддерживаемых параметров.

Структура данного раздела (группировка и наименования) повторяет структуру официальной документации Profitbase API. Это сделано для удобства навигации и быстрой сопоставимости методов клиента с эндпоинтами API.

Подробное описание параметров запросов (включая query string и body) и форматов ответов см. в официальной документации Profitbase: https://developer.profitbase.ru/.

Навигация по методам доступа к Profitbase API

auth

houses

projects

properties

board

presets

facade

floor

actions

crm

order

history

statuses

filter

property-specification

queue-reserve

render

users

stock-version

⚠️ Примечание о непроверенных методах

На реальном API была проверена работоспособность только идемпотентных методов (выполняющих безопасные операции не изменяющие состояние системы). Это связано с тем, что тестирование проводилось с доступом только на чтение.

Методы, выполнение которых изменяет состояние данных, не были проверены на реальном API. Такие методы в документации помечены специальным образом: ⚠️ Не проверено на реальном API.

auth

Авторизация

Метод для аутентификации. Возвращает access_token для доступа к API.

⚠️ Примечание: вызов auth() не обязателен — клиент автоматически обрабатывает получение, обновление и передачу access_token при каждом запросе.

Эндпоинт: POST /authentication

Сигнатура:

auth(string $apiKey): ResponseInterface

Пример вызова:

$client->auth('app-some-key');

⤴ Вернуться к навигации по методам

houses

Метод получения списка домов с возможностью фильтрации

Эндпоинт: GET /house

Сигнатура:

houses(array $queryParams = []): ResponseInterface

Пример вызова:

$client->houses(['isArchive' => false]);

⤴ Вернуться к навигации по методам

Метод получения количества этажей в конкретном доме

Эндпоинт: GET /house/get-count-floors

Сигнатура:

houseFloorCount(int $houseID, array $queryParams = []): ResponseInterface

Пример вызова:

$client->houseFloorCount(houseID: 12345);

⤴ Вернуться к навигации по методам

Метод получения количества помещений в конкретном доме на конкретном этаже

Эндпоинт: /house/get-count-properties-on-floor

Сигнатура:

houseFloorPropertyCount(int $houseID, int $floor, array $queryParams = []): ResponseInterface

Пример вызова:

$client->houseFloorPropertyCount(houseID: 12345, floor: 5);

⤴ Вернуться к навигации по методам

Устаревший метод v3 получения списка домов

Эндпоинт: /projects/{projectId}/houses

Сигнатура:

housesLegacyV3(int $projectID, array $queryParams = []): ResponseInterface

Пример вызова:

$client->housesLegacyV3(projectID: 789);

⤴ Вернуться к навигации по методам

Метод создания дома в существующий ЖК

⚠️ Не проверено на реальном API

Эндпоинт: POST /house

Сигнатура:

houseCreate(array $body, array $queryParams = []): ResponseInterface

Пример вызова:

$client->houseCreate(['title' => 'Корпус 1', 'projectId' => 789]);

⤴ Вернуться к навигации по методам

Метод обновления данных в конкретном доме

⚠️ Не проверено на реальном API

Эндпоинт: PUT /houses/{id}

Сигнатура:

houseUpdate(int $houseID, array $body, array $queryParams = []): ResponseInterface

Пример вызова:

$client->houseUpdate(12345, ['title' => 'Корпус 1А']);

⤴ Вернуться к навигации по методам

Метод для поиска домов по названию, адресу и названию ЖК

Эндпоинт: GET /houses/search

Сигнатура:

housesSearch(string $searchQuery, array $queryParams = []): ResponseInterface

Пример вызова:

$client->housesSearch('Корпус 1');

⤴ Вернуться к навигации по методам

projects

Метод получения списка ЖК

Эндпоинт: GET /projects

Сигнатура:

projects(?bool $isArchive = null, array $queryParams = []): ResponseInterface

Пример вызова:

$client->projects(isArchive: false);

⤴ Вернуться к навигации по методам

Метод создания ЖК

⚠️ Не проверено на реальном API

Эндпоинт: POST /projects

Сигнатура:

projectCreate(array $body, array $queryParams = []): ResponseInterface

Пример вызова:

$client->projectCreate(['title' => 'Новомосковский', 'type' => 'complex']);

⤴ Вернуться к навигации по методам

Метод обновления ЖК

⚠️ Не проверено на реальном API

Эндпоинт: PUT /projects/{id}

Сигнатура:

projectUpdate(int $projectID, array $body, array $queryParams = []): ResponseInterface

Пример вызова:

$client->projectUpdate(789, ['title' => 'Квартальный', 'type' => 'quarter']);

⤴ Вернуться к навигации по методам

Метод для поиска ЖК по названию, адресу и названию дома, названию застройщика

Эндпоинт: GET /projects/search

Сигнатура:

projectsSearch(string $searchQuery, array $queryParams = []): ResponseInterface

Пример вызова:

$client->projectsSearch('Новомосковский');

⤴ Вернуться к навигации по методам

properties

Метод получения списка помещений с возможностью фильтрации

Эндпоинт: GET /property

Сигнатура:

properties(array $queryParams = []): ResponseInterface

Пример вызова:

$client->properties(['status[]' => ['AVAILABLE', 'BOOKED']]);

⤴ Вернуться к навигации по методам

Метод создания помещения в конкретный дом

⚠️ Не проверено на реальном API

Эндпоинт: POST /properties

Сигнатура:

propertyCreate(array $body, array $queryParams = []): ResponseInterface

Пример вызова:

$client->propertyCreate([  
    'house_id' => 1,  
    'number' => 'A101',  
    'rooms_amount' => 3,  
    'section' => '1',  
    'floor' => 11,  
    'status' => 'AVAILABLE',  
    "area" => [  
        "area_total" => 60.2,  
        "area_estimated" => 60.2,  
        "area_living" => 60.2,  
        "area_kitchen" => 60.2,  
        "area_balcony" => 60.2,  
        "area_without_balcony" => 60.2  
    ],  
]);

⤴ Вернуться к навигации по методам

Метод обновления данных в конкретном помещении

⚠️ Не проверено на реальном API

Эндпоинт: PATCH /properties/{propertyId}

Сигнатура:

propertyUpdate(int $propertyID, array $body, array $queryParams = []): ResponseInterface

Пример вызова:

$client->propertyUpdate(56789, ['status' => 'SOLD']);

⤴ Вернуться к навигации по методам

Метод получения списка типов помещений и их дополнительных полей

Эндпоинт: GET /property-types

Сигнатура:

propertyTypes(array $queryParams = []): ResponseInterface

Пример вызова:

$client->propertyTypes();

⤴ Вернуться к навигации по методам

Метод получения списка помещений привязанных к конкретной сделке

Эндпоинт: GET /property/deal/{dealId}

Сигнатура:

propertyDealList(int $dealID, array $queryParams = []): ResponseInterface

Пример вызова:

$client->propertyDealList(dealID: 112233);

⤴ Вернуться к навигации по методам

Метод получения истории изменения статусов по конкретному помещению

Эндпоинт: GET /property/history/{propertyId}

Сигнатура:

propertyHistory(  
    int $propertyID,  
    ?int $offset = null,  
    ?int $limit = null,  
    array $queryParams = []  
): ResponseInterface

Пример вызова:

$client->propertyHistory(56789, offset: 0, limit: 10);

⤴ Вернуться к навигации по методам

Устаревший метод v3 получения списка помещений в конкретном доме

Эндпоинт: GET /projects/{projectId}/houses/{houseId}/properties/list

Сигнатура:

propertiesLegacyV3(int $projectID, int $houseID, array $queryParams = []): ResponseInterface

Пример вызова:

$client->propertiesLegacyV3(projectID: 123, houseID: 456);

⤴ Вернуться к навигации по методам

Метод получения списка сделок привязанных к конкретным помещениям

Эндпоинт: GET /get-property-deals

Сигнатура:

propertyDeals(array $propertyIDs, array $queryParams = []): ResponseInterface

Пример вызова:

$client->propertyDeals([56789, 56790]);

⤴ Вернуться к навигации по методам

Метод изменения статуса помещения

⚠️ Не проверено на реальном API

Эндпоинт: POST /properties/{id}/status-change

Сигнатура:

propertyStatusChange(int $propertyID, array $body, array $queryParams = []): ResponseInterface

Пример вызова:

$client->propertyStatusChange(56789, ['status' => 'UNAVAILABLE']);

⤴ Вернуться к навигации по методам

Метод продления брони в конкретном помещении

⚠️ Не проверено на реальном API

Эндпоинт: PATCH /reserve/prolong

Сигнатура:

reserveProlong(array $body, array $queryParams = []): ResponseInterface

Пример вызова:

$client->reserveProlong(['propertyId' => 56789, 'date' => '2025-11-16 12:00']);

⤴ Вернуться к навигации по методам

board

Метод получения шахматки дома

Эндпоинт: GET /board

Сигнатура:

board(int $houseID, array $queryParams = []): ResponseInterface

Пример вызова:

$client->board(houseID: 12345);

⤴ Вернуться к навигации по методам

presets

Метод получения планировок помещений с возможностью фильтрации

Эндпоинт: GET /plan

Сигнатура:

plans(array $queryParams = []): ResponseInterface

Пример вызова:

$client->plans(['projectId' => 123]);

⤴ Вернуться к навигации по методам

Устаревший метод получения планировок помещений в доме

Эндпоинт: GET /projects/{projectId}/houses/{houseId}/presets

Сигнатура:

presetsLegacy(int $projectID, int $houseID, array $queryParams = []): ResponseInterface

Пример вызова:

$client->presetsLegacy(projectID: 789, houseID: 12345);

⤴ Вернуться к навигации по методам

facade

Метод получения списка фасадов дома

Эндпоинт: GET /facade

Сигнатура:

facades(int $houseID, array $queryParams = []): ResponseInterface

Пример вызова:

$client->facades(houseID: 12345);

⤴ Вернуться к навигации по методам

floor

Метод получения планировок этажей дома

Эндпоинт: GET /floor

Сигнатура:

floors(int $houseID, array $queryParams = []): ResponseInterface

Пример вызова:

$client->floors(houseID: 12345);

⤴ Вернуться к навигации по методам

actions

Метод получения списка активных акции со списком помещений по каждой акции

Эндпоинт: GET /special-offer

Сигнатура:

specialOffers(  
    ?bool $isArchived = null,  
    ?bool $isDiscounted = null,  
    array $queryParams = []  
): ResponseInterface

Пример вызова:

$client->specialOffers(isArchived: false, isDiscounted: true);

⤴ Вернуться к навигации по методам

crm

Метод получения списка сделок или конкретной сделки

Эндпоинт: GET /crm/deals

Сигнатура:

crmDeals(?int $dealID = null, array $queryParams = []): ResponseInterface

Пример вызова:

$client->crmDeals(dealID: 112233);

⤴ Вернуться к навигации по методам

Метод получения списка сделок в которые добавлено конкретное помещение

Эндпоинт: GET /crm/deals/property/{propertyId}

Сигнатура:

crmPropertyDeals(int $propertyID, array $queryParams = []): ResponseInterface

Пример вызова:

$client->crmPropertyDeals(56789);

⤴ Вернуться к навигации по методам

Метод добавления помещения в сделку

⚠️ Не проверено на реальном API

Эндпоинт: POST /crm/addPropertyDeal

Сигнатура:

crmPropertyDealAdd(array $body, array $queryParams = []): ResponseInterface

Пример вызова:

$client->crmPropertyDealAdd(['dealId' => 112233, 'propertyId' => 56789]);

⤴ Вернуться к навигации по методам

Метод удаления помещений из сделки

⚠️ Не проверено на реальном API

Эндпоинт: POST /crm/removePropertyDeal

Сигнатура:

crmPropertyDealRemove(int $dealID, array $body = [], array $queryParams = []): ResponseInterface

Пример вызова:

$client->crmPropertyDealRemove(dealID: 112233);

⤴ Вернуться к навигации по методам

Метод обновления полей Proftibase в сделке по помещению

⚠️ Не проверено на реальном API

Эндпоинт: GET /crm/update/deal/{dealId}/property/{propertyId} Сигнатура:

crmDealPropertyUpdate(int $dealID, int $propertyID, array $queryParams = []): ResponseInterface

Пример вызова:

$client->crmDealPropertyUpdate(dealID: 112233, propertyID: 56789);

⤴ Вернуться к навигации по методам

Метод синхронизации статуса помещения с этапом сделки CRM согласно разметке статусов приложения CRM для Profitbase

⚠️ Не проверено на реальном API

Эндпоинт: GET /crm/syncPropertyStatus

Сигнатура:

crmPropertyStatusSync(int $dealID, array $queryParams = []): ResponseInterface

Пример вызова:

$client->crmPropertyStatusSync(dealID: 112233);

⤴ Вернуться к навигации по методам

order

Метод создания заявки на помещение

⚠️ Не проверено на реальном API

Эндпоинт: POST /orders

Сигнатура:

orderCreate(array $body, array $queryParams = []): ResponseInterface

Пример вызова:

$client->orderCreate([
	'order' => [
		'name' => 'TEST',
		'phone' => '+79111111111',
		'email' => 'test@profitbase.ru',
		'apartment_id' => 248408,
		'calc_credit' => 1,
		'comment' => 'тестовая заявка',
		'widget_id' => 1
	]
]);

⤴ Вернуться к навигации по методам

history

Метод получения истории изменения статусов помещений с возможностью фильтрации

Эндпоинт: POST /history

Сигнатура:

history(array $body, array $queryParams = []): ResponseInterface

Пример вызова:

$client->history([  
    'offset' => 0,  
    'limit' => 20,  
    'property_ids' => [  
        3225787,  
        3225788  
    ],  
    'from' => '2023-03-01 10:56:15',  
    'to' => '2023-03-02 07:20:50',  
]);

⤴ Вернуться к навигации по методам

statuses

Метод получения списка статусов для crm, или конкретного статуса по id

Эндпоинт: GET /custom-status/list

Сигнатура:

customStatuses(string $crmID, ?string $statusID = null, array $queryParams = []): ResponseInterface

Пример вызова:

$client->customStatuses('bitrix');

⤴ Вернуться к навигации по методам

filter

Метод для получения списка отображаемых в виджете фильтров

Эндпоинт: GET /filter

Сигнатура:

filters(array $queryParams = []): ResponseInterface

Пример вызова:

$client->filters();

⤴ Вернуться к навигации по методам

Метод для получения списка доступных отделок для отображения в фильтре по отделке

Эндпоинт: GET /filter/facings

Сигнатура:

filterFacings(array $houseIDs = [], array $queryParams = []): ResponseInterface

Пример вызова:

$client->filterFacings([12345, 12346]);

⤴ Вернуться к навигации по методам

Получить характеристики для фильтра

Эндпоинт: GET /filter/property-specifications

Сигнатура:

filterPropertySpecifications(array $queryParams = []): ResponseInterface

Пример вызова:

$client->filterPropertySpecifications();

⤴ Вернуться к навигации по методам

property-specification

Метод получения списка характеристик для помещений с количеством аналогичных помещений в доме

Эндпоинт: /property-specification

Сигнатура:

propertySpecifications(array $propertyIDs = [], array $queryParams = []): ResponseInterface

Пример вызова:

$client->propertySpecifications([56789, 56790]);

⤴ Вернуться к навигации по методам

Получить список всех характеристик

Эндпоинт: GET /property-specification/list

Сигнатура:

propertySpecificationList(array $queryParams = []): ResponseInterface

Пример вызова:

$client->propertySpecificationList();

⤴ Вернуться к навигации по методам

Получить характеристики по дому

Эндпоинт: GET /property-specification/house

Сигнатура:

propertySpecificationHouse(int $houseID, array $queryParams = []): ResponseInterface

Пример вызова:

$client->propertySpecificationHouse(houseID: 12345);

⤴ Вернуться к навигации по методам

queue-reserve

Метод получения списка очереди бронирования по указанному помещению

Эндпоинт: GET /queue-reserve/list Сигнатура:

queueReserveList(int $propertyID, array $queryParams = []): ResponseInterface

Пример вызова:

$client->queueReserveList(propertyID: 56789);

⤴ Вернуться к навигации по методам

Метод для удаления сделки из очереди бронирования

⚠️ Не проверено на реальном API

Эндпоинт: POST /queue-reserve/delete

Сигнатура:

queueReserveDelete(  
    int $dealQueueItemID,  
    array $body = [],  
    array $queryParams = []  
): ResponseInterface

Пример вызова:

$client->queueReserveDelete(dealQueueItemID: 123456);

⤴ Вернуться к навигации по методам

Метод для добавления сделки в очередь бронирования

⚠️ Не проверено на реальном API

Эндпоинт: POST /queue-reserve

Сигнатура:

queueReserveCreate(  
    int $propertyID,  
    int|string $dealID,  
    array $body = [],  
    array $queryParams = []  
): ResponseInterface

Пример вызова:

$client->queueReserveCreate(propertyID: 56789, dealID: 112233);

⤴ Вернуться к навигации по методам

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

⚠️ Не проверено на реальном API

Эндпоинт: POST /queue-reserve/change-position

Сигнатура:

queueReserveChangePosition(  
    int $sourceDealQueueItemID,  
    int $targetDealQueueItemID,  
    array $body = [],  
    array $queryParams = []  
): ResponseInterface

Пример вызова:

$client->queueReserveChangePosition(12456, 124);

⤴ Вернуться к навигации по методам

render

Метод получения списка генпланов

Эндпоинт: GET /render

Сигнатура:

renders(?int $projectID = null, array $queryParams = []): ResponseInterface

Пример вызова:

$client->renders(projectID: 789);

⤴ Вернуться к навигации по методам

users

Метод для получения информации о пользователях

Эндпоинт: GET /user/info

Сигнатура:

userInfo(array $queryParams = []): ResponseInterface

Пример вызова:

$client->userInfo(['email' => 'some_email@test.com']);

⤴ Вернуться к навигации по методам

Метод для изменения прав пользователей

⚠️ Не проверено на реальном API

Эндпоинт: PATCH /user/{userId}/access

Сигнатура:

userAccessUpdate(int $userID, array $body, array $queryParams = []): ResponseInterface

Пример вызова:

$client->userAccessUpdate(  
    334455,  
    [  
        'isAccountAccessEnabled' => 'true',  
        'isUsersSectionAccessEnabled' => 'true',  
        'isObjectsSectionAccessEnabled' => 'true'  
    ]  
);

⤴ Вернуться к навигации по методам

Инициализация сброса пароля для пользователя

⚠️ Не проверено на реальном API

Эндпоинт: GET /user/{userId}/password/forgot

Сигнатура:

userPasswordForgot(int $userID, array $queryParams = []): ResponseInterface

Пример вызова:

$client->userPasswordForgot(userID: 334455);

⤴ Вернуться к навигации по методам

stock-version

Получить изменения по версиям

Эндпоинт: POST /versions/find

Сигнатура:

stockVersionsFind(array $body, array $queryParams = []): ResponseInterface

Пример вызова:

$client->stockVersionsFind([  
    'ids' => [  
        12345,  
        12346  
    ],  
    'fields' => [  
        'price',  
        'status'  
    ]  
]);

⤴ Вернуться к навигации по методам

Обратная связь

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

Лицензия

Проект распространяется под лицензией MIT.

统计信息

  • 总下载量: 13
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 0
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2025-10-22