ladmin/engine
Ladmin Engine is a Laravel package for building modular admin panels. It provides a reusable engine for scaffolded CRUD screens, resource management, and authorization-aware backend UI, helping keep admin code organized and extensible across Laravel applications.
Read this first: you almost certainly should not install ladmin/engine directly.
The package presents itself as the engine layer beneath the Hexters Ladmin admin panel. With 0 stars, 0 dependents, and a score of 0.03, it has no independent user base — it is a transitive dependency that exists to be consumed by its parent package, not by application code. Treat it as an internal library whose public surface is whatever the parent package calls.
Step 1 — install the parent, not the engine.
composer require hexters/ladmin
Then check what you actually got:
composer show hexters/ladmin
composer show --tree | grep -i ladmin
If ladmin/engine (or hexters/ladmin-engine) appears in that tree, the engine is already available to you. If it doesn't, the repo is either unpublished, abandoned, or superseded — stop here and use the parent package's own scaffolding.
Step 2 — find the real entry points. Because this is an engine, the useful surface is almost always:
vendor/ladmin/engine/src/ — read its register() and boot() to learn what it binds into the container, what config it merges, and what it publishes.composer.json → extra.laravel.providers and extra.laravel.aliases. Note that the repository name (hexters/ladmin-engine) and the package name (ladmin/engine) disagree — confirm which one Composer actually resolves before writing any require line by hand.stubs/ or src/Stubs/ directory. In admin-panel engines this is where the generated code templates live, and it tells you more about the intended workflow than any README will.config/ inside the package, for the merged config key name (likely ladmin or engine).Step 3 — first use case: scaffold one CRUD module end to end. The realistic day-one goal is a single table with index/create/edit/delete screens, then reading the generated output to learn the engine's conventions. Publish assets and config, run the parent package's setup/install command, then generate one module from an existing migration:
php artisan vendor:publish --provider="Ladmin\Engine\LadminServiceProvider"
php artisan ladmin:setup # or vendor:install — check `php artisan list` for the real name
php artisan ladmin:crud # interactively pick a table
Read every file it emits before running a second generation. The generated code is the documentation.
Pattern 1 — generate, then own the output. Admin engines are scaffolding tools, not runtime frameworks. The healthy workflow is: generate a module, commit it, and edit it freely. Do not plan to regenerate over modified files — you will lose work. If the engine supports it, publish stubs once and customize the templates so every future generation matches your project's conventions (namespaces, base controller, repository layer, styling).
Pattern 2 — treat the engine as a bootstrapper in AppServiceProvider, not as an API you call. Bindings are usually container-level and configured once:
// config/ladmin.php (name is illustrative — confirm from the merged config)
return [
'path' => app_path('Ladmin'), // where generated modules land
'namespace' => 'App\\Ladmin',
'middleware' => ['web', 'auth', 'ladmin'],
'guard' => 'web',
];
Set the output path and namespace before the first generation. Changing them later means moving every generated file and every use statement.
Pattern 3 — module-per-domain, mirroring your tables. Keep generated modules thin: controller validates via a FormRequest, model stays a plain Eloquent model, and business logic goes into a service or action class outside the generated tree. This is the difference between an admin panel you can maintain and one you rewrite in six months.
Pattern 4 — layer authorization at the route/middleware level. Admin engines give you a gate for "is an admin" and rarely more. Add per-module policies on top rather than editing generated controllers to check roles inline:
Route::middleware(['web', 'auth', 'can:access-admin'])
->prefix(config('ladmin.path'))
->group(base_path('routes/ladmin.php'));
Pattern 5 — integrate through events, not edits. If the engine dispatches lifecycle hooks (post-create, post-update), subscribe to them for audit logging, cache invalidation, or search-index sync. That keeps your customizations out of generated files and survives a re-scaffold of a sibling module.
Pattern 6 — local path repository while you evaluate. Given the zero-star status, vendor it with a path repo so you can patch it without forking:
"repositories": [{ "type": "path", "url": "../ladmin-engine" }],
"require": { "ladmin/engine": "*" }
Useful for reading source under a debugger and for confirming exactly which version the parent resolves.
vendor/. Budget time for that — it is the dominant cost of adopting this package.hexters/ladmin-engine but the package is ladmin/engine. composer require hexters/ladmin-engine and composer require ladmin/engine resolve differently, and only one is real. Verify with composer show -a ladmin/engine before committing a require line.hexters/ladmin:^2.x or whatever is current) and let Composer solve the engine. Pinning both invites conflicts on the next parent upgrade.php artisan config:clear. mergeConfigFrom silently loses to a stale bootstrap/cache/config.php, and the symptom looks like "my config key does nothing."php artisan vendor:publish with no arguments first and pick from the interactive list; guessing --tag=config when the tag is ladmin-config wastes a cycle. The provider's publishes() call is the source of truth.RouteServiceProvider already loads, or expects you to register it. This is the single most common "the package is broken" false alarm.migrate before generating CRUD against those tables.composer update that overwrites the package doesn't silently reset them.dd(app(\Ladmin\Engine\SomeManager::class)) and dump the bound instance — engines frequently bind a concrete class that reads config at construction time, so stale config produces confusing nulls rather than errors.How can I help you explore Laravel packages today?