Version: 1.0.10
JeffAdmin is a CakePHP 5 admin UI plugin: layout, assets, view helpers, display switches, and a Bake theme that generates list, form, and view screens in one consistent look.
Composer: kavezoo/jeffadmin
JeffAdmin’s visual foundation comes from CoolAdmin — the HTML admin template whose structure, sidebar, and card-based screens shaped the plugin’s CSS and layout.
PikeAdmin provided the idea of turning that kind of admin experience into a CakePHP-native package: Bake-driven CRUD, helpers, and a reusable plugin instead of a one-off theme copy.
JeffAdmin builds on both: CoolAdmin for how it looks, PikeAdmin for how a CakePHP admin plugin should be packaged and generated — then extends the result with Tom Select, SweetAlert delete flows, configurable $show switches, related-record tabs, and more.
- PHP 8.1+
- CakePHP 5.x
cakephp/bake(dev) — only if you bake Admin controllers/templates with the JeffAdmin theme
Create a CakePHP ~5.4 app (or use an existing one), then require the plugin:
composer create-project --prefer-dist cakephp/app:~5.4 my_app_name
cd my_app_name
composer require kavezoo/jeffadmin:^1.0
composer require --dev cakephp/bakeOr, without a version constraint (latest stable):
composer require kavezoo/jeffadmin
composer require --dev cakephp/bakeOn Windows, use php bin/cake.php … instead of the bin/cake shell script.
In config/plugins.php:
<?php
return [
// …
'JeffAdmin' => [],
];Or in src/Application.php:
public function bootstrap(): void
{
parent::bootstrap();
$this->addPlugin('JeffAdmin');
}The plugin bootstrap:
- loads
JeffAdmin.show - registers helpers:
Icon,Action,Format,Input - sets
Bake.themetoJeffAdminwhen no other bake theme is configured
Add session config at the end of config/bootstrap.php (Bake theme write is optional if the plugin already set it):
use Cake\Core\Configure;
Configure::write('Bake.theme', 'JeffAdmin');
Configure::write('Session', [
'defaults' => 'php',
'cookie' => 'NameOfCookie',
'timeout' => 4320, // 3 days
]);You do not need to load JeffAdmin helpers in src/View/AppView.php — the plugin registers them automatically.
Create src/Controller/Admin/AppController.php:
<?php
declare(strict_types=1);
namespace App\Controller\Admin;
use JeffAdmin\Controller\AppController as JeffAdminAppController;
class AppController extends JeffAdminAppController
{
public function initialize(): void
{
parent::initialize();
}
}The layout (JeffAdmin.default) comes from the plugin AppController.
In config/routes.php:
$routes->prefix('Admin', function (RouteBuilder $builder) {
$builder->setRouteClass(DashedRoute::class);
$builder->connect('/', ['controller' => 'Cities', 'action' => 'index']);
$builder->fallbacks(DashedRoute::class);
});Point the default controller/action at your own models.
bin/cake bake model all
bin/cake bake controller all --prefix Admin --no-test
bin/cake bake template all --prefix AdminSingle model:
bin/cake bake model Cities --no-test
bin/cake bake controller Cities --prefix Admin --force --no-test
bin/cake bake template Cities --prefix Admin --force- Add the prefix in
config/routes.php:
$routes->prefix('Member', function (RouteBuilder $builder) {
$builder->setRouteClass(DashedRoute::class);
$builder->connect('/', ['controller' => 'Clubs', 'action' => 'index']);
$builder->fallbacks(DashedRoute::class);
});-
Create
src/Controller/Member/AppController.phpthe same way as Admin (extendJeffAdmin\Controller\AppController). -
Bake:
bin/cake bake controller all --prefix Member --no-test
bin/cake bake template all --prefix MemberThe layout calls $this->element('JeffAdmin.nav') (and header, header_top, footer the same way).
CakePHP looks under the current prefix first. If the host file exists, it wins; otherwise the plugin default is used.
templates/Admin/element/nav.php ← your menu (copy & edit)
plugins/.../templates/element/nav.php ← plugin default
Same pattern for header.php, header_top.php, footer.php.
No bootstrap menu config. Copy vendor/kavezoo/jeffadmin/templates/element/nav.php to templates/Admin/element/nav.php and add your links.
UI assets live only in the plugin — do not copy webroot into the host.
Global defaults: plugin config/show.php → Configure::read('JeffAdmin').
Notable defaults:
index.rowIdisfalse(id column off unless you enable it)password/passwords/passwdfields are skipped by the Bake theme (forms, index, view, related tables, and header search)
Per-template override in baked files:
use Cake\Core\Configure;
$show = Configure::read('JeffAdmin');
$showLocal = [];
$showLocal['edit'] = [
// 'relatedTables' => false,
// 'deleteButton' => false,
];
$show = array_merge($show['edit'] ?? [], $showLocal['edit']);View related tabs (HasMany / BelongsToMany): section markers Related: {Alias} (start|end); active columns like index (name/title, visible, pos, created/modified, actions); other fields in /* */. Per-table override via $relatedLocal['Alias'] (e.g. deleteGuardByCounts => false). Model bake keeps // 'dependent' => true commented for optional cascade delete.
Controller settings live in a separate file from $show: plugin config/paginate.php → JeffAdmin.paginate.limit / maxLimit (default 10 / 100). Applied by the plugin AppController.
Host override: Configure::write('JeffAdmin.paginate.limit', 25). Per controller in index(): $this->paginate['limit'] = 25.
composer update kavezoo/jeffadminIf composer.json pins an exact version, widen the constraint (e.g. ^1.0) first, then update.
MIT — see LICENSE.
Enjoy JeffAdmin!
Jeff Shoemaker