Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ee3ea44a81 | |||
|
|
293eb9e555 | ||
|
|
d961d2a80f | ||
|
|
0db845a116 | ||
|
|
35188860ce | ||
|
|
c8d6e911a6 | ||
|
|
03d26d9167 |
@@ -12,33 +12,64 @@ class Collection implements IteratorAggregate, Countable, JsonSerializable
|
|||||||
{
|
{
|
||||||
private array $elements;
|
private array $elements;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @param array $elements
|
||||||
|
*/
|
||||||
public function __construct(array $elements = [])
|
public function __construct(array $elements = [])
|
||||||
{
|
{
|
||||||
$this->elements = $elements;
|
$this->elements = $elements;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return first element of the collection
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
public function first(): mixed
|
public function first(): mixed
|
||||||
{
|
{
|
||||||
return reset($this->elements);
|
return reset($this->elements);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return last element of the collection
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
public function last(): mixed
|
public function last(): mixed
|
||||||
{
|
{
|
||||||
return end($this->elements);
|
return end($this->elements);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return collection length
|
||||||
|
*
|
||||||
|
* @return integer
|
||||||
|
*/
|
||||||
public function count(): int
|
public function count(): int
|
||||||
{
|
{
|
||||||
return count($this->elements);
|
return count($this->elements);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear all elements in collection
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
public function clear(): bool
|
public function clear(): bool
|
||||||
{
|
{
|
||||||
$this->elements = [];
|
$this->elements = [];
|
||||||
return count($this->elements) == 0;
|
return count($this->elements) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function index($index): mixed
|
/**
|
||||||
|
* Return element in nth position in the collection
|
||||||
|
*
|
||||||
|
* @param int $index
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function index(int $index): mixed
|
||||||
{
|
{
|
||||||
if (isset($this->elements[$index])) {
|
if (isset($this->elements[$index])) {
|
||||||
return $this->elements[$index];
|
return $this->elements[$index];
|
||||||
@@ -46,31 +77,67 @@ class Collection implements IteratorAggregate, Countable, JsonSerializable
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return random element of the collection
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
public function random(): mixed
|
public function random(): mixed
|
||||||
{
|
{
|
||||||
return array_rand($this->elements);
|
return array_rand($this->elements);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reduce function on the collection
|
||||||
|
*
|
||||||
|
* @param callable $fn
|
||||||
|
* @param mixed $initial
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
public function reduce(callable $fn, mixed $initial): mixed
|
public function reduce(callable $fn, mixed $initial): mixed
|
||||||
{
|
{
|
||||||
return array_reduce($this->elements, $fn, $initial);
|
return array_reduce($this->elements, $fn, $initial);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map function on the collection
|
||||||
|
*
|
||||||
|
* @param callable $fn
|
||||||
|
* @return Collection
|
||||||
|
*/
|
||||||
public function map(callable $fn): Collection
|
public function map(callable $fn): Collection
|
||||||
{
|
{
|
||||||
return new Collection(array_map($fn, $this->elements));
|
return new Collection(array_map($fn, $this->elements));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply callable function on each element of the function
|
||||||
|
*
|
||||||
|
* @param callable $fn
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function each(callable $fn): void
|
public function each(callable $fn): void
|
||||||
{
|
{
|
||||||
array_walk($this->elements, $fn);
|
array_walk($this->elements, $fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply function to filter collection
|
||||||
|
*
|
||||||
|
* @param callable $fn
|
||||||
|
* @return Collection
|
||||||
|
*/
|
||||||
public function filter(callable $fn): Collection
|
public function filter(callable $fn): Collection
|
||||||
{
|
{
|
||||||
return new Collection(array_filter($this->elements, $fn, ARRAY_FILTER_USE_BOTH));
|
return new Collection(array_filter($this->elements, $fn, ARRAY_FILTER_USE_BOTH));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return collection of the key related items in current collection
|
||||||
|
*
|
||||||
|
* @param string $key
|
||||||
|
* @return Collection
|
||||||
|
*/
|
||||||
public function pluck(string $key): Collection
|
public function pluck(string $key): Collection
|
||||||
{
|
{
|
||||||
return new Collection(array_map(function ($item) use ($key) {
|
return new Collection(array_map(function ($item) use ($key) {
|
||||||
@@ -83,36 +150,72 @@ class Collection implements IteratorAggregate, Countable, JsonSerializable
|
|||||||
}, $this->elements));
|
}, $this->elements));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return actual collection items in an array
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
public function toArray(): array
|
public function toArray(): array
|
||||||
{
|
{
|
||||||
return $this->elements;
|
return $this->elements;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return if the collection are empty
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
public function empty(): bool
|
public function empty(): bool
|
||||||
{
|
{
|
||||||
return empty($this->elements);
|
return empty($this->elements);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add an element to the collection
|
||||||
|
*
|
||||||
|
* @param mixed $element
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function add(mixed $element): void
|
public function add(mixed $element): void
|
||||||
{
|
{
|
||||||
$this->elements[] = $element;
|
$this->elements[] = $element;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return all values of the collection
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
public function values(): array
|
public function values(): array
|
||||||
{
|
{
|
||||||
return array_values($this->elements);
|
return array_values($this->elements);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return all items of the collection
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
public function items(): array
|
public function items(): array
|
||||||
{
|
{
|
||||||
return $this->elements;
|
return $this->elements;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Iterator
|
||||||
|
*
|
||||||
|
* @return Traversable
|
||||||
|
*/
|
||||||
public function getIterator(): Traversable
|
public function getIterator(): Traversable
|
||||||
{
|
{
|
||||||
return new ArrayIterator($this->elements);
|
return new ArrayIterator($this->elements);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return json serialization of the collection
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
public function jsonSerialize(): mixed
|
public function jsonSerialize(): mixed
|
||||||
{
|
{
|
||||||
return $this->elements;
|
return $this->elements;
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ class Connection
|
|||||||
private string $database;
|
private string $database;
|
||||||
private ?string $port;
|
private ?string $port;
|
||||||
private ?string $host;
|
private ?string $host;
|
||||||
|
private ?string $charset;
|
||||||
private string $error;
|
private string $error;
|
||||||
|
|
||||||
private function __construct($name, $config)
|
private function __construct($name, $config)
|
||||||
@@ -40,10 +41,11 @@ class Connection
|
|||||||
$key = (strtolower(trim($this->name)));
|
$key = (strtolower(trim($this->name)));
|
||||||
$this->type = isset($config[$key]["TYPE"]) ? $config[$key]["TYPE"] : null;
|
$this->type = isset($config[$key]["TYPE"]) ? $config[$key]["TYPE"] : null;
|
||||||
$this->user = isset($config[$key]["USER"]) ? $config[$key]["USER"] : null;
|
$this->user = isset($config[$key]["USER"]) ? $config[$key]["USER"] : null;
|
||||||
$this->host = isset($config[$key]["HOST"]) ? $config[$config[$key]["HOST"]] : null;
|
$this->host = isset($config[$key]["HOST"]) ? $config[$key]["HOST"] : null;
|
||||||
$this->password = isset($config[$key]["PASSWORD"]) ? $config[$key]["PASSWORD"] : null;
|
$this->password = isset($config[$key]["PASSWORD"]) ? $config[$key]["PASSWORD"] : null;
|
||||||
$this->database = isset($config[$key]["DATABASE"]) ? $config[$key]["DATABASE"] : null;
|
$this->database = isset($config[$key]["DATABASE"]) ? $config[$key]["DATABASE"] : null;
|
||||||
$this->port = isset($config[$key]["PORT"]) ? $config[$key]["PORT"] : null;
|
$this->port = isset($config[$key]["PORT"]) ? $config[$key]["PORT"] : null;
|
||||||
|
$this->charset = isset($config[$key]["CHARSET"]) ? $config[$key]["CHARSET"] : null;
|
||||||
} catch (\Throwable $th) {
|
} catch (\Throwable $th) {
|
||||||
$this->error = $th->getMessage();
|
$this->error = $th->getMessage();
|
||||||
}
|
}
|
||||||
@@ -70,6 +72,7 @@ class Connection
|
|||||||
$this->password = isset($_ENV[$this->getKey("PASSWORD", $key)]) ? $_ENV[$this->getKey("PASSWORD", $key)] : null;
|
$this->password = isset($_ENV[$this->getKey("PASSWORD", $key)]) ? $_ENV[$this->getKey("PASSWORD", $key)] : null;
|
||||||
$this->database = isset($_ENV[$this->getKey("DATABASE", $key)]) ? $_ENV[$this->getKey("DATABASE", $key)] : null;
|
$this->database = isset($_ENV[$this->getKey("DATABASE", $key)]) ? $_ENV[$this->getKey("DATABASE", $key)] : null;
|
||||||
$this->port = isset($_ENV[$this->getKey("PORT", $key)]) ? $_ENV[$this->getKey("PORT", $key)] : null;
|
$this->port = isset($_ENV[$this->getKey("PORT", $key)]) ? $_ENV[$this->getKey("PORT", $key)] : null;
|
||||||
|
$this->charset = isset($_ENV[$this->getKey("CHARSET", $key)]) ? $_ENV[$this->getKey("CHARSET", $key)] : null;
|
||||||
} catch (\Throwable $th) {
|
} catch (\Throwable $th) {
|
||||||
$this->error = $th->getMessage();
|
$this->error = $th->getMessage();
|
||||||
}
|
}
|
||||||
@@ -117,20 +120,42 @@ class Connection
|
|||||||
return $stmt;
|
return $stmt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function getMySQLOptions()
|
||||||
|
{
|
||||||
|
$ret = "";
|
||||||
|
if ($this->charset) {
|
||||||
|
$ret .= ";charset=" . $this->charset;
|
||||||
|
}
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
|
||||||
private function getConnString()
|
private function getConnString()
|
||||||
{
|
{
|
||||||
$this->connstring = match ($this->type) {
|
$this->connstring = match ($this->type) {
|
||||||
"mysql" => "mysql:host=" . $this->host . ":" . $this->port . ";dbname=" . $this->database,
|
"mysql" => "mysql:host=" . $this->host . ":" . $this->port . ";dbname=" . $this->database . $this->getMySQLOptions() ,
|
||||||
"sqlite" => "sqlite:" . $this->database,
|
"sqlite" => "sqlite:" . $this->database,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute raw query on the current pdo connection
|
||||||
|
*
|
||||||
|
* @param string $rawquery
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
public function executeRawQuery(string $rawquery): bool
|
public function executeRawQuery(string $rawquery): bool
|
||||||
{
|
{
|
||||||
$stmt = $this->pdo->prepare($rawquery);
|
$stmt = $this->pdo->prepare($rawquery);
|
||||||
return $stmt->execute();
|
return $stmt->execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run prepared query in the current pdo connection
|
||||||
|
*
|
||||||
|
* @param Query $query
|
||||||
|
* @param $fetchmode
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
public function getSelectQuery(Query $query, $fetchmode = PDO::FETCH_ASSOC): mixed
|
public function getSelectQuery(Query $query, $fetchmode = PDO::FETCH_ASSOC): mixed
|
||||||
{
|
{
|
||||||
$stmt = $this->pdo->prepare($query->getQuery());
|
$stmt = $this->pdo->prepare($query->getQuery());
|
||||||
@@ -140,6 +165,12 @@ class Connection
|
|||||||
return $stmt->fetchAll($fetchmode);
|
return $stmt->fetchAll($fetchmode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run prepared update query on the current pdo connection
|
||||||
|
*
|
||||||
|
* @param Query $query
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
public function updateQuery(Query $query): bool
|
public function updateQuery(Query $query): bool
|
||||||
{
|
{
|
||||||
$stmt = $this->pdo->prepare($query->getQuery());
|
$stmt = $this->pdo->prepare($query->getQuery());
|
||||||
@@ -148,6 +179,12 @@ class Connection
|
|||||||
return $stmt->execute();
|
return $stmt->execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run prepared insert query on the current pdo connection
|
||||||
|
*
|
||||||
|
* @param Query $query
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
public function insertQuery(Query $query): mixed
|
public function insertQuery(Query $query): mixed
|
||||||
{
|
{
|
||||||
$stmt = $this->pdo->prepare($query->getQuery());
|
$stmt = $this->pdo->prepare($query->getQuery());
|
||||||
@@ -161,6 +198,11 @@ class Connection
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Begin transaction on the current pdo connection
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
public function beginTransaction(): bool
|
public function beginTransaction(): bool
|
||||||
{
|
{
|
||||||
if ($this->pdo) {
|
if ($this->pdo) {
|
||||||
@@ -169,6 +211,11 @@ class Connection
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Commit transaction on the current pdo connection
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
public function commit(): bool
|
public function commit(): bool
|
||||||
{
|
{
|
||||||
if ($this->pdo) {
|
if ($this->pdo) {
|
||||||
@@ -177,6 +224,11 @@ class Connection
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rollback transaction on the current pdo connection
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
public function rollback(): bool
|
public function rollback(): bool
|
||||||
{
|
{
|
||||||
if ($this->pdo) {
|
if ($this->pdo) {
|
||||||
@@ -185,6 +237,13 @@ class Connection
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Init the connections
|
||||||
|
*
|
||||||
|
* @param [type] $config
|
||||||
|
* @param array $connections
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public static function init($config, array $connections = ["default"])
|
public static function init($config, array $connections = ["default"])
|
||||||
{
|
{
|
||||||
self::fillInstances($config, $connections);
|
self::fillInstances($config, $connections);
|
||||||
@@ -214,17 +273,32 @@ class Connection
|
|||||||
throw new \Exception("Unknown connection");
|
throw new \Exception("Unknown connection");
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getError()
|
/**
|
||||||
|
* Return last error
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getError(): string
|
||||||
{
|
{
|
||||||
return $this->error;
|
return $this->error;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getPdo()
|
/**
|
||||||
|
* Return current PDO object
|
||||||
|
*
|
||||||
|
* @return PDO
|
||||||
|
*/
|
||||||
|
public function getPdo(): PDO
|
||||||
{
|
{
|
||||||
return $this->pdo;
|
return $this->pdo;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDriverType()
|
/**
|
||||||
|
* Return current database driver type currently used
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getDriverType(): string
|
||||||
{
|
{
|
||||||
return $this->type;
|
return $this->type;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ namespace Kletellier\PdoWrapper;
|
|||||||
|
|
||||||
class Expression
|
class Expression
|
||||||
{
|
{
|
||||||
private $condition;
|
private string $condition;
|
||||||
private $operator;
|
private string $operator;
|
||||||
private $value;
|
private mixed $value;
|
||||||
|
|
||||||
public function __construct($condition, $operator, $value)
|
public function __construct($condition, $operator, $value)
|
||||||
{
|
{
|
||||||
@@ -15,6 +15,11 @@ class Expression
|
|||||||
$this->value = $value;
|
$this->value = $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return raw value of the expression
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public function raw(): string
|
public function raw(): string
|
||||||
{
|
{
|
||||||
$operator = trim(strtolower($this->operator));
|
$operator = trim(strtolower($this->operator));
|
||||||
@@ -34,40 +39,78 @@ class Expression
|
|||||||
return "(" . $this->condition . " " . $this->operator . " ? )";
|
return "(" . $this->condition . " " . $this->operator . " ? )";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return if the condition need to evaluate data
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
public function hasData()
|
public function hasData()
|
||||||
{
|
{
|
||||||
$operator = trim(strtolower($this->operator));
|
$operator = trim(strtolower($this->operator));
|
||||||
return (in_array($operator, ["isnull","notnull"])) ? false : true;
|
return (in_array($operator, ["isnull","notnull"])) ? false : true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getCondition()
|
/**
|
||||||
|
* Return actual condition
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getCondition(): string
|
||||||
{
|
{
|
||||||
return $this->condition;
|
return $this->condition;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setCondition($condition)
|
/**
|
||||||
|
* Set condition
|
||||||
|
*
|
||||||
|
* @param string $condition
|
||||||
|
* @return self
|
||||||
|
*/
|
||||||
|
public function setCondition(string $condition): self
|
||||||
{
|
{
|
||||||
$this->condition = $condition;
|
$this->condition = $condition;
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getOperator()
|
/**
|
||||||
|
* Get actual operator
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getOperator(): string
|
||||||
{
|
{
|
||||||
return $this->operator;
|
return $this->operator;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setOperator($operator)
|
/**
|
||||||
|
* Set operator
|
||||||
|
*
|
||||||
|
* @param string $operator
|
||||||
|
* @return self
|
||||||
|
*/
|
||||||
|
public function setOperator(string $operator): self
|
||||||
{
|
{
|
||||||
$this->operator = $operator;
|
$this->operator = $operator;
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getValue()
|
/**
|
||||||
|
* Get the value of the expression
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function getValue(): mixed
|
||||||
{
|
{
|
||||||
return $this->value;
|
return $this->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setValue($value)
|
/**
|
||||||
|
* Set the value of the expression
|
||||||
|
*
|
||||||
|
* @param mixed $value
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function setValue(mixed $value)
|
||||||
{
|
{
|
||||||
$this->value = $value;
|
$this->value = $value;
|
||||||
return $this;
|
return $this;
|
||||||
|
|||||||
158
src/Model.php
158
src/Model.php
@@ -8,58 +8,121 @@ class Model implements JsonSerializable
|
|||||||
{
|
{
|
||||||
protected mixed $values;
|
protected mixed $values;
|
||||||
protected array $updated;
|
protected array $updated;
|
||||||
protected string $table;
|
protected string $table = "";
|
||||||
protected string $connection = "";
|
protected string $connection = "";
|
||||||
protected string $pk;
|
protected string $pk;
|
||||||
private bool $new;
|
private bool $new;
|
||||||
|
private bool $ro;
|
||||||
|
|
||||||
public function __construct()
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @param boolean $ro readonly model
|
||||||
|
*/
|
||||||
|
public function __construct($ro = false)
|
||||||
{
|
{
|
||||||
$this->new = true;
|
$this->new = true;
|
||||||
$this->values = array();
|
$this->values = array();
|
||||||
$this->updated = array();
|
$this->updated = array();
|
||||||
$this->pk = "id";
|
$this->pk = "id";
|
||||||
$this->table = $this->getDefaultTableName();
|
$this->ro = $ro;
|
||||||
|
$this->initTable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function initTable(): void
|
||||||
|
{
|
||||||
|
if (!$this->ro) {
|
||||||
|
if ($this->table == "") {
|
||||||
|
$this->table = $this->getDefaultTableName();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$this->table = "ReadOnlyModel";
|
||||||
|
$this->pk = "__idpk";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return table
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public function getTable(): string
|
public function getTable(): string
|
||||||
{
|
{
|
||||||
return $this->table;
|
return $this->table;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define table
|
||||||
|
*
|
||||||
|
* @param string $table
|
||||||
|
* @return self
|
||||||
|
*/
|
||||||
public function setTable(string $table): self
|
public function setTable(string $table): self
|
||||||
{
|
{
|
||||||
$this->table = $table;
|
$this->table = $table;
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return current key value attributes
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
public function getValues(): array
|
public function getValues(): array
|
||||||
{
|
{
|
||||||
return $this->values;
|
return $this->values;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return current primary key
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public function getPk(): string
|
public function getPk(): string
|
||||||
{
|
{
|
||||||
return $this->pk;
|
return $this->pk;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set primary key
|
||||||
|
*
|
||||||
|
* @param string $pk
|
||||||
|
* @return self
|
||||||
|
*/
|
||||||
public function setPk(string $pk): self
|
public function setPk(string $pk): self
|
||||||
{
|
{
|
||||||
$this->pk = $pk;
|
$this->pk = $pk;
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getConnection()
|
/**
|
||||||
|
* Return actual connection
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getConnection(): string
|
||||||
{
|
{
|
||||||
return $this->connection;
|
return $this->connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setConnection($connection)
|
/**
|
||||||
|
* Set connection
|
||||||
|
*
|
||||||
|
* @param string $connection
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function setConnection(string $connection)
|
||||||
{
|
{
|
||||||
$this->connection = $connection;
|
$this->connection = $connection;
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fill values from key value array
|
||||||
|
*
|
||||||
|
* @param mixed $data
|
||||||
|
* @return self
|
||||||
|
*/
|
||||||
public function fillData(mixed $data): self
|
public function fillData(mixed $data): self
|
||||||
{
|
{
|
||||||
$this->values = $data;
|
$this->values = $data;
|
||||||
@@ -68,9 +131,15 @@ class Model implements JsonSerializable
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find specific element in the table on the primary key
|
||||||
|
*
|
||||||
|
* @param mixed $key
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
public function find(mixed $key): mixed
|
public function find(mixed $key): mixed
|
||||||
{
|
{
|
||||||
$qb = $this->newQueryBuilder();
|
$qb = $this->newQueryBuilder(get_class($this));
|
||||||
$find = $qb->find($key);
|
$find = $qb->find($key);
|
||||||
if ($find !== null) {
|
if ($find !== null) {
|
||||||
$this->fillData($find->getValues());
|
$this->fillData($find->getValues());
|
||||||
@@ -79,30 +148,37 @@ class Model implements JsonSerializable
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save current model
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
public function save(): bool
|
public function save(): bool
|
||||||
{
|
{
|
||||||
$ret = false;
|
$ret = false;
|
||||||
$qb = $this->newQueryBuilder();
|
if (!$this->ro) {
|
||||||
if ($this->new) {
|
$qb = $this->newQueryBuilder("");
|
||||||
$query = $qb->getPreparedQuery($this->values);
|
if ($this->new) {
|
||||||
$id = Connection::getInstance($this->connection)->insertQuery($query);
|
$query = $qb->getPreparedQuery($this->values);
|
||||||
if ($id !== false) {
|
$id = Connection::getInstance($this->connection)->insertQuery($query);
|
||||||
$this->values[$this->pk] = $id;
|
if ($id !== false) {
|
||||||
$this->new = false;
|
$this->values[$this->pk] = $id;
|
||||||
$ret = true;
|
$this->new = false;
|
||||||
}
|
$ret = true;
|
||||||
} else {
|
}
|
||||||
if (isset($this->values[$this->pk])) {
|
} else {
|
||||||
if (count($this->updated) > 0) {
|
if (isset($this->values[$this->pk])) {
|
||||||
$data = [];
|
if (count($this->updated) > 0) {
|
||||||
$data[$this->pk] = $this->values[$this->pk];
|
$data = [];
|
||||||
foreach ($this->updated as $updatecol) {
|
$data[$this->pk] = $this->values[$this->pk];
|
||||||
$data[$updatecol] = $this->values[$updatecol];
|
foreach ($this->updated as $updatecol) {
|
||||||
}
|
$data[$updatecol] = $this->values[$updatecol];
|
||||||
$query = $qb->getPreparedQuery($data, false);
|
}
|
||||||
$ret = Connection::getInstance($this->connection)->updateQuery($query);
|
$query = $qb->getPreparedQuery($data, false);
|
||||||
if ($ret) {
|
$ret = Connection::getInstance($this->connection)->updateQuery($query);
|
||||||
$this->updated = [];
|
if ($ret) {
|
||||||
|
$this->updated = [];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -110,9 +186,15 @@ class Model implements JsonSerializable
|
|||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function newQueryBuilder(): QueryBuilder
|
/**
|
||||||
|
* Return new QueryBuilder on the model
|
||||||
|
*
|
||||||
|
* @param string $className
|
||||||
|
* @return QueryBuilder
|
||||||
|
*/
|
||||||
|
public function newQueryBuilder(string $className): QueryBuilder
|
||||||
{
|
{
|
||||||
return new QueryBuilder($this->table, $this->pk, $this->connection);
|
return new QueryBuilder($this->table, $this->pk, $this->connection, $className);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __set($name, $value): void
|
public function __set($name, $value): void
|
||||||
@@ -132,10 +214,21 @@ class Model implements JsonSerializable
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function getClassName()
|
||||||
|
{
|
||||||
|
return static::class;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Static method to return new QueryBuilder
|
||||||
|
*
|
||||||
|
* @return QueryBuilder
|
||||||
|
*/
|
||||||
public static function q(): QueryBuilder
|
public static function q(): QueryBuilder
|
||||||
{
|
{
|
||||||
|
$cls = self::getClassName();
|
||||||
$ist = new static();
|
$ist = new static();
|
||||||
return $ist->newQueryBuilder();
|
return $ist->newQueryBuilder($cls);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __get($name): mixed
|
public function __get($name): mixed
|
||||||
@@ -156,6 +249,11 @@ class Model implements JsonSerializable
|
|||||||
return $table;
|
return $table;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialize the model in Json
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
public function jsonSerialize(): mixed
|
public function jsonSerialize(): mixed
|
||||||
{
|
{
|
||||||
return $this->values;
|
return $this->values;
|
||||||
|
|||||||
@@ -13,7 +13,13 @@ class Query
|
|||||||
$this->data = [];
|
$this->data = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function addData($value)
|
/**
|
||||||
|
* Add data to the query
|
||||||
|
*
|
||||||
|
* @param array|mixed $value
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function addData(mixed $value)
|
||||||
{
|
{
|
||||||
if (is_array($value)) {
|
if (is_array($value)) {
|
||||||
$this->data = array_merge($this->data, $value);
|
$this->data = array_merge($this->data, $value);
|
||||||
@@ -22,22 +28,44 @@ class Query
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return statement
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public function getQuery(): string
|
public function getQuery(): string
|
||||||
{
|
{
|
||||||
return $this->query;
|
return $this->query;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set Statement
|
||||||
|
*
|
||||||
|
* @param string $query
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function setQuery(string $query)
|
public function setQuery(string $query)
|
||||||
{
|
{
|
||||||
$this->query = $query;
|
$this->query = $query;
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return current data of the query
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
public function getData(): array
|
public function getData(): array
|
||||||
{
|
{
|
||||||
return $this->data;
|
return $this->data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set data of the query
|
||||||
|
*
|
||||||
|
* @param array $data
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function setData(array $data)
|
public function setData(array $data)
|
||||||
{
|
{
|
||||||
$this->data = $data;
|
$this->data = $data;
|
||||||
|
|||||||
@@ -6,9 +6,11 @@ class QueryBuilder
|
|||||||
{
|
{
|
||||||
protected array $columns;
|
protected array $columns;
|
||||||
protected array $wheres;
|
protected array $wheres;
|
||||||
|
protected array $orwheres;
|
||||||
protected array $orders;
|
protected array $orders;
|
||||||
protected array $groupby;
|
protected array $groupby;
|
||||||
protected string $table;
|
protected string $table;
|
||||||
|
protected string $classname;
|
||||||
protected string $connection;
|
protected string $connection;
|
||||||
protected string $pk;
|
protected string $pk;
|
||||||
protected ?int $take;
|
protected ?int $take;
|
||||||
@@ -16,8 +18,12 @@ class QueryBuilder
|
|||||||
protected string $raw_query;
|
protected string $raw_query;
|
||||||
protected bool $distinct;
|
protected bool $distinct;
|
||||||
|
|
||||||
public function __construct($table, $pk = "id", $connection = "")
|
public const MODE_AND = 0;
|
||||||
|
public const MODE_OR = 1;
|
||||||
|
|
||||||
|
public function __construct($table, $pk = "id", $connection = "", $classname = "")
|
||||||
{
|
{
|
||||||
|
$this->classname = $classname;
|
||||||
$this->table = $table;
|
$this->table = $table;
|
||||||
$this->pk = $pk;
|
$this->pk = $pk;
|
||||||
$this->connection = $connection;
|
$this->connection = $connection;
|
||||||
@@ -28,6 +34,7 @@ class QueryBuilder
|
|||||||
{
|
{
|
||||||
$this->columns = [];
|
$this->columns = [];
|
||||||
$this->wheres = [];
|
$this->wheres = [];
|
||||||
|
$this->orwheres = [];
|
||||||
$this->orders = [];
|
$this->orders = [];
|
||||||
$this->groupby = [];
|
$this->groupby = [];
|
||||||
$this->offset = null;
|
$this->offset = null;
|
||||||
@@ -128,12 +135,28 @@ class QueryBuilder
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function orWhere($condition, $operator, $value = null)
|
||||||
|
{
|
||||||
|
if ($value === null) {
|
||||||
|
$this->orwheres[] = new Expression($condition, "=", $operator);
|
||||||
|
} else {
|
||||||
|
$this->orwheres[] = new Expression($condition, $operator, $value);
|
||||||
|
}
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
public function whereRaw(string $raw)
|
public function whereRaw(string $raw)
|
||||||
{
|
{
|
||||||
$this->wheres[] = $raw;
|
$this->wheres[] = $raw;
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function orWhereRaw(string $raw)
|
||||||
|
{
|
||||||
|
$this->orwheres[] = $raw;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
public function find($id): mixed
|
public function find($id): mixed
|
||||||
{
|
{
|
||||||
$this->reset();
|
$this->reset();
|
||||||
@@ -187,7 +210,12 @@ class QueryBuilder
|
|||||||
{
|
{
|
||||||
$ret = array();
|
$ret = array();
|
||||||
foreach ($data as $row) {
|
foreach ($data as $row) {
|
||||||
$model = new Model();
|
if ($this->classname != "") {
|
||||||
|
$model = new $this->classname();
|
||||||
|
} else {
|
||||||
|
$model = new Model();
|
||||||
|
}
|
||||||
|
|
||||||
$ret[] = $model->setPk($this->pk)->setTable($this->table)->fillData($row);
|
$ret[] = $model->setPk($this->pk)->setTable($this->table)->fillData($row);
|
||||||
}
|
}
|
||||||
return new Collection($ret);
|
return new Collection($ret);
|
||||||
@@ -213,10 +241,16 @@ class QueryBuilder
|
|||||||
$query = "SELECT " . $distinct . " " . $columns . " FROM " . $this->table ;
|
$query = "SELECT " . $distinct . " " . $columns . " FROM " . $this->table ;
|
||||||
|
|
||||||
$where = $this->getWhere();
|
$where = $this->getWhere();
|
||||||
|
$Orwhere = $this->getWhere(QueryBuilder::MODE_OR);
|
||||||
|
|
||||||
$this->fillData($ret);
|
$this->fillData($ret);
|
||||||
|
|
||||||
|
if ($where != "" && $Orwhere != "") {
|
||||||
|
$Orwhere = " OR " . $Orwhere;
|
||||||
|
}
|
||||||
|
|
||||||
if ($where != "") {
|
if ($where != "") {
|
||||||
$query .= " WHERE " . $where;
|
$query .= " WHERE " . $where . $Orwhere;
|
||||||
}
|
}
|
||||||
|
|
||||||
$query .= $this->getClause("GROUP By", $this->groupby);
|
$query .= $this->getClause("GROUP By", $this->groupby);
|
||||||
@@ -229,7 +263,7 @@ class QueryBuilder
|
|||||||
|
|
||||||
private function fillData(Query &$query): void
|
private function fillData(Query &$query): void
|
||||||
{
|
{
|
||||||
foreach ($this->wheres as $expression) {
|
foreach (array_merge($this->wheres, $this->orwheres) as $expression) {
|
||||||
if ($expression instanceof Expression) {
|
if ($expression instanceof Expression) {
|
||||||
if ($expression->hasData()) {
|
if ($expression->hasData()) {
|
||||||
$query->addData($expression->getValue());
|
$query->addData($expression->getValue());
|
||||||
@@ -238,10 +272,18 @@ class QueryBuilder
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getWhere(): string
|
private function getWhere(int $mode = QueryBuilder::MODE_AND): string
|
||||||
{
|
{
|
||||||
$where = "";
|
$where = "";
|
||||||
foreach ($this->wheres as $expression) {
|
$collection = match ($mode) {
|
||||||
|
QueryBuilder::MODE_AND => $this->wheres,
|
||||||
|
QueryBuilder::MODE_OR => $this->orwheres,
|
||||||
|
};
|
||||||
|
$keyword = match ($mode) {
|
||||||
|
QueryBuilder::MODE_AND => " AND ",
|
||||||
|
QueryBuilder::MODE_OR => " OR ",
|
||||||
|
};
|
||||||
|
foreach ($collection as $expression) {
|
||||||
$sw = "";
|
$sw = "";
|
||||||
if ($expression instanceof Expression) {
|
if ($expression instanceof Expression) {
|
||||||
$sw = $expression->raw();
|
$sw = $expression->raw();
|
||||||
@@ -252,7 +294,7 @@ class QueryBuilder
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($where != "" && $sw != "") {
|
if ($where != "" && $sw != "") {
|
||||||
$where .= " AND ";
|
$where .= " $keyword ";
|
||||||
}
|
}
|
||||||
$where .= $sw;
|
$where .= $sw;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -98,6 +98,10 @@ test("querybuilder", function() {
|
|||||||
$qb->reset();
|
$qb->reset();
|
||||||
$rows = $qb->whereNotNull("col1")->get();
|
$rows = $qb->whereNotNull("col1")->get();
|
||||||
expect(count($rows))->toBe(2);
|
expect(count($rows))->toBe(2);
|
||||||
|
|
||||||
|
$qb->reset();
|
||||||
|
$rows = $qb->where("id",1)->orWhere("id",2)->get();
|
||||||
|
expect(count($rows))->toBe(2);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("extending model",function()
|
test("extending model",function()
|
||||||
@@ -112,6 +116,8 @@ test("extending model",function()
|
|||||||
$row = $qbs->find(1);
|
$row = $qbs->find(1);
|
||||||
expect($row->id)->toBe(1);
|
expect($row->id)->toBe(1);
|
||||||
expect($row->col1)->toBe("test");
|
expect($row->col1)->toBe("test");
|
||||||
|
|
||||||
|
expect($row)->toBeInstanceOf(Test::class);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("order by", function(){
|
test("order by", function(){
|
||||||
|
|||||||
Reference in New Issue
Block a user