154 lines
3.8 KiB
PHP
154 lines
3.8 KiB
PHP
<?php
|
|
|
|
namespace App\Models;
|
|
|
|
use Illuminate\Database\Query\Builder as QueryBuilder;
|
|
|
|
class CiQueryBuilder
|
|
{
|
|
protected QueryBuilder $builder;
|
|
protected array $setData = [];
|
|
|
|
protected array $tableMethods = [
|
|
'join',
|
|
'leftJoin',
|
|
'rightJoin',
|
|
'crossJoin',
|
|
'from',
|
|
'table',
|
|
'joinWhere',
|
|
'leftJoinWhere',
|
|
];
|
|
|
|
public function __construct(QueryBuilder $builder)
|
|
{
|
|
$this->builder = $builder;
|
|
}
|
|
|
|
public function __call($method, $arguments)
|
|
{
|
|
$arguments = $this->normalizeTableArgument($method, $arguments);
|
|
$result = $this->builder->$method(...$arguments);
|
|
|
|
if ($result instanceof QueryBuilder) {
|
|
$this->builder = $result;
|
|
return $this;
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
public function where($column, $operator = null, $value = null, $boolean = 'and')
|
|
{
|
|
if ($operator !== null && $value === null && preg_match('/^(.*)\s(>=|<=|<>|!=|>|<)$/', $column, $matches)) {
|
|
return $this->where(trim($matches[1]), $matches[2], $operator, $boolean);
|
|
}
|
|
|
|
$this->builder = $this->builder->where($column, $operator, $value, $boolean);
|
|
return $this;
|
|
}
|
|
|
|
public function like($column, $match, string $side = 'both')
|
|
{
|
|
$pattern = $this->wrapLike($match, $side);
|
|
$this->builder = $this->builder->where($column, 'like', $pattern);
|
|
return $this;
|
|
}
|
|
|
|
public function set($key, $value = null, bool $escape = true)
|
|
{
|
|
if (is_array($key)) {
|
|
$this->setData = array_merge($this->setData, $key);
|
|
} else {
|
|
$this->setData[$key] = $value;
|
|
}
|
|
|
|
return $this;
|
|
}
|
|
|
|
public function update($values = [])
|
|
{
|
|
$data = $values ?: $this->setData;
|
|
$this->setData = [];
|
|
return $this->builder->update($data);
|
|
}
|
|
|
|
public function findAll(int $limit = 0, int $offset = 0)
|
|
{
|
|
if ($limit > 0) {
|
|
$this->builder = $this->builder->limit($limit);
|
|
}
|
|
|
|
if ($offset > 0) {
|
|
$this->builder = $this->builder->offset($offset);
|
|
}
|
|
|
|
return $this->getResultArray();
|
|
}
|
|
|
|
public function get($columns = ['*'])
|
|
{
|
|
$collection = $this->builder->get($columns);
|
|
return new CiQueryResult($collection);
|
|
}
|
|
|
|
public function getResultArray(): array
|
|
{
|
|
return $this->get()->getResultArray();
|
|
}
|
|
|
|
public function getRowArray(): ?array
|
|
{
|
|
return $this->get()->getRowArray();
|
|
}
|
|
|
|
public function getRow(?string $column = null)
|
|
{
|
|
return $this->get()->getRow($column);
|
|
}
|
|
|
|
public function countAllResults(): int
|
|
{
|
|
return $this->builder->count();
|
|
}
|
|
|
|
protected function wrapLike($match, string $side): string
|
|
{
|
|
$pattern = "%{$match}%";
|
|
|
|
switch (strtolower($side)) {
|
|
case 'before':
|
|
return "%{$match}";
|
|
case 'after':
|
|
return "{$match}%";
|
|
default:
|
|
return $pattern;
|
|
}
|
|
}
|
|
|
|
protected function normalizeTableArgument(string $method, array $arguments): array
|
|
{
|
|
if (in_array($method, $this->tableMethods, true) && isset($arguments[0]) && is_string($arguments[0])) {
|
|
$arguments[0] = $this->normalizeTableName($arguments[0]);
|
|
}
|
|
|
|
return $arguments;
|
|
}
|
|
|
|
protected function normalizeTableName(string $table): string
|
|
{
|
|
$normalized = trim($table);
|
|
|
|
if (stripos($normalized, ' as ') !== false) {
|
|
return $normalized;
|
|
}
|
|
|
|
if (strpos($normalized, ' ') !== false) {
|
|
[$name, $alias] = preg_split('/\s+/', $normalized, 2);
|
|
return "{$name} as {$alias}";
|
|
}
|
|
|
|
return $normalized;
|
|
}
|
|
}
|