Идея этой библиотеки - максимально лёгкий и гибкий SDK, позволяющий работать с API 1.2 и PHP 8.1+
.
Библиотека находится в разработке, версии до v1.0.0
могут не обладать обратной совместимостью. Список изменений можно найти в Changelog. Инструкция по обновлению для версий, не поддерживающих обратную совместимость - Upgrade guide.
composer require evgeek/moysklad
//Минимум
$ms = new \Evgeek\Moysklad\MoySklad(['token']);
//С подробностями
$ms = new \Evgeek\Moysklad\MoySklad(
credentials: ['login', 'password'],
formatter: new \Evgeek\Moysklad\Formatters\StdClassFormat(),
requestSenderFactory: new \Evgeek\Moysklad\Http\GuzzleSenderFactory(retires: 3, exceptionTruncateAt: 4000)
);
credentials
- массив с учётными данными. Можно использовать либо токен, либо логин/пароль.formatter
- объект, преобразующий json-строку ответа от API в нужный формат, и наоборот - передаваемый payload в json-строку. Должен реализовывать\Evgeek\Moysklad\Formatters\JsonFormatterInterface
. Встроенные форматтеры -StdClassFormat
(по умолчанию),ArrayFormat
, иStringFormat
. Все встроенные форматтеры могут принимать в качестве payloadstdClass
,array
иstring
.requestSenderFactory
- фабрика, создающая объект для отправки http-запросов. По умолчанию библиотека для этих целей использует Guzzle. В стандартныйGuzzleSenderFactory()
в качестве аргументов можно передать желаемое количество попыток повтора запроса в случае неудачи (по умолчанию 0, задержка между повторами экспоненциальна) и максимальный размер сообщения об ошибке (по умолчанию 120 символов). Фабрика и отправитель реализованы через простыеPSR-7
совместимые интерфейсы, поэтому не составит труда как просто настроить клиент Guzzle под свои предпочтения, так и реализовать собственный способ отправки.
Взаимодействовать с API можно как при помощи реализованных в SDK сущностей, так и при помощи универсальных методов, которые позволят собрать любой запрос. К примеру, запрос GET https://online.moysklad.ru/api/remap/1.2/entity/customerorder/00001c03-5227-11e8-9ff4-315000132d57/positions?limit=2
можно построить так:
$ms->query()
->entity()
->customerorder()
->byId('00001c03-5227-11e8-9ff4-315000132d57')
->positions()
->limit(2)
->get();
Или так:
$ms->query()
->endpoint('entity')
->method('customerorder')
->byId('00001c03-5227-11e8-9ff4-315000132d57')
->method('positions')
->param('limit', '2')
->send('GET');
Список универсальных методов:
endpoint()
- входная точка api:entity
,report
и т д.method()
- шаг вложенности url. Вложенностей может быть несколькоbyId()
- аналогично, шаг вложенности, но предназначен для идентификаторов сущностей. Отmethod()
отличается только набором методов.param()
- для формирования query-параметров urlsend()
- отправляет http-запрос и возвращает его результат. Параметрыmethod
иbody
позволяют задать http-метод запроса и его payload.
Для формирования параметров запроса, помимо param()
, есть несколько более удобных методов:
limit()
- ограничение количества записей в ответеoffset()
- сдвиг для пагинацииsearch()
- контекстный поиск (doc)expand()
- разворачивание вложенных сущностей (doc). Несколько полей можно задать при помощи нескольких вызовов метода, или передав в метод массив с названиями полей. Помните, что разворачивание работает только с limit <= 100 и до 3-го уровня вложенности (ограничение API):
$ms->query()->entity()->product()
->limit(100)
->expand('owner')
->expand('minPrice.currency')
->expand(['group', 'images']);
filter()
- фильтрация результатов выдачи (doc). В метод можно передать три параметра (ключ, знак и значение), или только два (ключ и значение, в качестве знака по умолчанию будет использовано=
). Знаком может быть строка ('='
,'!='
и пр.) или enumEvgeek\Moysklad\Enums\FilterSign
. Несколько фильтров за раз можно передать как массив массивов с параметрами фильтрации:
$product = $ms->query()->entity()->product()
->filter('archived', false)
->filter('name', '=~', 'apple')
->filter([
['minimumBalance', '=', '0'],
['code', FilterSign::NEQ, 123],
]);
order()
- сортировка (doc). Если направление не задано, будет сортироваться по возрастанию (asc
). Несколько сортировок можно передать или массивом массивов, или через несколько вызовов метода:
$ms->query()->entity()->product()
->order('updated', 'asc')
->order([
['code', 'desc'],
['name'],
]);
Нюансы:
- И
param()
, и специализированные методы поддерживают дозапись в параметрах, где это возможно (filter
,expand
,order
). В остальных параметрах ранее установленное значение перезаписывается. param()
, аналогично прочим методам с дозаписью, поддерживает передачу нескольких наборов значений через массив массивов.filter()
автоматом экранирует;
.param()
- нет.
Помимо send()
, для отправки http-запросов поддерживаются следующие методы:
get()
-GET
запрос для чтения данныхcreate()
-POST
запрос для создания сущностиupdate()
-PUT
запрос для обновления сущностиdelete()
-DELETE
запрос для удаления сущностиmassDelete()
-POST
запрос для массового удаления
Тело для POST
и PUT
запросов можно передавать в любом поддерживаемом формате (массив, объект, json-строка).
getGenerator()
- метод для итерируемых сущностей. Возвращает генератор, перебирающий массивrows
с текущегоoffset
и до последнего элемента (с отправкой новых запросов, если это необходимо). Пагинация осуществляется с шагомlimit
.
$generator = $ms->query()->entity()->product()->limit(100)->search('orange')->getGenerator();
foreach ($generator as $product) {
//...
}
debug()
- можно разместить перед любымCRUD
методом, чтобы увидеть в подробностях, какой именно запрос будет отправлен:
$product = $ms
->query()
->entity()
->product()
->limit(1)
->filter([
['archived', false],
['name', '!=', 'tangerine'],
])
->debug()
->get();
var_dump($product);
object(stdClass)#28 (5) {
["method"]=>
string(3) "GET"
["url"]=>
string(101) "https://online.moysklad.ru/api/remap/1.2/entity/product?limit=1&filter=archived=false;name!=tangerine"
["url_encoded"]=>
string(109) "https://online.moysklad.ru/api/remap/1.2/entity/product?limit=1&filter=archived%3Dfalse%3Bname%21%3Dtangerine"
["headers"]=>
object(stdClass)#29 (2) {
["Content-Type"]=>
string(16) "application/json"
["Authorization"]=>
string(38) "Basic ###############################"
}
["body"]=>
array(0) {
}
}
\Evgeek\Moysklad\Tools\Guid
- предназначен для работы с id (guid/uuid) сущностей:
$url = 'https://online.moysklad.ru/api/remap/1.2/entity/customerorder/00001c03-5227-11e8-9ff4-315000132d57/positions/00002107-5227-11e8-9ff4-315000132d58';
var_dump(Guid::extractAll($url));
var_dump(Guid::extractFirst($url));
var_dump(Guid::extractLast($url));
array(2) {
[0]=>
string(36) "00001c03-5227-11e8-9ff4-315000132d57"
[1]=>
string(36) "00002107-5227-11e8-9ff4-315000132d58"
}
string(36) "00001c03-5227-11e8-9ff4-315000132d57"
string(36) "00002107-5227-11e8-9ff4-315000132d58"
\Evgeek\Moysklad\Tools\Meta
- помогает формировать метадату для создания новых объектов:
var_dump(Meta::organization('ec008e5b-f5ab-11e5-7a69-970f0019fa50'));
object(stdClass)#19 (3) {
["href"]=>
string(97) "https://online.moysklad.ru/api/remap/1.2/entity/organization/ec008e5b-f5ab-11e5-7a69-970f0019fa50"
["type"]=>
string(12) "organization"
["mediaType"]=>
string(16) "application/json"
}
Форматирование можно задать при помощи метода Meta::setFormat()
. По умолчанию используется StdClassFormat
. Учитывайте, что Meta
и MoySklad
используют разные форматтеры, то есть установка формата в одном классе не затронет другой.
Помимо небольшого набора предопределённых сущностей, можно сформировать любую мету при помощи универсального метода Meta::create()
(и более узкого Meta::entity()
). Примеры:
Meta::setFormat(new ArrayFormat());
$order = [
'name' => 'test_order',
'organization' => ['meta' => Meta::create(['entity', 'organization', 'ec008e5b-f5ab-11e5-7a69-970f0019fa50'], 'organization')],
'agent' => ['meta' => Meta::entity(['counterparty', '918e0c83-483c-11e7-7a69-93a700ee9dbd'], 'counterparty')],
];
var_dump($order);
array(3) {
["name"]=>
string(10) "test_order"
["organization"]=>
array(1) {
["meta"]=>
array(3) {
["href"]=>
string(97) "https://online.moysklad.ru/api/remap/1.2/entity/organization/ec008e5b-f5ab-11e5-7a69-970f0019fa50"
["type"]=>
string(12) "organization"
["mediaType"]=>
string(16) "application/json"
}
}
["agent"]=>
array(1) {
["meta"]=>
array(3) {
["href"]=>
string(97) "https://online.moysklad.ru/api/remap/1.2/entity/counterparty/918e0c83-483c-11e7-7a69-93a700ee9dbd"
["type"]=>
string(12) "counterparty"
["mediaType"]=>
string(16) "application/json"
}
}
}