FreeGrid PHP server helper
==========================

FreeGridQuery.php   one file (namespace FreeGrid: FreeGridQuery and GridError), PHP 8.1+ and PDO

  FreeGridQuery::readRequest($body)  reads restDatasource's request (paging, sort, filters, quick filter, advanced filter, grouping)
  $query->build($request)            turns it into SQL: where, orderBy, page, args, countArgs, group
  FreeGridQuery::bind($st, $args)    binds the values (integers as PDO::PARAM_INT, for MySQL's LIMIT ?)
  FreeGridQuery::toRows($rows, $n)   the ['rows', 'total'] response, dates as "YYYY-MM-DD"
  FreeGridQuery::readSave($body)     ['created', 'updated', 'deleted'] from saveChanges()

  $query = new FreeGridQuery(['orderNo' => ['ORDER_NO', 'text'], 'qty' => ['QTY', 'number']], dialect: 'limit');
  $sql = $query->build(FreeGridQuery::readRequest(json_decode($raw, true)));
  $st = $pdo->prepare('SELECT ... FROM ORDERS' . $sql['where'] . $sql['orderBy'] . $sql['page']);
  FreeGridQuery::bind($st, $sql['args']);
  $st->execute();

Laravel: put the file in app/Support/, add "app/Support/FreeGridQuery.php" to autoload.files in
composer.json, and use DB::getPdo(), or DB::select($text, $sql['args']).

Only the columns you list can be sorted, filtered or grouped; every value is a bound parameter.
A bad number or date, an unknown filter op or too many values raises GridError: answer 400 { message }.
LIKE searches use ESCAPE '!', so % and _ typed in a filter are matched as text.

What the grid sends and what to answer, with a full example server:
  https://freegrid.app/docs/server/     (English)
  https://freegrid.app/ko/docs/server/  (한국어)

Use is covered by the FreeGrid license: https://freegrid.app/pricing/
