PHPackages                             blax-software/laravel-workkit - 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. [Utility &amp; Helpers](/categories/utility)
4. /
5. blax-software/laravel-workkit

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

blax-software/laravel-workkit
=============================

Laravel collection of helpers and utilities to reduce redundant code over multiple projects.

v1.1.1(2mo ago)1642MITPHPPHP &gt;=8.0

Since Apr 15Pushed 1mo agoCompare

[ Source](https://github.com/blax-software/laravel-workkit)[ Packagist](https://packagist.org/packages/blax-software/laravel-workkit)[ Docs](http://www.blax.at)[ RSS](/packages/blax-software-laravel-workkit/feed)WikiDiscussions master Synced today

READMEChangelogDependencies (4)Versions (5)Used By (0)

[![Blax Software OSS](https://raw.githubusercontent.com/blax-software/laravel-workkit/master/art/oss-initiative-banner.svg)](https://github.com/blax-software)

Laravel Workkit
===============

[](#laravel-workkit)

[![PHP Version](https://camo.githubusercontent.com/c43a736f738fa982a023ed7fc827895810d2ca0f353aa53674e0691bccea1034/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f7068702d253345253344382e302d626c7565)](https://php.net)[![Laravel](https://camo.githubusercontent.com/0daef7568c276be3ebf8be36baf2a38ae26298952f1de1c56251d67453e57d48/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c61726176656c2d31302e782d2d31332e782d6f72616e6765)](https://laravel.com)[![License](https://camo.githubusercontent.com/f8df3091bbe1149f398a5369b2c39e896766f9f6efba3477c63e9b4aa940ef14/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d677265656e)](LICENSE)

A Laravel collection of helpers and utilities to reduce redundant code over multiple projects.

Features
--------

[](#features)

- 💾 **Streaming DB backups** — `mysqldump | xz | openssl` in one pipe, APP\_KEY-encrypted, zero DB bytes held in PHP memory (multi-GB safe)
- ♻️ **Safe restores** — `--fresh` wipes a dirty/partial schema before importing, after taking + verifying a recovery snapshot; failed imports never leave you stranded
- 🔎 **Backup verification** — `workkit:db:verify` proves a backup decrypts + is a complete xz stream *without* a database, so "is it corrupt?" gets a real answer
- 🧹 **Retention pruning** — age-based cleanup that always keeps the N newest, so prune can never delete your last recovery point
- 📊 **Stats overview** — `workkit:stats` prints per-model row counts, the largest tables, total DB size + a queue/backup summary
- 🩺 **Queue health** — `workkit:queue:health` reports per-queue depth/age/failed jobs and exits non-zero on breach (cron-friendly)
- 📄 **Variable pagination** — a `#[VariablePaginatable]` attribute + `request()->perPage()` macro for per-route, user-overridable page sizes
- 🧩 **Reusable middleware &amp; traits** — bearer-token auth, force-JSON responses, `HasExpiration`, `HasMeta`, `HasMetaTranslation`, and small service helpers

Quick Start
-----------

[](#quick-start)

```
composer require blax-software/laravel-workkit
```

```
php artisan workkit:db:backup            # storage/backups/db_mysql_.sql.xz.enc
php artisan workkit:db:verify            # is the newest backup intact?
php artisan workkit:db:restore --fresh   # wipe + restore the newest backup
```

Backups are encrypted with a key derived from your app's `APP_KEY`; a backup is restorable only by a deployment that knows the same `APP_KEY`.

Database Backups
----------------

[](#database-backups)

A streaming, compressed, encrypted MySQL backup/restore suite. The dump, compression and encryption happen in a single shell pipe, so PHP never holds the database content in memory regardless of dump size.

### Commands

[](#commands)

CommandWhat it does`workkit:db:backup`Stream `mysqldump → xz → openssl` into `storage/backups`, write a `.meta.json` sidecar (size, sha256, params).`workkit:db:restore`Stream `openssl → xz → mysql`. Verifies the source first; `--fresh` wipes the target after a verified safety snapshot.`workkit:db:verify`Prove a backup decrypts and is a complete xz stream — no database touched.`workkit:db:prune-backups`Delete backups older than the retention window, always keeping the N newest.### Backup

[](#backup)

```
php artisan workkit:db:backup                 # default connection
php artisan workkit:db:backup --connection=mysql --xz-level=6
php artisan workkit:db:backup --verify        # confirm the backup right after writing
```

### Restore

[](#restore)

```
# Newest restorable backup into the default connection (prompts unless --force)
php artisan workkit:db:restore

# A specific file
php artisan workkit:db:restore --file=db_mysql_2026-06-28_09-21-49.sql.xz.enc

# Wipe the target first — the ONLY thing that fixes a restore failing with
# errno 150 / error 3780 against a dirty or partially-migrated schema.
php artisan workkit:db:restore --fresh
```

`--fresh` is deliberately careful, because dropping every table is irreversible:

1. The **source backup is verified** before anything is touched — a file that can't be decrypted never triggers a wipe.
2. A **pre-restore safety snapshot** of the current database is taken *and verified* (skip with `--no-safety-backup`; the restore aborts if the snapshot can't be written, rather than wiping with no recovery point).
3. Only then are all tables + views dropped — via the **same** `mysql` client and database the import uses, so the wipe and the import provably hit the same server (a `url` DSN / `unix_socket` / read-write split can't make them diverge).
4. If the import fails *after* the wipe, the command prints the exact `workkit:db:restore --file=` command to recover.

Interactively, `--fresh` asks you to type the database name to confirm; under `--force` it proceeds non-interactively for deploy scripts.

> **Why `--fresh` and not just FK checks?** A leftover table with an incompatible column type makes MySQL raise `errno 150` / error `3780` at `CREATE TABLE` even with `FOREIGN_KEY_CHECKS=0` (which restores already set). The only fix is an empty target. If a restore fails this way, the command tells you to re-run with `--fresh`.

### Verify

[](#verify)

```
php artisan workkit:db:verify                 # newest backup
php artisan workkit:db:verify --file=db_mysql_2026-06-28_09-21-49.sql.xz.enc
php artisan workkit:db:verify --all           # every backup in the directory
```

Verify proves **integrity** (decrypts with this host's `APP_KEY` + a complete, non-truncated xz stream), flags a missing mysqldump completion marker (source-truncation), and compares the on-disk sha256 against the `.meta.json`sidecar. It does **not** prove restorability — a valid backup of the wrong or empty database still verifies "OK".

### Prune

[](#prune)

```
php artisan workkit:db:prune-backups --dry-run
php artisan workkit:db:prune-backups --days=30 --keep-min=5
```

The `--keep-min` floor (default 5) is always kept regardless of age, so an aggressive `--days` can never leave you with zero backups. Schedule it:

```
Schedule::command('workkit:db:prune-backups')->daily();
```

### Configuration

[](#configuration)

```
php artisan vendor:publish --tag=workkit-config
```

KeyEnvDefaultPurpose`backup.path``WORKKIT_BACKUP_PATH``storage/backups`Where backups live`backup.retention_days``WORKKIT_BACKUP_RETENTION_DAYS``30`Age cutoff for prune`backup.retention_min_keep``WORKKIT_BACKUP_RETENTION_MIN_KEEP``5`Newest backups always kept`backup.xz_level``WORKKIT_BACKUP_XZ_LEVEL``3`xz compression level (0–9)### Requirements

[](#requirements)

The host needs `mysqldump`, `mysql`, `xz`, `openssl` and `bash` on `PATH` — standard on any reasonable Linux server. A non-empty `APP_KEY` is required (backups are unrecoverable without the key that produced them).

### Restoring without the package

[](#restoring-without-the-package)

The output is plain `openssl enc -salt` format, so any host with the same `APP_KEY` can restore it directly:

```
openssl enc -d -aes-256-cbc -pbkdf2 -iter 600000 -pass env:WK_KEY \
  -in db_mysql_2026-06-28_09-21-49.sql.xz.enc | xz -d | mysql
# WK_KEY = your APP_KEY with the "base64:" prefix stripped
```

Ops &amp; Observability
-----------------------

[](#ops--observability)

### Stats overview

[](#stats-overview)

```
php artisan workkit:stats                  # models + largest tables + DB size + queue/backup summary
php artisan workkit:stats --exact          # true COUNT(*) per table (heavier) instead of the estimate
php artisan workkit:stats --models --json  # just per-model counts, machine-readable
php artisan workkit:stats --tables --limit=30
```

Model row counts are **estimated** from `information_schema` on MySQL (instant); pass `--exact` for a real `COUNT(*)`. Models are auto-discovered from `app/Models` — override with `config('workkit.stats.models')` (an explicit FQCN list) or `models_path`. Table/DB **sizes** are MySQL-only and degrade to "n/a" elsewhere.

### Queue health

[](#queue-health)

```
php artisan workkit:queue:health                       # human table; exits 0 / non-zero
php artisan workkit:queue:health --json || notify-ops  # cron / monitoring probe
php artisan workkit:queue:health --max-age=10 --max-depth=500 --max-failed=50
```

For the `database` queue driver it reports per-queue **pending / due / delayed / reserved** counts and the **oldest due job's age**, plus failed jobs (total + last *N* hours). It flags a queue **STALLED** — due work older than `max_age_minutes` with nothing reserved (the worker is probably down) — and **exits non-zero on any breach** so it slots straight into cron or a health probe. Thresholds live under `config('workkit.queue.*')`, with per-queue depth overrides for intentionally-slow queues. Schedule it:

```
Schedule::command('workkit:queue:health')->everyFiveMinutes();
```

Changelog
---------

[](#changelog)

See [CHANGELOG.md](CHANGELOG.md).

Star History
------------

[](#star-history)

[    ![Star History Chart](https://camo.githubusercontent.com/73f133f203e673d0af7a2625972225b6cdb093b4ef84e2d2a5d386eb42658f71/68747470733a2f2f6170692e737461722d686973746f72792e636f6d2f63686172743f7265706f733d626c61782d736f6674776172652f6c61726176656c2d776f726b6b697426747970653d64617465266c6567656e643d746f702d6c656674) ](https://www.star-history.com/?repos=blax-software%2Flaravel-workkit&type=date&legend=top-left)

###  Health Score

41

—

FairBetter than 87% of packages

Maintenance90

Actively maintained with recent releases

Popularity17

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity42

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% 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 ~5 days

Total

4

Last Release

64d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/2d548acfc3520e2f810e35cfb78230f885befda9fa26a3be42353723c48f991e?d=identicon)[blax-software](/maintainers/blax-software)

---

Top Contributors

[![justsomexanda](https://avatars.githubusercontent.com/u/48434066?v=4)](https://github.com/justsomexanda "justsomexanda (28 commits)")

###  Code Quality

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/blax-software-laravel-workkit/health.svg)

```
[![Health](https://phpackages.com/badges/blax-software-laravel-workkit/health.svg)](https://phpackages.com/packages/blax-software-laravel-workkit)
```

###  Alternatives

[unopim/unopim

UnoPim Laravel PIM

10.5k2.4k](/packages/unopim-unopim)[blair2004/nexopos

The Free Modern Point Of Sale System build with Laravel, TailwindCSS and Vue.js.

1.2k2.4k](/packages/blair2004-nexopos)

PHPackages © 2026

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