fin/user-backup-lib
UserBackupLib
Библиотека для выгрузки, удаления и восстановления данных пользователя по явному плану:
какие строки принадлежат пользователю, задаёт приложение декларацией правил, а не имя колонки
user_id. Выгрузка и удаление отбирают строки одними и теми же селекторами, поэтому бэкап
всегда покрывает то, что будет удалено.
Что в пакете
| Слой | Где | Что делает |
|---|---|---|
| План | src/Plan/* |
Правила таблиц (UserDataRule, TableAction: keep / backupAndDelete / backupOnly / detach), AST селекторов (Equals, InScope, ExistsInParent, AnyOf, MorphReference), компиляция в CompiledUserDataPlan, порядок удаления с проверкой циклов |
| Исполнение | src/Plan/Execution/* |
Обход строк keyset-курсором (в том числе составным), удаление и отвязка порциями, предохранитель по числу строк (RowLimitGuard) |
| Preflight | src/Plan/Preflight/* |
Сверка плана со схемой БД до первого изменения |
| Файлы | src/Services/FileStorageService.php |
Потоковая запись и чтение бэкапа, сжатие и шифрование порциями через Crypt (APP_KEY) |
| Сжатие | src/Services/Compression/* |
gzip встроенным zlib перед шифрованием (BackupStreamCompressor), распаковка с распознаванием по сигнатуре (BackupStreamDecoder) |
Сам план собирает приложение: провайдеры правил по доменам, профили операций, подключения.
Формат файла
- v2 (
saveBackup) — шапка@meta(владелец, версия формата и плана) и секции таблиц с подключением:{"@meta":{...},"tables":[{"connection":"mysql","table":"...","rows":[...]}]}. - v1 (
saveToFile) —{"table":[rows]}без шапки. Пишется только для совместимости и тестов, читается всегда.
Запись атомарная: файл пишется во временный, порция дописывается до конца, закрытие
проверяется, готовый файл публикуется переименованием. Недописанный бэкап не может выглядеть
готовым (BackupWriteIncompleteException, BackupFileCloseException).
Сжатие и шифрование
Зашифрованный файл (*.enc) — это строки, каждая строка — шифротекст Crypt порции
сжатого JSON. Сжатие делается до шифрования: шифротекст уже не сжимается, а base64 в
конверте Crypt раздувает данные ещё в 1,78 раза.
- Формат — gzip,
zlibуровня 6, потоково (deflate_init/inflate_init): файл целиком в память не читается. Замер на реальных бэкапах: 163 МБ JSON → 7 МБ меньше чем за секунду, итоговый файл в 13–30 раз меньше прежнего. - Файлы, записанные до сжатия, читаются без изменений: сжатый поток распознаётся по сигнатуре
gzip
1f 8bпосле расшифровки, а JSON с байта0x1fначинаться не может. - Оборванный или повреждённый сжатый поток не принимается за целый:
BackupDecompressionException(user_backup.decompression_failed, стадия и число прочитанных байт вcontext()). Ошибка сжатия —BackupCompressionException. - Незашифрованный файл (
encrypt: false) пишется простым JSON без сжатия. - Сжатие и распаковка подменяются биндингом контрактов
BackupStreamCompressorиBackupStreamDecoder;FileStorageServiceо формате сжатия не знает.
Чтение
use UserDataBackup\Contracts\FileStorageServiceInterface;
$storage = app(FileStorageServiceInterface::class);
$header = $storage->readHeader($path); // v1 → BackupHeader::legacy()
foreach ($storage->streamBackupData($path) as $entry) {
// ['connection' => ..., 'table' => ..., 'row' => [...]]
}
Что удалено
Старый движок эвристического удаления и выгрузки по колонке user_id
(UserBackupService, UserBackupServiceFactory, UserDataDeletionService, BackupProcessor,
DatabaseService, UserDataScope, конфиг user-backup.connections) удалён: его заменил план.
Гайд docs/user-backup-guide.md описывает удалённый API и оставлен
как история.
Тесты
vendor/bin/phpunit
Related Packages
Powerful PHP database abstraction layer (DBAL) with many features for database s...
Laravel Serializable Closure provides an easy and secure way to serialize closur...
Cli error handling for console/command-line PHP applications.
Version History
| Version | Released | PHP | Laravel | License |
|---|---|---|---|---|
| v3.1.0 | ^8.0 | ^8.0 | MIT | |
| v3.0.0 | ^8.0 | ^8.0 | MIT | |
| v2.4.0 | ^8.0 | ^8.0 | MIT | |
| v2.3.0 | ^8.0 | ^8.0 | MIT | |
| v2.2.0 | ^8.0 | ^8.0 | MIT | |
| v2.1.0 | ^8.0 | ^8.0 | MIT | |
| v2.0.0 | ^8.0 | ^8.0 | ||
| v1.0.1 | ^8.0 | ^8.0 |