kematjaya / base-controller-bundle
base component for traditional web application
Package info
github.com/kematjaya0/base-controller-bundle
pkg:composer/kematjaya/base-controller-bundle
8.0.8
2026-05-21 01:30 UTC
Requires
- doctrine/doctrine-bundle: ^2.0|^3.2
- doctrine/orm: ^2.10|^3.3|^3.5
- doctrine/persistence: ^3.3|^4.1
- giggsey/libphonenumber-for-php: ^8.12|^9.0
- haydenpierce/class-finder: ^0.5
- kematjaya/hidden-type-bundle: ^7.0|^8.0
- knplabs/knp-paginator-bundle: ^6.6
- spiriitlabs/form-filter-bundle: ^11.0|^12.0
- symfony/config: ^6.0|^7.0|^8.0
- symfony/dependency-injection: ^6.0|^7.0|^8.0
- symfony/form: ^6.0|^7.0|^8.0
- symfony/framework-bundle: ^6.0|^7.0|^8.0
- symfony/http-foundation: ^6.0|^7.0|^8.0
- symfony/http-kernel: ^6.0|^7.0|^8.0
- symfony/property-access: ^7.0|^8.0
- symfony/translation-contracts: ^3.5
- twig/twig: ^3.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.0
- phpstan/phpstan: ^2.0
- phpstan/phpstan-symfony: ^2.0
- phpunit/phpunit: ^11.0
- symfony/dom-crawler: ^6.0|^7.0
- symfony/var-dumper: ^6.0|^7.0
- dev-main
- 8.0.8
- 8.0.7
- 8.0.6
- 8.0.5
- 8.0.4
- 8.0.3
- 8.0.2
- 8.0.1
- 8.0
- 8.0-BETA
- 7.0.7
- 7.0.6
- 7.0.5
- 7.0.4
- 7.0.3
- 7.0.2
- 7.0.1
- 7.0
- 2.4.3
- 2.4.2
- 2.4.1
- 2.4
- 2.3.9
- 2.3.8
- 2.3.7
- 2.3.6
- 2.3.5
- 2.3.4
- 2.3.3
- 2.3.2
- 2.3.1
- 2.3
- 2.2.1
- 2.2
- 2.1.7
- 2.1.6
- 2.1.5
- 2.1.4
- 2.1.3
- 2.1.2
- 2.1.1
- 2.1.0
- 2.0.2
- 2.0.1
- 2.0
- 1.11.0
- 1.10.5
- 1.10.4
- 1.10.3
- 1.10.2
- 1.10.1
- 1.10.0
- 1.9.7
- 1.9.6
- 1.9.5
- 1.9.4
- 1.9.3
- 1.9.2
- 1.9.1
- 1.9.0
- 1.8.5
- 1.8.4
- 1.8.3
- 1.8.2
- 1.8.1
- 1.8.0
- 1.7.1
- 1.7
- 1.6
- 1.5
- 1.4
- 1.3
- 1.2
- 1.1
- 1.0
- dev-detached
This package is auto-updated.
Last update: 2026-05-21 01:31:46 UTC
README
Base component for Symfony 6/7/8 applications providing reusable CRUD controllers, pagination, filtering, and custom form types.
Requirements
- PHP >= 8.1
- Symfony 6.4+ / 7.4+ / 8.0+
Installation
composer require kematjaya/base-controller-bundle
Add to config/bundles.php:
Kematjaya\BaseControllerBundle\BaseControllerBundle::class => ['all' => true]
Usage
Controller
// src/Controller/FooController.php namespace App\Controller; use App\Entity\Foo; use App\Form\FooType; use App\Filter\FooFilterType; use App\Repository\FooRepository; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Attribute\Route; use Kematjaya\BaseControllerBundle\Controller\FilterBuilderController as BaseController; #[Route('/foo', name: 'foo_')] class FooController extends BaseController { #[Route('/', name: 'index', methods: ['GET', 'POST'])] public function index(Request $request, FooRepository $repo): Response { $form = $this->createFormFilter(FooFilterType::class); $queryBuilder = $this->buildFilter($request, $form, $repo->createQueryBuilder('this')); return $this->render('foo/index.html.twig', [ 'datas' => parent::createPaginator($queryBuilder, $request), 'filter' => $form->createView(), ]); } #[Route('/new', name: 'new', methods: ['GET', 'POST'])] public function new(Request $request): Response { $foo = new Foo(); // Ajax form processing $form = $this->createForm(FooType::class, $foo, [ 'attr' => ['id' => 'ajaxForm', 'action' => $this->generateUrl('foo_new')], ]); $result = parent::processFormAjax($request, $form); if ($result['process']) { return $this->json($result); } // Non-ajax form processing $form = $this->createForm(FooType::class, $foo, [ 'action' => $this->generateUrl('foo_new'), ]); $result = parent::processForm($request, $form); if ($result['process']) { return $this->redirectToRoute('foo_index'); } return $this->render('foo/form.html.twig', [ 'foo' => $foo, 'form' => $form->createView(), 'title' => 'new', ]); } #[Route('/{id}/show', name: 'show', methods: ['GET'])] public function show(Foo $foo): Response { return $this->render('foo/show.html.twig', [ 'foo' => $foo, ]); } #[Route('/{id}/edit', name: 'edit', methods: ['GET', 'POST'])] public function edit(Request $request, Foo $foo): Response { $form = $this->createForm(FooType::class, $foo, [ 'attr' => ['id' => 'ajaxForm', 'action' => $this->generateUrl('foo_edit', ['id' => $foo->getId()])], ]); $result = parent::processFormAjax($request, $form); if ($result['process']) { return $this->json($result); } $form = $this->createForm(FooType::class, $foo, [ 'action' => $this->generateUrl('foo_edit', ['id' => $foo->getId()]), ]); $result = parent::processForm($request, $form); if ($result['process']) { return $this->redirectToRoute('foo_index'); } return $this->render('foo/form.html.twig', [ 'foo' => $foo, 'form' => $form->createView(), 'title' => 'edit', ]); } #[Route('/{id}/delete', name: 'delete', methods: ['DELETE'])] public function delete(Request $request, Foo $foo): Response { $tokenName = 'delete'.$foo->getId(); parent::doDelete($request, $foo, $tokenName); return $this->redirectToRoute('foo_index'); } }
Form Type
// src/Form/FooType.php namespace App\Form; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; use Kematjaya\BaseControllerBundle\Type\PhoneNumberType; use Kematjaya\BaseControllerBundle\Type\DateRangeType; class FooType extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options): void { $builder->add('phone', PhoneNumberType::class, [ 'label' => 'phone', ]); $builder->add('dateRange', DateRangeType::class, [ 'label' => 'date range', 'from_options' => ['widget' => 'single_text'], 'to_options' => ['widget' => 'single_text'], ]); } }
Add to config/packages/twig.yaml:
twig: form_themes: - '@BaseController/phone_number_layout.html.twig'
Filter
Filter form based on SpiriitLabs FormFilterBundle (fork of LexikFormFilterBundle).
// src/Filter/FooFilterType.php namespace App\Filter; use Symfony\Component\Form\FormBuilderInterface; use Kematjaya\BaseControllerBundle\Filter\AbstractFilterType; class FooFilterType extends AbstractFilterType { public function buildForm(FormBuilderInterface $builder, array $options): void { $builder->add('roles', Filter\ChoiceFilterType::class, [ 'choices' => [], 'apply_filter' => $this->JSONQuery(), ]); } }
Available query helper methods (from FilterFunctionTrait):
JSONQuery()— query JSON columns with LIKEdateRangeQuery()— filter by date rangefloatRangeQuery()— filter by numeric range
Development
composer test # run PHPUnit tests composer phpstan # run static analysis (level 6) composer cs:check # check coding standards (dry-run) composer cs:fix # auto-fix coding standards