crudadmin/framework
CRUDAdmin Framework is a Laravel package for rapidly building admin panels and CRUD interfaces. It offers configurable resources, forms, data tables, filters, and access control, helping developers scaffold backend management screens and streamline day-to-day administration.
crudadmin/framework is a Laravel package that supplies the scaffolding layer for admin-panel CRUD: it registers an admin model concept and, most importantly, the migration support that turns an admin model definition into real database tables. Treat it as infrastructure you build your own admin panel on top of, not a finished admin UI.
Minimal steps:
composer require crudadmin/framework
php artisan vendor:publish --provider="CrudAdmin\Framework\CrudAdminServiceProvider" --tag=config
config/crudadmin.php first — it holds the migration path, table prefix/connection, and the list of registered admin models. If tables end up in the wrong database or with the wrong prefix, the answer is almost always here.AdminModel or implementing an AdminResource contract) that declares its columns, and then run the migration generation command:
php artisan crudadmin:migrate
(Confirm the exact signature with php artisan list | grep crudadmin — the command names are the fastest way to learn the package's actual surface.)First real use case: define a single admin model for something you already own (e.g. Product) with a handful of columns, generate its migration, inspect the produced file in database/migrations before running it, and only then php artisan migrate. That first inspection teaches you the package's column-type mapping, which is the thing you'll spend the most time fighting later.
Where to look when stuck, in order: the published config, the package's src/ migration compiler (the class that translates your model definition into a Blueprint), the generated migration itself, and only then the README.
One admin model per domain entity, kept alongside — not inside — your Eloquent models. The admin model is a schema definition, your Eloquent model is runtime behavior. Keeping them in app/Admin/Models (or whatever the config points at) avoids the common trap of trying to make one class serve both roles.
Declarative columns, then generate, then review. The workflow that holds up:
// app/Admin/Models/ProductAdminModel.php (shape will follow the package's contract)
class ProductAdminModel extends AdminModel
{
public function columns(): array
{
return [
$this->id(),
$this->string('name')->index(),
$this->text('description')->nullable(),
$this->decimal('price', 10, 2),
$this->foreignId('category_id')->constrained('categories'),
$this->timestamps(),
];
}
}
Generate the migration, read it, commit it, then run it. Never let generation be part of a deploy script that you haven't diffed — generated migrations are code, and they deserve code review.
Treat generated migrations as a starting point you own. The healthy pattern is: generate → hand-edit (add indexes, adjust column order, add a composite unique) → commit → never regenerate that file again. If you regenerate over an existing migration you will silently lose your edits. Consider a naming/timestamp convention so regenerated files are obviously new.
Pair with a service provider of your own that registers admin models explicitly rather than relying on directory scanning. Explicit registration is greppable, order-stable, and survives refactors:
// AppServiceProvider::boot()
CrudAdmin::models([
ProductAdminModel::class,
CategoryAdminModel::class,
]);
Use it as the schema half of a two-package setup if the package doesn't ship UI. Generate the tables here, and drive the actual admin screens from your own controllers/Livewire/Filament — the migration definitions become the single source of truth for "what an admin can edit," which is genuinely valuable even without a UI.
Environments: run generation locally only, commit the resulting migration, and let CI/production run plain php artisan migrate. Generation on production is a footgun.
crudadmin:migrate / crudadmin:generate between minor versions. php artisan list | grep -i crud is your source of truth, not the README.vendor/crudadmin/framework/src directly — you'll be doing that anyway, so get comfortable there early.down() methods are often shallow in generated migrations. Generated rollbacks may drop tables without dropping the indexes or foreign keys your hand-edits added. Sanity-check migrate:rollback on a scratch database before you rely on it.constrained() will fail on a table that doesn't exist yet.money() or status()), the config's migration path, and — if present — any macroable registry for custom column types. Wrapping the package behind your own base class early makes a future swap to a more maintained package far less painful."crudadmin/framework": "x.y.*" rather than ^x.y. With zero dependents there is no ecosystem pressure keeping the API stable, and a minor bump can change generated output.How can I help you explore Laravel packages today?