302 lines
7.6 KiB
PHP
302 lines
7.6 KiB
PHP
<?php
|
|
|
|
namespace Kletellier\PdoWrapper;
|
|
|
|
class QueryBuilder
|
|
{
|
|
protected array $columns;
|
|
protected array $wheres;
|
|
protected array $orders;
|
|
protected array $groupby;
|
|
protected string $table;
|
|
protected string $connection;
|
|
protected string $pk;
|
|
protected ?int $take;
|
|
protected ?int $offset;
|
|
protected string $raw_query;
|
|
protected bool $distinct;
|
|
|
|
public function __construct($table, $pk = "id", $connection = "")
|
|
{
|
|
$this->table = $table;
|
|
$this->pk = $pk;
|
|
$this->connection = $connection;
|
|
$this->reset();
|
|
}
|
|
|
|
public function reset()
|
|
{
|
|
$this->columns = [];
|
|
$this->wheres = [];
|
|
$this->orders = [];
|
|
$this->groupby = [];
|
|
$this->offset = null;
|
|
$this->take = null;
|
|
$this->distinct = false;
|
|
$this->raw_query = "";
|
|
}
|
|
|
|
public function raw(string $query)
|
|
{
|
|
$this->raw_query = $query;
|
|
return $this;
|
|
}
|
|
|
|
public function take(?int $nb)
|
|
{
|
|
$this->take = $nb;
|
|
return $this;
|
|
}
|
|
|
|
public function offset(?int $offset)
|
|
{
|
|
$this->offset = $offset;
|
|
return $this;
|
|
}
|
|
|
|
public function distinct()
|
|
{
|
|
$this->distinct = true;
|
|
return $this;
|
|
}
|
|
|
|
public function orderBy($columns, $sort = "ASC")
|
|
{
|
|
if (is_array($columns)) {
|
|
foreach ($columns as $column) {
|
|
$this->orders[] = $column . " " . $sort;
|
|
}
|
|
} else {
|
|
$this->orders[] = $columns . " " . $sort;
|
|
}
|
|
return $this;
|
|
}
|
|
|
|
public function columns($columns)
|
|
{
|
|
if (is_array($columns)) {
|
|
$this->columns = array_merge($this->columns, $columns);
|
|
}
|
|
if (is_string($columns)) {
|
|
$this->columns[] = $columns;
|
|
}
|
|
return $this;
|
|
}
|
|
|
|
public function groupBy($columns)
|
|
{
|
|
if (is_array($columns)) {
|
|
$this->groupby = array_merge($this->groupby, $columns);
|
|
}
|
|
if (is_string($columns)) {
|
|
$this->groupby[] = $columns;
|
|
}
|
|
return $this;
|
|
}
|
|
|
|
public function whereIn($condition, array $values)
|
|
{
|
|
$this->wheres[] = new Expression($condition, "in", $values);
|
|
return $this;
|
|
}
|
|
|
|
public function whereBetween($condition, $value1, $value2)
|
|
{
|
|
$this->wheres[] = new Expression($condition, "between", [$value1,$value2]);
|
|
return $this;
|
|
}
|
|
|
|
public function whereNotNull($condition)
|
|
{
|
|
$this->wheres[] = new Expression($condition, "notnull", "");
|
|
return $this;
|
|
}
|
|
|
|
public function whereNull($condition)
|
|
{
|
|
$this->wheres[] = new Expression($condition, "isnull", "");
|
|
return $this;
|
|
}
|
|
|
|
public function where($condition, $operator, $value = null)
|
|
{
|
|
if ($value === null) {
|
|
$this->wheres[] = new Expression($condition, "=", $operator);
|
|
} else {
|
|
$this->wheres[] = new Expression($condition, $operator, $value);
|
|
}
|
|
return $this;
|
|
}
|
|
|
|
public function whereRaw(string $raw)
|
|
{
|
|
$this->wheres[] = $raw;
|
|
return $this;
|
|
}
|
|
|
|
public function find($id): mixed
|
|
{
|
|
$this->reset();
|
|
$expression = new Expression($this->pk, "=", $id);
|
|
$this->wheres = [$expression];
|
|
$this->columns = ["*"];
|
|
$data = $this->getData();
|
|
if (count($data) > 0) {
|
|
return $this->prepareModels($data)->first();
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public function get(): mixed
|
|
{
|
|
$data = $this->getData();
|
|
return $this->prepareModels($data);
|
|
}
|
|
|
|
public function getPreparedQuery(array $data, $insert = true): Query
|
|
{
|
|
$ret = new Query();
|
|
|
|
$columns = implode(",", array_keys($data));
|
|
$query = "";
|
|
|
|
if ($insert) {
|
|
$keys = implode(",", str_split(str_repeat("?", count($data))));
|
|
$query = "INSERT INTO " . $this->table . " (" . $columns . ") VALUES (" . $keys . ");";
|
|
foreach ($data as $key => $value) {
|
|
$ret->addData($value);
|
|
}
|
|
} else {
|
|
$query = "UPDATE " . $this->table . " SET ";
|
|
$up = "";
|
|
foreach ($data as $key => $value) {
|
|
if ($up != "") {
|
|
$up .= ", ";
|
|
}
|
|
$up .= $key . " = ? ";
|
|
$ret->addData($value);
|
|
}
|
|
$query .= $up . " WHERE " . $this->pk . " = ? ;";
|
|
$ret->addData($data[$this->pk]);
|
|
}
|
|
$ret->setQuery($query);
|
|
return $ret;
|
|
}
|
|
|
|
private function prepareModels(mixed $data): mixed
|
|
{
|
|
$ret = array();
|
|
foreach ($data as $row) {
|
|
$model = new Model();
|
|
$ret[] = $model->setPk($this->pk)->setTable($this->table)->fillData($row);
|
|
}
|
|
return new Collection($ret);
|
|
}
|
|
|
|
private function getData(): mixed
|
|
{
|
|
return Connection::getInstance($this->connection)->getSelectQuery($this->getQuery());
|
|
}
|
|
|
|
private function getConstructedQuery(): Query
|
|
{
|
|
$ret = new Query();
|
|
$ret->setQuery("");
|
|
$ret->setData([]);
|
|
|
|
if (count($this->columns) == 0) {
|
|
$this->columns("*");
|
|
}
|
|
|
|
$columns = implode(",", $this->columns);
|
|
$distinct = ($this->distinct) ? " DISTINCT " : "";
|
|
$query = "SELECT " . $distinct . " " . $columns . " FROM " . $this->table ;
|
|
|
|
$where = $this->getWhere();
|
|
$this->fillData($ret);
|
|
|
|
if ($where != "") {
|
|
$query .= " WHERE " . $where;
|
|
}
|
|
|
|
$query .= $this->getClause("GROUP By", $this->groupby);
|
|
$query .= $this->getClause("ORDER By", $this->orders);
|
|
$query .= $this->getLimit();
|
|
|
|
$ret->setQuery($query);
|
|
return $ret;
|
|
}
|
|
|
|
private function fillData(Query &$query): void
|
|
{
|
|
foreach ($this->wheres as $expression) {
|
|
if ($expression instanceof Expression) {
|
|
if ($expression->hasData()) {
|
|
$query->addData($expression->getValue());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private function getWhere(): string
|
|
{
|
|
$where = "";
|
|
foreach ($this->wheres as $expression) {
|
|
$sw = "";
|
|
if ($expression instanceof Expression) {
|
|
$sw = $expression->raw();
|
|
}
|
|
if (is_string($expression)) {
|
|
if (trim($expression) !== "") {
|
|
$sw = "(" . $expression . ")";
|
|
}
|
|
}
|
|
if ($where != "" && $sw != "") {
|
|
$where .= " AND ";
|
|
}
|
|
$where .= $sw;
|
|
}
|
|
return $where;
|
|
}
|
|
|
|
private function getClause(string $word, array $data): string
|
|
{
|
|
if (!empty($data)) {
|
|
return " $word " . implode(",", $data);
|
|
}
|
|
return "";
|
|
}
|
|
|
|
private function getLimit(): string
|
|
{
|
|
if ($this->take !== null || $this->offset !== null) {
|
|
$ret = ($this->take !== null ? " LIMIT " . $this->take : "") . ($this->offset !== null ? " OFFSET " . $this->offset : "");
|
|
return $ret;
|
|
} else {
|
|
return "";
|
|
}
|
|
}
|
|
|
|
private function getQuery(): Query
|
|
{
|
|
if ($this->raw_query !== "") {
|
|
$query = new Query();
|
|
$query->setQuery($this->raw_query);
|
|
$query->setData([]);
|
|
return $query;
|
|
} else {
|
|
return $this->getConstructedQuery();
|
|
}
|
|
}
|
|
|
|
public function getConnection()
|
|
{
|
|
return $this->connection;
|
|
}
|
|
public function setConnection($connection)
|
|
{
|
|
$this->connection = $connection;
|
|
return $this;
|
|
}
|
|
}
|