Installation
Add the bundle to your composer.json:
composer require cpana/generator-bundle
Register the bundle in config/bundles.php:
return [
// ...
CPANA\GeneratorBundle\CPANAGeneratorBundle::class => ['all' => true],
];
First Use Case
Generate a CRUD for an existing entity (e.g., Author) with bidirectional relations:
php bin/console generate:doctrine:crud --entity=Author --with-write --with-show
The bundle will automatically include related entities (e.g., Book) in the show view with action buttons.
Where to Look First
Resources/doc/index.md (check for custom templates or overrides).templates/ (e.g., templates/Author/show.html.twig).config/packages/cpana_generator.yaml (if provided).Generating CRUD with Relations Use the command to scaffold a CRUD for an entity with bidirectional relations:
php bin/console generate:doctrine:crud --entity=Author --with-show --with-write
The bundle will:
ArrayCollection properties (e.g., $books).Book) into the show view.Customizing Relation Display Override the default Twig template for relation rendering:
{# templates/Author/show.html.twig #}
{% extends 'generator_crud/show.html.twig' %}
{% block relation_books %}
<h3>Custom Books Section</h3>
{% for book in author.books %}
<div>{{ book.title }} [{{ path('app_book_edit', {'id': book.id}) }}]</div>
{% endfor %}
{% endblock %}
Adding New Relation Actions Extend the bundle’s action generation by creating a custom command or overriding the base generator:
# config/packages/cpana_generator.yaml
cpana_generator:
relations:
Author:
books:
add_route: 'app_author_add_book' # Custom route for "Add Book"
Integration with Forms
Ensure forms are namespaced under Type (not Form) by default. Extend the base form type:
// src/Form/Type/AuthorType.php
namespace App\Form\Type; // Must be under 'Type'
use Symfony\Component\Form\AbstractType;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
class AuthorType extends AbstractType {
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder->add('books', EntityType::class, [
'class' => 'App\Entity\Book',
'multiple' => true,
]);
}
}
ParamConverter for Actions
Leverage @ParamConverter in controllers for automatic entity hydration:
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
class AuthorController extends AbstractCRUDController {
/**
* @ParamConverter("book", options={"mapping": {"id": "request", "get": "get"}}, class="App\Entity\Book")
*/
public function addBookAction(Author $author, Book $book = null) {
$author->addBook($book);
// ...
}
}
Namespace Mismatch for Forms
Form (not Type) may break relation rendering.AbstractType and are placed in src/Form/Type/.Bidirectional Relation Detection
mappedBy/inversedBy is misconfigured in Doctrine.Book entity has:
/**
* @ORM\ManyToOne(targetEntity="Author", inversedBy="books")
*/
private $author;
Template Overrides Not Applied
templates/ are ignored.php bin/console cache:clear
Or explicitly target the bundle’s namespace in Twig:
{% extends 'generator_crud:Author/show.html.twig' %}
Route Generation Conflicts
app_author_add_book) clash with existing ones.Date/Time Formatting
config/packages/cpana_generator.yaml:
cpana_generator:
datetime_format: 'd/m/Y H:i:s'
Check Generated Templates Dump the rendered template to debug relation blocks:
{{ dump(app.request) }}
{% block relation_books %}{% endblock %}
Log Relation Data Add a debug controller to inspect entity relations:
public function debugRelations(Author $author) {
\Symfony\Component\Debug\Debug::dump($author->getBooks());
}
Enable Generator Debug Mode Set in config to log generation steps:
cpana_generator:
debug: true
Custom Relation Renderers Override the relation rendering logic by extending the base template:
{# templates/generator_crud/relations.html.twig #}
{% for relation in relations %}
{% if relation.name == 'books' %}
{% include 'Author/_custom_books.html.twig' %}
{% else %}
{% include 'generator_crud/relations/_default.html.twig' %}
{% endif %}
{% endfor %}
Add New Relation Actions Extend the bundle’s command or create a custom generator:
// src/Command/CustomRelationCommand.php
use CPANA\GeneratorBundle\Command\AbstractGeneratorCommand;
class CustomRelationCommand extends AbstractGeneratorCommand {
protected function configure() {
$this->setName('generate:custom-relation');
}
protected function execute(InputInterface $input, OutputInterface $output) {
// Add logic for custom relation buttons (e.g., "Delete Book")
}
}
Modify ParamConverter Behavior
Override the base controller to customize @ParamConverter:
class CustomAuthorController extends AbstractCRUDController {
public function __construct() {
$this->paramConverterOptions = [
'book' => ['class' => 'App\Entity\Book', 'mapping' => ['id' => 'request']],
];
}
}
Hook into Generation Events Use Symfony events to intercept generation (if the bundle supports it):
// src/EventListener/GeneratorListener.php
use CPANA\GeneratorBundle\Event\GenerateEvent;
class GeneratorListener {
public function onGenerate(GenerateEvent $event) {
$event->addRelationAction('books', 'delete', 'app_book_delete');
}
}
Register the listener in services.yaml:
services:
App\EventListener\GeneratorListener:
tags:
- { name: kernel.event_listener, event: cpana.generator.generate, method: onGenerate }
How can I help you explore Laravel packages today?