Я работаю над API с FlightPHP и PHPActiveRecord, который возвращает массив отчетов, необязательно фильтруемых по параметрам строки запроса URL.
$allowed = ['author' => 'author_id', 'owner' => 'owner_id'];
$options = build_options(Flight::request(), $allowed);
$reports = Report::all($options);
Метод build_options создает массив со всеми параметрами запроса, в этомслучай, когда предложения WHERE удаляют те столбцы, которые не разрешены, и игнорируют непереданные параметры.
function build_options($request, $allowed) {
$clauses = array_map(function($column, $value) {
return "($column = :$value OR :$value IS NULL)";
}, $allowed, array_keys($allowed));
$where = implode($clauses, ' AND ');
$params = array_intersect_key($request->query->getData(), $allowed);
return ['conditions' => [$where, $params]];
}
Эта функция создает предложение WHERE, например:
(author_id = :author OR :author IS NULL) AND (owner_id = :owner OR :owner IS NULL)
, но кажется, что PHPActiveRecord не принимает именованные заполнители,Единственная проблема в их GitHub, спрашивающем об этом, была с 2010 года и была закрыта.
Есть ли другой способ элегантной фильтрации запроса с необязательными параметрами?
- EDIT -
Я работал над обходным решением с позиционными заполнителями, которое работает без именованных заполнителей. Я все еще думаю, что версия с именованным заполнителем выглядит чище и понятнее.
function build_options($request, $allowed) {
$params = array_intersect_key($request->query->getData(), $allowed);
$clauses = array_map(function($param) use ($allowed) {
return "$allowed[$param] = ?";
}, array_keys($params));
$where = implode($clauses, ' AND ');
return ['conditions' => array_merge([$where], array_values($params))];
}