timgws/query-builder-parser
Parse jQuery QueryBuilder rules into safe Laravel query builder constraints. Whitelist allowed fields, then generate SQL (Illuminate/Database) or MongoDB queries (via jenssegers/mongodb). Works well with tools like jQuery DataTables for advanced filtering.
Install the Package:
composer require timgws/query-builder-parser
Ensure compatibility with your Laravel version (supports 5.5+ up to 13).
Basic Usage:
use timgws\QueryBuilderParser;
use Illuminate\Support\Facades\DB;
// Define allowed fields (columns) for filtering
$allowedFields = ['name', 'email', 'status'];
// Initialize parser
$parser = new QueryBuilderParser($allowedFields);
// Parse frontend query rules into a Laravel query builder
$query = $parser->parse($request->input('querybuilder'), DB::table('users'));
// Execute and return results
return $query->get();
Frontend Integration:
rules field in POST data).QueryBuilderParser to your controller.['name', 'email', 'created_at']).{"condition":"AND","rules":[{"field":"email","operator":"contains","value":"gmail"}]}).$parser = new QueryBuilderParser(['email', 'status']);
$query = $parser->parse($request->rules, DB::table('users'));
return Datatable::query($query)
->showColumns(['id', 'name', 'email'])
->orderColumns(['name', 'email'])
->make();
// Update Datatables with new rules
function reloadData() {
const rules = $('#querybuilder').queryBuilder('getRules');
$.post('/admin/users', { rules }, (data) => {
oTable.fnDraw();
});
}
JoinSupportingQueryBuilderParser for nested queries:
$joinFields = [
'orders' => [
'from_table' => 'users',
'from_col' => 'id',
'to_table' => 'orders',
'to_col' => 'user_id',
]
];
$parser = new JoinSupportingQueryBuilderParser(['name'], $joinFields);
$query = $parser->parse($request->rules, DB::table('users'));
DB::table() with DB::collection():
$parser = new QueryBuilderParser(['name', 'email']);
$query = $parser->parse($request->rules, DB::collection('users'));
$parser = new QueryBuilderParser(['safe_column1', 'safe_column2']);
begins_with, ends_with) by extending the parser.$query->paginate(10);
Field Mismatches:
$allowedFields.strictMode (if available):
$parser = new QueryBuilderParser(['name', 'email'], ['strict' => true]);
MongoDB Quirks:
$regex) may not work as expected for case-sensitive searches.$options: 'i' for case-insensitive queries:
// Customize MongoDB operators in the parser or post-process the query.
Join Complexity:
JoinSupportingQueryBuilderParser may generate inefficient SQL for deep joins.select():
$query->select('users.*', 'orders.total');
Date Handling:
YYYY-MM-DD vs. MM/DD/YYYY).$parser->setDateFormat('Y-m-d'); // Align with frontend format.
Operator Conflicts:
custom_function) may not map to SQL.$parser->addOperator('custom_function', function ($field, $value) {
return DB::raw("SOME_CUSTOM_FUNCTION($field, '$value')");
});
\Log::info('Frontend rules:', $request->rules);
DB::enableQueryLog();
$query->get();
\Log::info(DB::getQueryLog());
$query = $parser->parse($rules, DB::collection('users'));
\Log::info('MongoDB query:', $query->toJson());
Custom Operators:
$parser->addOperator('custom_op', function ($field, $value) {
return DB::raw("UPPER($field) = UPPER('$value')");
});
Field Transformations:
$parser->setFieldTransformer('email', function ($value) {
return strtolower($value);
});
Post-Processing:
$query = $parser->parse($rules, DB::table('users'));
$query->where('active', 1); // Add static conditions.
MongoDB Customization:
$parser->setMongoOperator('contains', '$regex', function ($value) {
return ['$regex' => ".*$value.*", '$options' => 'i'];
});
with() for eager loading in joins:
$query->with(['orders' => function ($q) {
$q->where('status', 'completed');
}]);
email, status) are indexed in the database.$query->cursor()->limit(100);
How can I help you explore Laravel packages today?