modera/direct-bundle
A small Modera bundle that integrates Direct functionality into Symfony/PHP applications, providing bundle configuration and service wiring for quick setup in projects already using Modera components.
Reality check first. modera/direct-bundle is a Symfony bundle (2.x/3.x era, last tagged 2016-05-31), not a Laravel package. There is no service provider, no config/direct.php, no facade, no artisan command. composer require modera/direct-bundle in a Laravel app gets you a package whose bootstrapping expects Symfony\Component\HttpKernel\Bundle\Bundle, XML service definitions, and a KernelInterface. Unless you are maintaining a legacy Symfony app with an ExtJS frontend, the day-to-day leverage here is close to zero — treat it as a reference implementation of the ExtDirect protocol on PHP, not a dependency.
If you actually are on the target stack:
app/AppKernel.php, then confirm the routing import actually loaded:
php app/console debug:router | grep -i direct
If nothing shows up, the bundle's routing file wasn't imported and nothing else will work.DependencyInjection/Configuration.php — the only authoritative source for provider config keys (they moved between the 2014 and 2016 tags).Resources/config/services.xml — shows whether providers are resolved by service ID, by controller class, or by a compiler-pass tag.?provider=x, returns Ext.app.REMOTING_API) and the batched RPC POST in the same action.Ext.direct.Manager.addProvider(Ext.app.REMOTING_API);
then call one method from the JS console before wiring it into a grid.The first genuinely useful use case is replacing hand-written Ext.Ajax.request plumbing for one grid/store: expose list/read and save on an existing controller, point an Ext.data.proxy.Direct at it, and you get batched create/update/destroy in a single round trip.
If you are on Laravel: don't install it. Spend a half-day reading the protocol layer end-to-end and produce a conformance checklist of what the existing client depends on. That checklist — not the composer package — is your starting artifact.
Symfony-native usage. The bundle wires three moving parts, and every real workflow rides one of them:
Ext.app.REMOTING_API / your own) to a set of PHP actions. Providers are declared in config and resolved through the DI container — by service id or class, depending on the tag. The registry is the contract between descriptor generation and dispatch; keep them derived from the same config.Client.Users.list(). This means your existing Symfony controller can already be the action class — no separate DTO, no REST serialization. That is the leverage.?provider=x (returns api.js descriptor) and POST (batched JSON dispatch). Route it behind the same session/CSRF/auth firewall as the rest of your admin.Laravel bridge (recommended pattern). Treat the Symfony bundle as spec, not code. The reusable core is ~300–600 lines:
POST /direct route → route model binding is irrelevant; you parse {action, method, data, tid} envelopes in the request.action/method against a registry of callables, and returns a per-call envelope:
// success
['type' => 'rpc', 'tid' => $tid, 'action' => $action, 'method' => $method, 'result' => $result]
// exception — still inside HTTP 200
['type' => 'exception', 'tid' => $tid, 'action' => $action, 'method' => $method,
'message' => '…', 'where' => '…']
GET /direct/api.js that generates Ext.app.REMOTING_API from the same registry. Never let the descriptor and the dispatcher drift — a cached descriptor calling a deleted method yields opaque runtime method not found errors.Per-action authorization. ExtDirect is batched, so a single HTTP request can carry many logical calls with different permission requirements. Laravel's single-route middleware model doesn't express this. Resolve authorization inside the dispatcher, per call, before execution, and return a denial as that call's exception envelope — not a 403 for the whole batch.
Adapter isolation. If you must run the bundle in-process for a dual-run phase, install it in an isolated Symfony microservice or separate PHP-FPM pool with its own composer.json, and proxy to it. Never put a 2016 dependency graph into Laravel's vendor tree — the transitive Symfony constraints will fight Laravel's own.
[READ-ONLY] subtree split. This repo is a split of an upstream monorepo. Any patch goes upstream to a project dormant ~nine years. Practically: you are vendoring and owning the code — assign a named owner.create_function-era idioms, and untyped internals. On 8.1+ budget for a fork on day one, plus Composer platform constraints that refuse to resolve against Laravel 10/11.?provider=x and the batched POST hit the same action. If you debug only the POST you'll never understand why the client boots into method-not-found errors — test the descriptor URL in isolation.message/where.post_max_size and produce a silent empty request that looks like an auth bug — log the raw body size before dispatch.api.js (or bust cache on registry change). Stale descriptors are the #1 source of "worked yesterday, broken today" ExtJS tickets.debug:router, debug:container to inspect provider/service ids, and the bundle's Configuration.php for true config keys. On Laravel (your port): log raw envelope + resolved callable + envelope-out per call; that trace is what you'll diff in the conformance harness.How can I help you explore Laravel packages today?