Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Devexpressbundle Laravel Package

elma/devexpressbundle

Symfony bundle that bridges DevExpress JS widgets with Doctrine, currently supporting dxDataGrid. It parses DevExpress load options and applies filtering, sorting, and pagination to Doctrine queries via simple column-to-field mapping. Unofficial and a work in progress; contributions welcome.

View on GitHub
Deep Wiki
Context7

Getting Started

The bundle bridges DevExpress dxDataGrid client widgets to Doctrine query builders in Symfony. It is not an official DevExpress product and does not ship any DevExpress JS — you still install/serve the widgets yourself. It is explicitly a WIP that currently only supports dxDataGrid.

Install and register it (the README targets Symfony 2/3-era kernel style):

composer require elma/devexpressbundle "~1.0@dev"
// app/AppKernel.php
$bundles = [
    new Bilendi\DevExpressBundle\BilendiDevExpressBundle,
];

For Symfony 4+/Flex you must instead add Bilendi\DevExpressBundle\BilendiDevExpressBundle::class to config/bundles.php and adapt any service registration yourself.

Look first at the README’s indexAction example — it shows the whole workflow in one place. The entry point is SearchQueryParser, which decodes the DevExpress loadOptions payload:

$parser = new SearchQueryParser();
$query  = $parser->parse(json_decode($request->get('loadOptions')));

Then define the map between grid column dataField names and Doctrine fields:

$map = [
    'Username'  => 'u.username',
    'FirstName' => 'u.firstName',
    // ...
];

Your first real use case: a controller endpoint that backs a dxDataGrid configured with remoteOperations enabled, returning server-side paging, sorting, and filtering for a single Doctrine entity.

Implementation Patterns

Standard grid controller. The canonical pattern is: parse loadOptions → build a QueryBuilder for the entity → apply the parsed query using the column map → serialize rows to JSON, including totalCount.

public function indexAction(Request $request)
{
    $parser = new SearchQueryParser();
    $query  = $parser->parse(json_decode($request->get('loadOptions'), true));

    $map = [
        'Username'  => 'u.username',
        'FirstName' => 'u.firstName',
    ];

    $qb = $this->getDoctrine()->getRepository(User::class)
        ->createQueryBuilder('u');

    // apply $query against $qb using $map (sorting, filtering, paging)
    // ...

    return new JsonResponse([
        'data'       => $qb->getQuery()->getArrayResult(),
        'totalCount' => $totalCount,
    ]);
}

Column map as an explicit whitelist. Keep the map defined per-endpoint. Never pass client-supplied column names straight into DQL — the map doubles as your allow-list and is your primary defense against injection through filter/sort selectors.

Separate the count query. dxDataGrid sends requireTotalCount; run a SELECT COUNT(...) on the filtered query builder before applying skip/take, otherwise paging metadata will be wrong.

Frontend wiring. In dxDataGrid, enable remoteOperations: { paging: true, sorting: true, filtering: true } and forward loadOptions as JSON to your endpoint. The parser expects the exact object shape DevExpress sends (filter, sort, skip, take, requireTotalCount).

Service-ize it. Rather than new SearchQueryParser() in every action, register it as a Symfony service and inject a reusable “apply query to QueryBuilder” helper. This keeps controllers thin and makes the map easy to unit test.

Repository/manager abstraction. For larger apps, wrap the controller logic in a GridDataProvider service that accepts a grid name, resolves the map from config, and returns the payload. Multiple grids then share one code path with different maps.

Integration tip. The bundle is a bridge, not a full stack — pair it with your normal serializer (e.g. Symfony Serializer or JMS) instead of getArrayResult() for richer entity shapes and relations.

Gotchas and Tips

  • Maturity risk. 4 stars, 0 dependents, last release 2020. Treat it as a reference implementation you may need to vendor/fork or replace with a hand-rolled parser. Budget time for bugs in the filter parser.
  • Incomplete filter support. The README says “simple (and incomplete).” Complex nested and/or filter trees and some operators likely won’t parse. Test every operator your grid exposes (contains, startswith, >=, between, etc.) before shipping.
  • Symfony version mismatch. The install instructions (AppKernel.php) are for old Symfony. On 4+/Flex, register in config/bundles.php and verify whether the bundle ships a services.xml/services.yaml auto-loaded under the right path; you may need manual service definitions.
  • null payloads. json_decode(null) returns null; guard against a missing loadOptions request parameter to avoid fatal errors on initial grid load.
  • Strict field names. dataField values in the grid and keys in the map must match exactly (case-sensitive). A typo silently yields no filter/sort rather than an error.
  • Count vs. page ordering. Apply filters first, snapshot COUNT, then apply sort and skip/take. Applying take before counting is the most common bug producing a wrong totalCount.
  • Debugging. json_decode + dump()/var_dump() the raw loadOptions and the parsed SearchQuery object side-by-side; nearly every issue is a shape mismatch between what the grid sends and what the parser expects.
  • Security. Client controls filter and sort. Keep the map as a hard whitelist and validate operators server-side; don’t concatenate raw selectors.
  • Extension points. Fork or decorate SearchQueryParser if you hit unsupported operators, and wrap the QueryBuilder application step in your own service so you can swap out the bundle later without touching controllers.
  • No DevExpress assets. You must include the DevExpress libraries and license yourself; this bundle only handles the server-side JSON contract.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package