PHPackages                             kematjaya/base-controller-bundle - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Framework](/categories/framework)
4. /
5. kematjaya/base-controller-bundle

ActiveLibrary[Framework](/categories/framework)

kematjaya/base-controller-bundle
================================

base component for traditional web application

8.0.8(1mo ago)32.3k1MITPHP

Since Nov 20Pushed 1mo ago1 watchersCompare

[ Source](https://github.com/kematjaya0/base-controller-bundle)[ Packagist](https://packagist.org/packages/kematjaya/base-controller-bundle)[ RSS](/packages/kematjaya-base-controller-bundle/feed)WikiDiscussions main Synced today

READMEChangelogDependencies (41)Versions (78)Used By (1)

base-controller-bundle
======================

[](#base-controller-bundle)

Base component for Symfony 6/7/8 applications providing reusable CRUD controllers, pagination, filtering, and custom form types.

Requirements
------------

[](#requirements)

- PHP &gt;= 8.1
- Symfony 6.4+ / 7.4+ / 8.0+

Installation
------------

[](#installation)

```
composer require kematjaya/base-controller-bundle
```

Add to `config/bundles.php`:

```
Kematjaya\BaseControllerBundle\BaseControllerBundle::class => ['all' => true]
```

Usage
-----

[](#usage)

### Controller

[](#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

[](#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)

Filter form based on [SpiriitLabs FormFilterBundle](https://github.com/SpiriitLabs/form-filter-bundle) (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 LIKE
- `dateRangeQuery()` — filter by date range
- `floatRangeQuery()` — filter by numeric range

Development
-----------

[](#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
```

###  Health Score

51

—

FairBetter than 95% of packages

Maintenance91

Actively maintained with recent releases

Popularity20

Limited adoption so far

Community12

Small or concentrated contributor base

Maturity69

Established project with proven stability

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~26 days

Total

76

Last Release

43d ago

Major Versions

1.11.0 → 2.02021-07-26

2.4.2 → 7.02024-10-22

2.4.3 → 7.0.62024-12-04

7.0.7 → 8.0-BETA2026-01-18

8.0.3 → 9.0.42026-02-04

### Community

Maintainers

![](https://www.gravatar.com/avatar/f2cf191329e1adc930a168a7d3baeda8517b7982184820692163a5baa72e3965?d=identicon)[kematjaya0](/maintainers/kematjaya0)

---

Top Contributors

[![kematjaya0](https://avatars.githubusercontent.com/u/36223951?v=4)](https://github.com/kematjaya0 "kematjaya0 (48 commits)")

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StylePHP CS Fixer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/kematjaya-base-controller-bundle/health.svg)

```
[![Health](https://phpackages.com/badges/kematjaya-base-controller-bundle/health.svg)](https://phpackages.com/packages/kematjaya-base-controller-bundle)
```

###  Alternatives

[easycorp/easyadmin-bundle

Admin generator for Symfony applications

4.3k17.9M386](/packages/easycorp-easyadmin-bundle)[open-dxp/opendxp

Content &amp; Product Management Framework (CMS/PIM)

9421.6k61](/packages/open-dxp-opendxp)[sylius/sylius

E-Commerce platform for PHP, based on Symfony framework.

8.5k5.9M737](/packages/sylius-sylius)[2lenet/crudit-bundle

The easy like Crud'it Bundle.

1616.4k14](/packages/2lenet-crudit-bundle)[oro/platform

Business Application Platform (BAP)

645143.5k115](/packages/oro-platform)[contao/core-bundle

Contao Open Source CMS

1231.6M2.8k](/packages/contao-core-bundle)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
