kksonthomas / kkson-framework
self use framework
Requires
- php: >=8.1.0
- ext-mbstring: *
- ext-mysqli: *
- almasaeed2010/adminlte: 3.*.*
- bootstrap-select/bootstrap-select: 1.12.*
- electrolinux/phpquery: 0.9.6
- filp/whoops: 2.*.*
- fortawesome/font-awesome: 4.*
- gabordemooij/redbean: ^5.7.2
- gammadia/slim-2.x: 2.6.*
- gaomingcode/ckeditor5: ^27.1
- greenlion/php-sql-parser: 4.*
- ircmaxell/password-compat: 1.0.*
- league/plates: ^3.4.0
- league/route: 2.*.*
- moment/moment: ^2.29.3
- php-curl-class/php-curl-class: 4.10.0
- phpmailer/phpmailer: v5.2.14
- phpoffice/phpspreadsheet: ^1.23.0
- respect/validation: 1.1.14
- slim/slim: 2.6.*
- swaggest/json-diff: ^3.5.0
- voku/stringy: ^6.5.3
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.8
- gd-75/php-cs-fixer-enforce-double-quotes: ^1.0
- phpstan/phpstan: ^1.6
- phpunit/phpunit: ^9.5.20
This package is auto-updated.
Last update: 2026-06-04 08:10:12 UTC
README
PHP admin/CRUD framework built on Slim 2, RedBeanPHP, Plates, and AdminLTE. Includes authentication, CRUD UI, search/export, permissions, and system logging.
Installation
composer require kksonthomas/kkson-framework
Add configuration under your application conf/ directory:
app.config.ini— environment and app settings (envselects the DB config file)db.config.{env}.ini— database connection
IP ban performance (v0.10.4.1+)
Updating the package improves IP ban behavior without any database change. Unauthenticated requests only check existing bans; failed-login counting runs after a failed login.
For faster queries on large system_log tables, apply the optional SQL patch once:
vendor/kksonthomas/kkson-framework/sql/patch-v0.10.4.1-ip-ban.sql
Example:
mysql -u USER -p DATABASE < vendor/kksonthomas/kkson-framework/sql/patch-v0.10.4.1-ip-ban.sql
The script adds system_log.client_ip, backfills simple JSON array rows, and creates indexes. Skip it if you do not need indexed IP lookups; the app remains fully functional.
On re-run, ignore duplicate column or duplicate index errors. Requires system_log and ban_ip_list tables.
Soft delete (mimic delete)
Models can soft-delete by setting _deleted = 1 instead of removing rows. Enable on a BaseModelBase subclass:
public static function _enabledMimicDelete() { return true; }
The table must have an integer _deleted column (0 = active, 1 = deleted).
Loading
Model::load($id)— active rows only (_deleted = 0).Model::load($id, true)— includes soft-deleted rows.Model::loadForUpdate($id)— same filter asload(); useloadForUpdate($id, true)to lock a deleted row.Model::isActiveInDb()— re-reads_deletedfrom the database for long-running jobs.
Saving and concurrency
R::store() runs the FUSE update() hook on boxed models. For mimic-delete tables, BaseModelBase::update() rejects a stale revive: the database row is soft-deleted (_deleted = 1) while the in-memory bean still has _deleted = 0. This prevents cross-request/cron races from undoing a delete after deleteSelf() or CRUD delete.
- Restore a row with
undeleteSelf()orsave(allowReviveDeleted: true). - Otherwise catch
KKsonFramework\RedBeanPHP\Exception\StaleDeletedModelExceptionand skip the write (typical for background jobs).
Subclasses that override update() must call parent::update() first so the guard runs.
CRUD transactions
KKsonCRUD::setIsInsertUpdateUseTransaction(true) wraps one HTTP request (insert/update/delete). It does not cover CLI, cron, or a second concurrent request. Long jobs should re-check isActiveInDb() before saving or handle StaleDeletedModelException.