Сущности
Объекты, в которые SDK превращает ответы сервера. Все они неизменяемы (readonly) и
описывают состояние на момент ответа; чтобы увидеть новое состояние, используйте то, что
вернул метод изменения, или перечитайте объект.
Общее
Даты — DateTimeImmutable с часовым поясом сервера.
Перечисления — объекты PHP-перечислений (Retention::WEEK), а не числа. См.
Опции и перечисления.
JSON. Каждая сущность реализует JsonSerializable и метод toArray(), поэтому её можно
сразу отдать в ответ: ResponseEntity::ok($file). В JSON даты — строки ISO 8601
(2026-11-07T14:54:51+00:00), перечисления — имена ("WEEK"), вложенные объекты — массивы.
json_encode($folder);
// {"name":"avatars","public":true,"retention":"NONE",
// "cache":{"maxAge":null,"visibility":null},
// "createdAt":"2026-11-07T14:54:51+00:00","updatedAt":"2026-11-07T14:54:51+00:00"}Проверка ответа. Если в ответе сервера нет нужного поля или у него не тот тип, SDK бросает
ResponseException с путём к полю — например, S5W v1/check: bytes.quota must be int, got string.
File
Файл в бакете.
| Поле | Тип | Описание |
|---|---|---|
id |
string |
16 символов A-Za-z0-9_-; по нему файл адресуется везде. На сервере — slug. Не меняется при переименовании и переносе |
name |
string |
имя; уникально в папке |
folder |
?string |
имя папки; null — корень бакета |
content |
FileContent |
размер, тип, расширение, хеш |
public |
bool |
доступен ли по publicUrl без ключа; следует за папкой |
deduplicated |
bool |
такие байты в бакете уже были — место на диске не потрачено |
processed |
?Processing |
отчёт об обработке картинки; только в ответе на загрузку, при чтении — null |
expiresAt |
?DateTimeImmutable |
когда файл удалит срок хранения папки; null — не удалится сам |
privateUrl |
string |
адрес /p/{id} — отдаёт файл с любым ключом в заголовке Authorization |
publicUrl |
?string |
адрес /o/{bucketId}/{id} — без ключа; null, пока файл не публичный |
createdAt |
DateTimeImmutable |
когда загружен |
updatedAt |
DateTimeImmutable |
когда изменён (имя, папка) |
Адреса строятся от PUBLIC_BASE_URL сервера — см. настройку S5W.
File::ID_PATTERN, File::isValidId()
Формат id: /^[A-Za-z0-9_-]{16}$/. Метод проверяет только форму, а не существование файла —
удобно, чтобы отсеять мусор из адреса страницы до запроса.
public const string ID_PATTERN = '/^[A-Za-z0-9_-]{16}$/';
public static function isValidId(string $id): boolFile::isValidId('FXOkqegbdrNRWQgc'); // true
File::isValidId('../etc/passwd'); // falseFileContent
Байты файла. Два файла с одинаковым содержимым ссылаются на одни и те же байты.
| Поле | Тип | Описание |
|---|---|---|
size |
int |
размер в байтах |
mime |
string |
MIME-тип, определённый сервером по содержимому |
extension |
string |
расширение, соответствующее типу; может быть пустым |
hash |
string |
SHA-256 содержимого, 64 символа в нижнем регистре |
Processing
Что сервер сделал с картинкой при загрузке.
| Поле | Тип | Описание |
|---|---|---|
applied |
bool |
была ли обработка |
reason |
?string |
почему не было: no options, nothing to do, animated, output is larger than source; null, если была |
operations |
list<string> |
что сделано, например ["resize:400x267", "encode:webp@80"] |
source |
?ImageInfo |
исходная картинка; null, если обработки не было |
result |
?ImageInfo |
результат; null, если обработки не было |
Методы
saved(): int — сколько байт сэкономлено: source->size - result->size. Отрицательное, если
результат тяжелее; 0, если обработки не было.
ImageInfo
| Поле | Тип | Описание |
|---|---|---|
width |
int |
ширина, пикселей |
height |
int |
высота, пикселей |
size |
int |
размер, байт |
mime |
string |
MIME-тип |
Folder
Папка. Один уровень, без вложенности; имя уникально в бакете.
| Поле | Тип | Описание |
|---|---|---|
name |
string |
имя |
public |
bool |
файлы внутри доступны без ключа |
retention |
Retention |
срок хранения файлов |
cache |
CachePolicy |
политика кэша папки |
createdAt |
DateTimeImmutable |
когда создана |
updatedAt |
DateTimeImmutable |
когда изменена |
Folder::ROOT
Корень бакета там, где ожидается папка.
public const string ROOT = '/';Значение / не может быть именем настоящей папки, поэтому путаницы нет. Где действует:
| Метод | Что значит Folder::ROOT |
|---|---|
files()->list(), files()->all() |
только файлы без папки |
files()->move(), files()->update() |
перенести в корень (файл станет публичным) |
files()->upload(), uploads()->send() и другие загрузки |
загрузить в корень — то же, что null |
CachePolicy
Переопределение кэша на уровне папки. Каждое поле со значением null наследуется от бакета.
| Поле | Тип | Описание |
|---|---|---|
maxAge |
?int |
max-age, секунд |
visibility |
?CacheVisibility |
кто может кэшировать |
Методы
isInherited(): bool — true, если оба поля null: папка ничего не переопределяет.
Page
Одна страница списка. Повторяет формат сервера { meta, data }.
| Поле | Тип | Описание |
|---|---|---|
items |
list<T> |
элементы этой страницы (File или Folder) |
current |
int |
номер страницы, с 1 |
size |
int |
размер страницы, который применил сервер |
total |
int |
сколько элементов всего под фильтром, на всех страницах |
pages |
int |
сколько всего страниц |
previous |
?int |
номер предыдущей страницы или null |
next |
?int |
номер следующей страницы или null |
Методы
hasNext(): bool — есть ли следующая страница.
isEmpty(): bool — пуста ли эта страница.
count($page) — сколько элементов на этой странице (Countable). Не путать с total.
foreach ($page as $item) — обход элементов этой страницы (IteratorAggregate).
map(callable $fn): Page — новая страница, где каждый элемент прошёл через $fn; мета
сохраняется. Удобно, чтобы превратить сущности в свои DTO.
toArray() / jsonSerialize() — { meta: { current, size, total, pages, previous, next }, data: [...] }.
$page = $s5w->files()->list(limit: 10);
count($page); // 10 — на этой странице
$page->total; // 134 — всего
$page->hasNext(); // true
$names = $page->map(fn(File $f) => $f->name);
json_encode($names); // {"meta":{…},"data":["a.txt","b.txt",…]}previous за последней страницей
Если запросить страницу дальше последней, сервер вернёт пустой список, но previous будет
равен current - 1 — например, 998 при pages = 1. Для навигации надёжнее опираться на
pages.
UploadSession
Состояние загрузки частями. Каждый вызов uploads() возвращает новую сессию с текущим
смещением сервера.
| Поле | Тип | Описание |
|---|---|---|
id |
string |
UUID сессии; пустая строка, если сработала дедупликация |
name |
string |
имя, заявленное при старте |
size |
int |
заявленный размер, байт |
offset |
int |
сколько байт уже на сервере — отсюда начинается следующая часть |
chunkSize |
int |
каким размером сервер просит слать части; 0 при дедупликации |
expiresAt |
?DateTimeImmutable |
когда сессию удалят без новых частей; null при дедупликации |
file |
?File |
готовый файл, если содержимое уже было в бакете |
Методы
isDeduplicated(): bool — содержимое было в бакете, файл готов, передавать нечего.
isComplete(): bool — все байты на сервере (offset >= size), можно собирать.
remaining(): int — сколько байт осталось отправить.
KeyInfo
Ответ check(): что стоит за ключом.
| Поле | Тип | Описание |
|---|---|---|
bucket |
BucketRef |
бакет ключа |
access |
TokenAccess |
уровень доступа |
expiresAt |
?DateTimeImmutable |
когда ключ истечёт; null — бессрочный |
storage |
Storage |
место в бакете |
Методы
expiresBefore(DateTimeInterface $at = now): bool — истечёт ли ключ к моменту $at.
if ($s5w->check()->expiresBefore(new DateTimeImmutable('+7 days'))) {
$logger->warning('Ключ S5W истекает в течение недели');
}BucketRef
| Поле | Тип | Описание |
|---|---|---|
id |
string |
UUID бакета; это {bucketId} в публичных адресах /o/{bucketId}/{id} |
name |
string |
имя бакета |
Storage
Место в бакете, в байтах.
| Поле | Тип | Описание |
|---|---|---|
quota |
int |
квота |
used |
int |
занято |
free |
int |
свободно |
Методы
fits(int $bytes): bool — поместится ли ещё $bytes байт.
usage(): float — доля занятого, от 0.0 до 1.0.