Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
293eb9e555 | ||
|
|
d961d2a80f | ||
|
|
0db845a116 | ||
|
|
35188860ce | ||
|
|
c8d6e911a6 |
@@ -18,6 +18,7 @@ class Connection
|
||||
private string $database;
|
||||
private ?string $port;
|
||||
private ?string $host;
|
||||
private ?string $charset;
|
||||
private string $error;
|
||||
|
||||
private function __construct($name, $config)
|
||||
@@ -44,6 +45,7 @@ class Connection
|
||||
$this->password = isset($config[$key]["PASSWORD"]) ? $config[$key]["PASSWORD"] : null;
|
||||
$this->database = isset($config[$key]["DATABASE"]) ? $config[$key]["DATABASE"] : null;
|
||||
$this->port = isset($config[$key]["PORT"]) ? $config[$key]["PORT"] : null;
|
||||
$this->charset = isset($config[$key]["CHARSET"]) ? $config[$key]["CHARSET"] : null;
|
||||
} catch (\Throwable $th) {
|
||||
$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->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->charset = isset($_ENV[$this->getKey("CHARSET", $key)]) ? $_ENV[$this->getKey("CHARSET", $key)] : null;
|
||||
} catch (\Throwable $th) {
|
||||
$this->error = $th->getMessage();
|
||||
}
|
||||
@@ -117,10 +120,19 @@ class Connection
|
||||
return $stmt;
|
||||
}
|
||||
|
||||
private function getMySQLOptions()
|
||||
{
|
||||
$ret = "";
|
||||
if ($this->charset) {
|
||||
$ret .= ";charset=" . $this->charset;
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
private function getConnString()
|
||||
{
|
||||
$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,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -8,19 +8,33 @@ class Model implements JsonSerializable
|
||||
{
|
||||
protected mixed $values;
|
||||
protected array $updated;
|
||||
protected string $table;
|
||||
protected string $table = "";
|
||||
protected string $connection = "";
|
||||
protected string $pk;
|
||||
private bool $new;
|
||||
private bool $ro;
|
||||
|
||||
public function __construct()
|
||||
public function __construct($ro = false)
|
||||
{
|
||||
$this->new = true;
|
||||
$this->values = array();
|
||||
$this->updated = array();
|
||||
$this->pk = "id";
|
||||
$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";
|
||||
}
|
||||
}
|
||||
|
||||
public function getTable(): string
|
||||
{
|
||||
@@ -70,7 +84,7 @@ class Model implements JsonSerializable
|
||||
|
||||
public function find(mixed $key): mixed
|
||||
{
|
||||
$qb = $this->newQueryBuilder();
|
||||
$qb = $this->newQueryBuilder(get_class($this));
|
||||
$find = $qb->find($key);
|
||||
if ($find !== null) {
|
||||
$this->fillData($find->getValues());
|
||||
@@ -82,7 +96,8 @@ class Model implements JsonSerializable
|
||||
public function save(): bool
|
||||
{
|
||||
$ret = false;
|
||||
$qb = $this->newQueryBuilder();
|
||||
if (!$this->ro) {
|
||||
$qb = $this->newQueryBuilder("");
|
||||
if ($this->new) {
|
||||
$query = $qb->getPreparedQuery($this->values);
|
||||
$id = Connection::getInstance($this->connection)->insertQuery($query);
|
||||
@@ -107,12 +122,13 @@ class Model implements JsonSerializable
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
public function newQueryBuilder(): QueryBuilder
|
||||
public function newQueryBuilder($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
|
||||
@@ -132,10 +148,16 @@ class Model implements JsonSerializable
|
||||
}
|
||||
}
|
||||
|
||||
public static function getClassName()
|
||||
{
|
||||
return static::class;
|
||||
}
|
||||
|
||||
public static function q(): QueryBuilder
|
||||
{
|
||||
$cls = self::getClassName();
|
||||
$ist = new static();
|
||||
return $ist->newQueryBuilder();
|
||||
return $ist->newQueryBuilder($cls);
|
||||
}
|
||||
|
||||
public function __get($name): mixed
|
||||
|
||||
@@ -6,9 +6,11 @@ class QueryBuilder
|
||||
{
|
||||
protected array $columns;
|
||||
protected array $wheres;
|
||||
protected array $orwheres;
|
||||
protected array $orders;
|
||||
protected array $groupby;
|
||||
protected string $table;
|
||||
protected string $classname;
|
||||
protected string $connection;
|
||||
protected string $pk;
|
||||
protected ?int $take;
|
||||
@@ -16,8 +18,12 @@ class QueryBuilder
|
||||
protected string $raw_query;
|
||||
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->pk = $pk;
|
||||
$this->connection = $connection;
|
||||
@@ -28,6 +34,7 @@ class QueryBuilder
|
||||
{
|
||||
$this->columns = [];
|
||||
$this->wheres = [];
|
||||
$this->orwheres = [];
|
||||
$this->orders = [];
|
||||
$this->groupby = [];
|
||||
$this->offset = null;
|
||||
@@ -128,12 +135,28 @@ class QueryBuilder
|
||||
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)
|
||||
{
|
||||
$this->wheres[] = $raw;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function orWhereRaw(string $raw)
|
||||
{
|
||||
$this->orwheres[] = $raw;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function find($id): mixed
|
||||
{
|
||||
$this->reset();
|
||||
@@ -187,7 +210,12 @@ class QueryBuilder
|
||||
{
|
||||
$ret = array();
|
||||
foreach ($data as $row) {
|
||||
if ($this->classname != "") {
|
||||
$model = new $this->classname();
|
||||
} else {
|
||||
$model = new Model();
|
||||
}
|
||||
|
||||
$ret[] = $model->setPk($this->pk)->setTable($this->table)->fillData($row);
|
||||
}
|
||||
return new Collection($ret);
|
||||
@@ -213,10 +241,16 @@ class QueryBuilder
|
||||
$query = "SELECT " . $distinct . " " . $columns . " FROM " . $this->table ;
|
||||
|
||||
$where = $this->getWhere();
|
||||
$Orwhere = $this->getWhere(QueryBuilder::MODE_OR);
|
||||
|
||||
$this->fillData($ret);
|
||||
|
||||
if ($where != "" && $Orwhere != "") {
|
||||
$Orwhere = " OR " . $Orwhere;
|
||||
}
|
||||
|
||||
if ($where != "") {
|
||||
$query .= " WHERE " . $where;
|
||||
$query .= " WHERE " . $where . $Orwhere;
|
||||
}
|
||||
|
||||
$query .= $this->getClause("GROUP By", $this->groupby);
|
||||
@@ -229,7 +263,7 @@ class QueryBuilder
|
||||
|
||||
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->hasData()) {
|
||||
$query->addData($expression->getValue());
|
||||
@@ -238,10 +272,18 @@ class QueryBuilder
|
||||
}
|
||||
}
|
||||
|
||||
private function getWhere(): string
|
||||
private function getWhere(int $mode = QueryBuilder::MODE_AND): string
|
||||
{
|
||||
$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 = "";
|
||||
if ($expression instanceof Expression) {
|
||||
$sw = $expression->raw();
|
||||
@@ -252,7 +294,7 @@ class QueryBuilder
|
||||
}
|
||||
}
|
||||
if ($where != "" && $sw != "") {
|
||||
$where .= " AND ";
|
||||
$where .= " $keyword ";
|
||||
}
|
||||
$where .= $sw;
|
||||
}
|
||||
|
||||
@@ -98,6 +98,10 @@ test("querybuilder", function() {
|
||||
$qb->reset();
|
||||
$rows = $qb->whereNotNull("col1")->get();
|
||||
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()
|
||||
@@ -112,6 +116,8 @@ test("extending model",function()
|
||||
$row = $qbs->find(1);
|
||||
expect($row->id)->toBe(1);
|
||||
expect($row->col1)->toBe("test");
|
||||
|
||||
expect($row)->toBeInstanceOf(Test::class);
|
||||
});
|
||||
|
||||
test("order by", function(){
|
||||
|
||||
Reference in New Issue
Block a user