flytachi / winter-mui-data-grid
Server-side MUI DataGrid adapter for Winter Framework — pagination, filtering, sorting and column visibility out of the box.
v1.0.1
2026-03-31 14:22 UTC
Requires
- php: >=8.3
- flytachi/winter-kernel: ^2.0
Requires (Dev)
- squizlabs/php_codesniffer: @stable
README
Server-side MUI DataGrid adapter for Winter Framework. Handles pagination, multi-column sorting, full operator filtering, and column visibility — with SQL injection protection built in.
Documentation: winterframe.net/docs/mui-data-grid
Requirements
- PHP >= 8.3
- flytachi/winter-kernel ^2.0
Installation
composer require flytachi/winter-mui-data-grid
Quick Start
Frontend request
Send a POST request with JSON body:
{
"page": 0,
"pageSize": 25,
"sortModel": [{ "field": "name", "sort": "asc" }],
"filterModel": {
"logicOperator": "and",
"items": [
{ "field": "name", "operator": "contains", "value": "apple" }
]
},
"visibleColumns": ["id", "name", "quantity"]
}
Auto mode
The wrapper builds SELECT / WHERE / ORDER BY from scratch.
// Controller $request = ProductRequest::json(); return new Resp(ProductService::getGrid($request)); // Request class ProductRequest extends MuiGridRequest {} // Service public static function getGrid(ProductRequest $request): array { $repo = new ProductRepository(); $request->allowColumns(['id', 'name', 'quantity', 'createdAt']); $request->overrideSelection(['createdAt' => 'created_at']); $request->overrideOrder('name ASC'); $response = MuiGridWrapper::paginate($repo, $request, Qb::eq('is_active', true)); return $response->toArray(); }
Overlay mode
Use when you need custom JOINs, conditional SELECT, or business-level WHERE conditions. The wrapper appends MUI filters on top of your pre-built query.
public static function getGrid(StorageRequest $request): array { $repo = new StorageRepository(); $repo->select('i.id, p.name AS productName, i.quantity') ->joinLeft('products p', Qb::raw('p.id = i.product_id')) ->where(Qb::eq('i.warehouse_id', $request->warehouseId)); $request->overrideFilter(function (MGFilterItem $item): ?Qb { return match ($item->operator) { MGOperator::CONTAINS => Qb::like('p.name', "%{$item->value}%", true), MGOperator::EQ => Qb::eq('i.quantity', $item->value), default => null, }; }); $response = MuiGridWrapper::paginate($repo, $request, overlay: true); $response->rows = array_map(StorageResource::from(...), $response->rows); return $response->toArray(); }
API Reference
MuiGridRequest
Extend this class for your endpoint-specific request.
| Method | Description |
|---|---|
allowColumns(array $allowed) |
Whitelist of field names for SELECT, sort, and filter. Rejects unlisted fields. |
overrideSelection(array $map) |
Maps MUI field names to SQL expressions (['createdAt' => 'created_at']). |
overrideFilter(?callable $cb) |
Replaces default filter logic. Callback receives MGFilterItem, returns ?Qb. |
overrideOrder(?string $default) |
Fallback ORDER BY clause when sortModel is empty. |
isVisible(string $field) |
Returns true if the field is visible (or visibleColumns was not sent). |
MuiGridWrapper::paginate()
MuiGridWrapper::paginate(
RepositoryInterface $repo,
MuiGridRequest $request,
?Qb $headQueryBuilder = null, // base WHERE (auto mode)
bool $overlay = false,
): MuiGridResponse
MuiGridResponse
$response->rowCount; // int — total rows (for MUI pagination) $response->rows; // array — current page rows (mutable for post-processing) $response->toArray(); // ['rowCount' => int, 'rows' => array]
Supported Operators
| Category | Operators |
|---|---|
| String | contains, notContains, startsWith, endsWith |
| Equality | equals, is, not, =, != |
| Numeric | >, >=, <, <= |
| Date | after, onOrAfter, before, onOrBefore |
| Set | isAnyOf |
| Null | isEmpty, isNotEmpty |
License
MIT — Flytachi