petkopara/crud-generator-bundle
A Symfony bundle that generates complete CRUD interfaces for Doctrine entities from the command line, creating controllers, forms, templates, and routes so you can scaffold admin panels and data management screens quickly.
First, the framework reality check: this is a Symfony 3 bundle, not a Laravel package. There is no service provider, no config/crud.php, no Artisan command. You cannot composer require it into a Laravel app and expect it to boot. What you can do as a Laravel developer is (a) run it in a throwaway Symfony 3.4 project to study the generated CRUD shape, or (b) port its conventions — pagination + filter form + bulk actions in one index screen — into your own Laravel resource controllers.
To try it in a Symfony 3.4 sandbox:
composer require petkopara/crud-generator-bundle
Register it in app/AppKernel.php:
$bundles = [
// ...
new Petkopara\CrudGeneratorBundle\PetkoparaCrudGeneratorBundle(),
];
No configuration file is required to start. Then point the generator at an entity:
bin/console generate:petkopara:crud
It interactively asks for the entity shortcut (e.g. AppBundle:Product), the target bundle, and route prefix, then writes a controller, a form type, and a set of Twig templates.
Where to look first, in this order:
src/AppBundle/Controller/ProductController.php. This is the most valuable artifact; it is plain Doctrine + Symfony Form code showing exactly how filtering, sorting, pagination, and bulk operations are wired together.src/AppBundle/Form/ProductType.php and the accompanying filter form.app/Resources/views/product/ (index.html.twig, edit.html.twig, new.html.twig, show.html.twig). These are Bootstrap 3.3.6 tables with a filter bar on top and a bulk-action dropdown.vendor/petkopara/crud-generator-bundle/Resources/views/ — this is what you override.First real use case: scaffold an admin back office for a single entity, log in, and confirm the index page supports search-by-field, column sorting, page-size changes, and "select all → delete" in one screen. That index screen is the entire selling point of the bundle, and it is also the thing you will spend the most time re-implementing in Laravel.
Treat the output as scaffolding, not as application code. The generator is a one-shot accelerator. The healthy workflow is: generate → read → immediately refactor anything you intend to keep. In practice this means extracting the generated indexAction into a small base controller or a trait (the Laravel analogue being a HasFilters / HasBulkActions trait on your resource controllers). If you leave the generated controller untouched, every future regeneration or template override becomes a merge conflict.
Bundle inheritance for template overrides. The Symfony 3 pattern for customizing generated views without editing vendor/ is to place a file at the same relative path under app/Resources/PetkoparaCrudGeneratorBundle/views/. For per-entity control most teams instead copy the generated templates into app/Resources/views/product/ and edit freely — the generator only writes them once. Decide up front which of the two you are doing; mixing both is the most common source of "my change didn't take effect."
Filter + pagination as a single composed request. The generated index reads three things from the query string: the filter form values, the sort column/direction, and the page. In Laravel terms this is a Request validated against a filter FormRequest, passed to a query scope, then ->paginate($perPage)->appends(request()->query()). When porting, keep the "append the query string to pagination links" detail — dropping it is why filter state silently disappears on page 2.
Bulk actions belong in a separate form. The generator renders a checkbox column plus a <form> wrapping the whole table for the bulk operation, distinct from the per-row delete buttons. Keep that separation: bulk delete should carry its own CSRF token and confirm dialog, and should be a POST to a dedicated route rather than overloading the DELETE /product/{id} route.
Guard the generated routes. Generated controllers assume an authenticated admin. Wrap the imported routes in a firewall/ROLE_ADMIN check (or @Security("is_granted('ROLE_ADMIN')") on the class) before the code ever reaches a shared environment. The generator does not add authorization for you.
Integration tip — form themes. The templates assume Bootstrap 3.3.6 markup. If your app already ships a form theme, set it explicitly in config.yml under twig.form_themes rather than relying on the bundle's defaults, otherwise you get double-wrapped form-group divs.
config/bundles.php, and the directory layout changed); on PHP 8 expect deprecation noise from generated code. Budget for a rewrite, not an upgrade.git status afterwards — hand-edited controllers and form types are exactly what you will lose.LIKE/= condition built in the repository. On a table with relation-backed filter columns you get N+1 queries per page. Add indexes on filtered columns and consider restricting the filter form to indexed fields only.bin/console debug:twig to confirm which path actually resolves, and check for a stale app/cache — template overrides are the number one cache-clear casualty.FilterType for a given entity gives you control over which fields appear in the filter bar without touching generated code).php artisan make:model -mcr plus a hand-written index action. The bundle's real contribution is the layout of that index screen — filter bar, sortable headers, per-page selector, and a bulk dropdown — so copy the UX, write the query logic yourself with Eloquent scopes, and you get the same result without the abandoned dependency.How can I help you explore Laravel packages today?