68 lines
2.6 KiB
PHP
68 lines
2.6 KiB
PHP
<?php
|
||
|
||
namespace Helper;
|
||
|
||
use Exception;
|
||
|
||
class QueryBuilder
|
||
{
|
||
public function __construct(private readonly string $tableName, private string $columns = '*') {}
|
||
|
||
public function setColumns(string $columns): void
|
||
{
|
||
$this->columns = $columns;
|
||
}
|
||
|
||
/**
|
||
* @throws Exception
|
||
*/
|
||
public function select(array $filters = [], int $limit = 0): array
|
||
{
|
||
if (empty($filters)) {
|
||
return ['sql' => "select $this->columns from $this->tableName"];
|
||
}
|
||
$where = [];
|
||
$params = [];
|
||
foreach ($filters as $filter) {
|
||
[$name, $operation, $value] = explode(' ', $filter, 3);
|
||
$placeholder = ":$name";
|
||
$value = explode(' ', $value, 3); //todo: а ведь может прилететь значение из нескольких слов с пробелом...
|
||
if (count($value) === 1) {
|
||
$value = $value[0];
|
||
if (is_numeric($value)) {
|
||
$value = (int)$value;
|
||
}
|
||
} else {
|
||
array_walk_recursive($value, function (&$var) {
|
||
if (is_numeric($var)) {
|
||
$var = (int)$var;
|
||
}
|
||
});
|
||
if (is_numeric($value[0]) && is_numeric($value[2])) {
|
||
$value = match ($value[1]) {
|
||
'+' => $value[0] + $value[2],
|
||
'-' => $value[0] - $value[2],
|
||
'*' => $value[0] * $value[2],
|
||
'/' => ($value[2] != 0) ? $value[0] / $value[2] : throw new Exception('Деление на ноль недопустимо.'),
|
||
default => throw new Exception('Недопустимый оператор. Допустимы: +, -, *, /.'),
|
||
};
|
||
} elseif (is_string($value[0])) {
|
||
$placeholder = "$value[0] $value[1] :$name";
|
||
$value = $value[2];
|
||
} elseif (is_string($value[2])) {
|
||
$placeholder = "$value[2] $value[1] :$name";
|
||
$value = $value[0];
|
||
}
|
||
}
|
||
//todo: но есть ещё форменное скотство, когда в запрос кидают сложные формулы...
|
||
|
||
$where[] = "$name $operation $placeholder";
|
||
$params[$name] = $value;
|
||
}
|
||
|
||
return [
|
||
'sql' => "select $this->columns from $this->tableName where " . implode(" and ", $where) . ($limit > 0 ? " limit $limit" : ""),
|
||
'binds' => $params,
|
||
];
|
||
}
|
||
} |