kenny1911/ajax-bundle
Symfony bundle that streamlines AJAX handling in your applications, offering ready-made utilities for processing asynchronous requests and returning JSON responses. Simplifies wiring front-end calls to Symfony controllers so you can build dynamic interfaces with less boilerplate.
First, a scoping check: kenny1911/ajax-bundle is a Symfony bundle, not a Laravel package. If you are working in a Laravel codebase, this package cannot be installed into it — Laravel has no bundle/DI-extension concept, and the equivalent functionality is already built in via $request->ajax(), $request->wantsJson(), and the Accept header middleware. The rest of this assessment assumes a Symfony application.
Minimal steps:
composer require kenny1911/ajax-bundle and immediately pin the resolved version in composer.json ("kenny1911/ajax-bundle": "x.y.z" rather than ^x.y). With zero dependents there is no ecosystem pressure to keep the API stable.config/bundles.php (Kenny1911\AjaxBundle\...Bundle::class => ['all' => true]) — there is no Symfony Flex recipe, so nothing will be auto-registered and nothing will appear in config/packages/ for you.README.md → composer.json (PHP and symfony/* version constraints; this is the fastest compatibility verdict) → src/ for the public surface (look for a DependencyInjection/ extension and Resources/config/services.yaml) → tests/ for the actual behavioural contract, which is more trustworthy than the README in a low-adoption package.$request->isXmlHttpRequest() (which core Symfony has provided since 2.x) — if it is only header sniffing, the bundle is not earning its dependency.Conditional response in a controller. The canonical daily pattern is a single action serving both an HTML page and a JSON payload:
if ($this->ajax->isAjax($request)) {
return $this->json(['items' => $items]);
}
return $this->render('items/index.html.twig', ['items' => $items]);
Wrap this behind your own small service (App\Ajax\AjaxResponder) rather than injecting the bundle service directly into every controller. That one indirection is what makes the bundle replaceable later — and given the maintenance profile, you should assume it will be.
Listener over controller checks. If the bundle ships a kernel.request/kernel.response subscriber, prefer letting it normalise the response (e.g. forcing Content-Type: application/json or mapping exceptions to JSON error envelopes) so controllers stay thin. Verify registration with bin/console debug:event-dispatcher and bin/console debug:container <service-id> before writing code against it — a mis-registered bundle fails silently, not loudly.
Consistent envelope + response factory. Put your own { data, meta, errors } shape in a project service and let the bundle only handle detection. Detection is the trivial, replaceable part; the envelope is your domain contract.
Testing. Functional tests are straightforward: build a request and set the header the bundle keys off (X-Requested-With: XMLHttpRequest) via $client->request('GET', '/items', [], [], ['HTTP_X_REQUESTED_WITH' => 'XMLHttpRequest']). Write these tests first — they become your safety net if you later vendor the code or swap it out.
Integration tip. If the bundle exposes configuration, the extension alias (from DependencyInjection/*Extension::getAlias()) determines the YAML root key — it is not always the bundle's short name.
composer show kenny1911/ajax-bundle for what actually resolved and whether a tag (vs. a dev-main branch alias) is what you installed.X-Requested-With is the classic trap. fetch() does not send it by default — only jQuery and some libraries do. If your front end uses fetch, axios, or HTMX, you must set the header explicitly or detection silently returns "not AJAX" and you get an HTML fragment injected where JSON was expected. Decide early whether you standardise on X-Requested-With, Accept: application/json, or a Turbo/HTMX-specific header, and make the bundle detection match that choice.Request::isXmlHttpRequest() and Request::getPreferredFormat() exist in Symfony core. Audit the package's src/ for what is genuinely additive before accepting the dependency; with a 0-dependent bundle, "replace with three lines of core code" is often the correct architectural call.decorates:), compiler passes, and listener priority — all better than forking. If you must fork, use a VCS repository entry in composer.json against your own fork and tag it, so composer.lock stays reproducible.debug:container for the service, debug:event-dispatcher for the subscriber, debug:router if it ships routes, and bin/console cache:clear after editing config/bundles.php — a stale container is the most common cause of "the bundle seems not to load."How can I help you explore Laravel packages today?