rezaamini-ir/laravel-easypanel
Laravel EasyPanel integrates the EasyPanel server management panel with your Laravel app, providing a fluent API and Artisan commands to manage projects, deployments, services, and Docker-based resources—ideal for automating provisioning and deployments.
2.0.0 is a breaking release — treat this as a re-integration of the package rather than a version bump. Start by reading the upgrade section of the docs (the release ships a separate EasyPanel doc site) before touching your config.
composer require badaso/easy-panel:^2.0 (or your fork/vendor). Commit composer.lock separately from your config/code changes so you can bisect.php artisan vendor:publish --tag=easypanel-config and the migration/asset tags, then diff the new config/easypanel.php against yours. The "admin management strategy" change means your auth model, admin table, and guard wiring almost certainly differ from 1.8.php artisan crud:generate ...), and diff the generated controller/view against your 1.8 version. This single diff tells you everything about the new Field/Input API, policy wiring, and view structure in one pass.Where to look first, in order: config/easypanel.php → the generated controller for one CRUD → the generated policy → resources/views/vendor/easypanel overrides you already have.
Config-driven auth and guard. With the guard now customizable, set the guard/admin model once in config and let generated controllers, middleware, and policies read from it. Don't hardcode auth()->guard('admin') in your own controllers — centralize it so a later guard swap doesn't cascade.
ACL vs. policies — pick one lane per CRUD. The release gives both a role/permission ACL layer and Laravel policy authorization on generated CRUDs. Use policies as the enforcement point (they compose with Gate::authorize, can: middleware, and Blade @can), and treat roles/permissions as the assignment UI that populates them. Mixing raw permission checks and policy checks on the same resource is how you get "works in the admin panel, 403s in the API" bugs.
Roles managed in the GUI, defined in code. The role manager page is great for assigning roles to users; keep the permission list itself seeded/migrated (a seeder that enumerates resource.action permissions) so environments stay reproducible. GUI-created roles drift across staging/prod otherwise.
Fields and inputs as composable objects. The new Field and Input classes are the main extension point. Pattern:
Field = the column/attribute (name, label, validation, visibility per form context).Input = the renderer (text, date, time, datetime, multi-select, select with data provider).MyFields::status()) returning preconfigured Field objects so your team isn't hand-assembling them in every crud:generate call site.Data providers for selects. For anything beyond a static option list, back selects/multi-selects with a provider that returns id => label and respects scoping (tenant, active-only). Keep provider queries select(['id','name']) and cached where the list is stable — admin forms hydrate several of these per page.
Translations in the GUI, keys in files. The translation management GUI writes to language files at runtime. Treat JSON/PHP lang files as data in dev, but in production prefer read-only deploys and manage translations through your normal deploy pipeline — or at minimum ensure the lang directory is writable and backed up.
Date/time inputs. The expanded input set (date, time, datetime) needs an explicit cast + format contract on the model and a matching input format, or you get silent 0000-00-00/Carbon-parse failures. Standardize the format in one config value and reference it from both sides.
Multi-select needs a pivot plan. A multi-select input implies many-to-many or JSON-cast storage. Decide per field before generating: pivot table + belongsToMany (queryable, joins work) vs. JSON column (simpler, but painful to filter and index). Retrofitting this later means regenerating and migrating.
Policy scaffolding in CI. Generated policies are a good starting point but usually need real ability logic (viewAny scoping by tenant/team). Add a test that hits each CRUD ability as an unauthorized user — the generator won't catch a policy that always returns true.
Field/Input classes, and the customizable guard all invalidate 1.8-generated controllers and views. Regenerate rather than hand-patch, then re-apply your customizations from a diff — keeping custom code in published views/models, not in generated files, is what makes this survivable.php artisan config:clear && php artisan route:clear && php artisan view:clear. Most "the guard change did nothing" reports are a stale bootstrap/cache/config.php.view:clear and any published-view overrides must be re-checked, or you'll get "undefined variable" errors from 1.8 templates rendering against 2.0 controllers.@can in the view — the generator wires both, and they can drift.id => label renders an empty dropdown with no error.php artisan cache:clear or your permission-cache command) or changes won't take effect.lang/ path. On read-only container filesystems the save silently fails or 500s — mount it writable in dev, or disable the editor in prod.config/easypanel.php, custom Input/Field subclasses, published views under resources/views/vendor/easypanel, and data providers. Anything you edit directly inside vendor/ or inside a freshly generated controller is lost on the next crud:generate.How can I help you explore Laravel packages today?