Skip to content

Commit 8018168

Browse files
committed
Added CreatedAt, UpdatedAt and DeletedAt
1 parent 52025ec commit 8018168

File tree

14 files changed

+186
-40
lines changed

14 files changed

+186
-40
lines changed

README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,18 @@ class User {
3535

3636
#[Column]
3737
public ?string $description;
38+
39+
#[Column(sqlType: "TIMESTAMP")]
40+
#[CreatedAt]
41+
public ?string $createdAt;
42+
43+
#[Column(sqlType: "TIMESTAMP")]
44+
#[UpdatedAt]
45+
public ?string $updatedAt;
46+
47+
#[Column(sqlType: "TIMESTAMP")]
48+
#[DeletedAt]
49+
public ?string $deletedAt;
3850
}
3951
```
4052
### example.php

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "interaapps/uloleorm",
3-
"version": "3.1.2",
3+
"version": "3.1.3",
44
"type": "library",
55
"authors": [
66
{

de/interaapps/ulole/orm/ModelInformation.php

Lines changed: 45 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@
33
namespace de\interaapps\ulole\orm;
44

55
use de\interaapps\ulole\orm\attributes\Column;
6+
use de\interaapps\ulole\orm\attributes\CreatedAt;
7+
use de\interaapps\ulole\orm\attributes\DeletedAt;
8+
use de\interaapps\ulole\orm\attributes\Identifier;
69
use de\interaapps\ulole\orm\attributes\Table;
10+
use de\interaapps\ulole\orm\attributes\UpdatedAt;
711
use ReflectionClass;
812
use ReflectionException;
913

@@ -16,9 +20,13 @@ class ModelInformation {
1620
* @var ColumnInformation[]
1721
*/
1822
private array $fields;
19-
private ?string $name;
23+
private ?string $name = null;
2024
private bool $disableAutoMigrate = false;
2125

26+
private ?string $createdAt = null;
27+
private ?string $updatedAt = null;
28+
private ?string $deletedAt = null;
29+
2230
private const PHP_SQL_TYPES = [
2331
"int" => "INTEGER",
2432
"float" => "FLOAT",
@@ -38,9 +46,10 @@ public function __construct(
3846

3947
if (count($tableAttributes) > 0) {
4048
$tableAttribute = $tableAttributes[0]->newInstance();
41-
$this->name = $tableAttribute->value;
49+
$this->name = $tableAttribute->name;
4250
$this->disableAutoMigrate = $tableAttribute->disableAutoMigrate;
43-
} else {
51+
}
52+
if ($this->name === null) {
4453
$this->name = strtolower(preg_replace('/(?<!^)[A-Z]/', '_$0', $reflection->getShortName()));
4554
if (!str_ends_with($this->name, "s"))
4655
$this->name .= "s";
@@ -51,7 +60,21 @@ public function __construct(
5160
$columnAttributes = $property->getAttributes(Column::class);
5261
if (count($columnAttributes) > 0) {
5362
$columnAttribute = $columnAttributes[0]->newInstance();
54-
$this->fields[$property->getName()] = new ColumnInformation($columnAttribute->name ?? strtolower(preg_replace('/(?<!^)[A-Z]/', '_$0', $property->getName())), $columnAttribute, $property);
63+
$columnInfo = new ColumnInformation($columnAttribute->name ?? strtolower(preg_replace('/(?<!^)[A-Z]/', '_$0', $property->getName())), $columnAttribute, $property);
64+
65+
$this->fields[$property->getName()] = $columnInfo;
66+
67+
if ($columnAttribute->id)
68+
$this->identifier = $property->getName();
69+
70+
if (count($property->getAttributes(CreatedAt::class)))
71+
$this->createdAt = $property->getName();
72+
73+
if (count($property->getAttributes(UpdatedAt::class)))
74+
$this->updatedAt = $property->getName();
75+
76+
if (count($property->getAttributes(DeletedAt::class)))
77+
$this->deletedAt = $property->getName();
5578
}
5679
}
5780
}
@@ -94,8 +117,6 @@ public function getColumnInformation(string $name): ColumnInformation|null {
94117
}
95118

96119
public function getFieldValue($obj, string $field): string {
97-
98-
99120
return $obj->{$this->getFieldName($field)};
100121
}
101122

@@ -106,11 +127,11 @@ public function getIdentifierValue($obj): string {
106127
public function isAutoMigrateDisabled(): bool {
107128
return $this->disableAutoMigrate;
108129
}
109-
110-
public function autoMigrate(array|null $databases = null) : ModelInformation {
130+
131+
public function autoMigrate(array|null $databases = null): ModelInformation {
111132
if ($databases === null)
112133
$databases = UloleORM::getDatabases();
113-
134+
114135
foreach ($databases as $database) {
115136
$tables = [];
116137
foreach ($database->query("SHOW TABLES;")->fetchAll() as $r) {
@@ -138,7 +159,8 @@ public function autoMigrate(array|null $databases = null) : ModelInformation {
138159
"identifier" => $isIdentifier,
139160
"query" => "`" . $field->getFieldName() . "` "
140161
. $type
141-
. ($field->getType()->allowsNull() ? '' : ' NOT NULL')
162+
. ($field->getType()->allowsNull() ? ' NULL' : ' NOT NULL')
163+
. ($field->getColumnAttribute()->unique ? ' UNIQUE' : '')
142164
. ($type == 'INTEGER' && $isIdentifier ? ' AUTO_INCREMENT' : '')
143165
];
144166
}, $fields);
@@ -182,7 +204,19 @@ public function autoMigrate(array|null $databases = null) : ModelInformation {
182204
}
183205
}
184206

185-
207+
186208
return $this;
187209
}
210+
211+
public function getCreatedAt(): ?string {
212+
return $this->createdAt;
213+
}
214+
215+
public function getDeletedAt(): ?string {
216+
return $this->deletedAt;
217+
}
218+
219+
public function getUpdatedAt(): ?string {
220+
return $this->updatedAt;
221+
}
188222
}

de/interaapps/ulole/orm/ORMModel.php

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public function save(string $database = 'main'): bool {
2525
if (isset($this->{$fieldName}))
2626
$query->set($modelInformation->getFieldName(), $this->{$fieldName});
2727
}
28-
return $query->where(UloleORM::getModelInformation(static::class)->getIdentifier(), UloleORM::getModelInformation(static::class)->getIdentifierValue($this))->update() !== false;
28+
return $query->whereId(UloleORM::getModelInformation(static::class)->getIdentifierValue($this))->update();
2929
} else {
3030
return $this->insert($database);
3131
}
@@ -34,9 +34,17 @@ public function save(string $database = 'main'): bool {
3434
public function insert(string $database = 'main'): bool {
3535
$fields = [];
3636
$values = [];
37-
foreach (UloleORM::getModelInformation(static::class)->getFields() as $fieldName => $modelInformation) {
37+
$modelInfo = UloleORM::getModelInformation(static::class);
38+
39+
$createdAt = $modelInfo->getUpdatedAt();
40+
if ($createdAt !== null && !isset($this->createdAt)) {
41+
$fields[] = $modelInfo->getFieldName($createdAt);
42+
$values[] = date("Y-m-d H:i:s");
43+
}
44+
45+
foreach ($modelInfo->getFields() as $fieldName => $columnInformation) {
3846
if (isset($this->{$fieldName})) {
39-
$fields[] = $modelInformation->getFieldName();
47+
$fields[] = $columnInformation->getFieldName();
4048
$values[] = $this->{$fieldName};
4149
}
4250
}
@@ -63,7 +71,7 @@ public function insert(string $database = 'main'): bool {
6371

6472
public function delete(string $database = 'main'): bool {
6573
return self::table($database)
66-
->where(UloleORM::getModelInformation(static::class)->getIdentifier(), UloleORM::getModelInformation(static::class)->getIdentifierValue($this))
74+
->whereId(UloleORM::getModelInformation(static::class)->getIdentifierValue($this))
6775
->delete();
6876
}
6977

de/interaapps/ulole/orm/Query.php

Lines changed: 46 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ class Query {
1717
private int|null $offset = null;
1818
private array|null $orderBy = null;
1919
private bool $temporaryQuery = false;
20+
private bool $withDeleted = false;
2021
private ModelInformation $modelInformation;
2122

2223
/**
@@ -49,7 +50,12 @@ public function where(string $field, mixed $var2, mixed $var3 = null): Query {
4950
$operator = '=';
5051
} else
5152
$value = $var3;
52-
return $this->whereRaw('`'.$this->modelInformation->getFieldName($field).'`', $operator, '?', [$value]);
53+
return $this->whereRaw('`' . $this->modelInformation->getFieldName($field) . '`', $operator, '?', [$value]);
54+
}
55+
56+
public function whereId($id): Query {
57+
$this->whereRaw("`" . $this->modelInformation->getIdentifier() . "`", "=", "?", [$id]);
58+
return $this;
5359
}
5460

5561
public function whereDay(string $field, mixed $val): Query {
@@ -96,17 +102,17 @@ public function whereColumns(string $field1Table, string $field1Name, string $op
96102
$this->queries[] = [
97103
'type' => 'AND',
98104
'query' =>
99-
UloleORM::getTableName($field1Table) . '.`' . UloleORM::getModelInformation($field1Table)->getFieldName($field1Name) . '` '
105+
UloleORM::getTableName($field1Table) . '.`' . UloleORM::getModelInformation($field1Table)->getFieldName($field1Name) . '` '
100106
. $operator . ' '
101-
. UloleORM::getTableName($field2Table) . '.`' . UloleORM::getModelInformation($field2Table)->getFieldName($field2Name).'`'];
107+
. UloleORM::getTableName($field2Table) . '.`' . UloleORM::getModelInformation($field2Table)->getFieldName($field2Name) . '`'];
102108
return $this;
103109
}
104110

105111
/**
106112
* @return $this
107113
*/
108114
public function orWhere(string $var1, mixed $var2, mixed $var3 = null): Query {
109-
return $this->or(fn ($q) => $q->where($var1, $var2, $var3));
115+
return $this->or(fn($q) => $q->where($var1, $var2, $var3));
110116
}
111117

112118
/**
@@ -190,7 +196,7 @@ public function whereExists(string $table, callable $callable): Query {
190196
* @throws Null
191197
*/
192198
public function in(string $field, callable|array $var, string|null $table = null): Query {
193-
$query = ['type' => 'WHERE_IN', "column" => '`'.$this->modelInformation->getFieldName($field).'`', "not" => false];
199+
$query = ['type' => 'WHERE_IN', "column" => '`' . $this->modelInformation->getFieldName($field) . '`', "not" => false];
194200
if (is_array($var)) {
195201
$query["query"] = implode(",", array_map(fn() => "?", $var));
196202
$query["vars"] = $var;
@@ -206,6 +212,7 @@ public function in(string $field, callable|array $var, string|null $table = null
206212

207213
return $this;
208214
}
215+
209216
public function notIn(string $field, callable|array $var, string|null $table = null): Query {
210217
$this->in($field, $var, $table);
211218
$this->queries[count($this->queries) - 1]["not"] = true;
@@ -240,14 +247,15 @@ public function first(): mixed {
240247
if ($this->limit === null)
241248
$this->limit(1);
242249

243-
return $this->get()[0] ?? null;
250+
return $this->all()[0] ?? null;
244251
}
245252

246253
/**
247254
* @return T[]
248255
*/
249256
public function all(): array {
250257
$vars = [];
258+
251259
$query = $this->buildQuery();
252260
$vars = array_merge($vars, $query->vars);
253261

@@ -283,7 +291,7 @@ private function selectNumber(string $f): int|float {
283291
$vars = [];
284292
$query = $this->buildQuery();
285293
$vars = array_merge($vars, $query->vars);
286-
$statement = $this->run('SELECT '.$f.' as num FROM ' . UloleORM::getTableName($this->model) . $query->query . ';', $vars);
294+
$statement = $this->run('SELECT ' . $f . ' as num FROM ' . UloleORM::getTableName($this->model) . $query->query . ';', $vars);
287295
$statement->setFetchMode(PDO::FETCH_NUM);
288296
$result = $statement->fetch();
289297
if ($result === false)
@@ -297,39 +305,49 @@ public function count(): int {
297305
}
298306

299307
public function sum(string $field): float|int {
300-
return $this->selectNumber("SUM(`".$this->modelInformation->getFieldName($field)."`)");
308+
return $this->selectNumber("SUM(`" . $this->modelInformation->getFieldName($field) . "`)");
301309
}
302310

303311
public function sub(string $field): float|int {
304-
return $this->selectNumber("SUM(-`".$this->modelInformation->getFieldName($field)."`)");
312+
return $this->selectNumber("SUM(-`" . $this->modelInformation->getFieldName($field) . "`)");
305313
}
306314

307315
public function avg(string $field): float|int {
308-
return $this->selectNumber("AVG(`".$this->modelInformation->getFieldName($field)."`)");
316+
return $this->selectNumber("AVG(`" . $this->modelInformation->getFieldName($field) . "`)");
309317
}
310318

311319
public function min(string $field): float|int {
312-
return $this->selectNumber("MIN(`".$this->modelInformation->getFieldName($field)."`)");
320+
return $this->selectNumber("MIN(`" . $this->modelInformation->getFieldName($field) . "`)");
313321
}
314322

315323
public function max(string $field): float|int {
316-
return $this->selectNumber("MAX(`".$this->modelInformation->getFieldName($field)."`)");
324+
return $this->selectNumber("MAX(`" . $this->modelInformation->getFieldName($field) . "`)");
317325
}
318326

319327
public function update(): bool {
320328
$vars = [];
329+
330+
$updatedAt = $this->modelInformation->getUpdatedAt();
331+
if ($updatedAt !== null) {
332+
$this->set($updatedAt, date("Y-m-d H:i:s"));
333+
}
334+
321335
$query = $this->buildQuery();
322336
$vars = array_merge($vars, $query->vars);
323337

324-
return $this->run('UPDATE `' . UloleORM::getTableName($this->model) . '`' . $query->query . ';', $vars, true);
338+
return $this->run('UPDATE `' . UloleORM::getTableName($this->model) . '`' . $query->query . ';', $vars, true) !== false;
325339
}
326340

327341
public function delete(): bool {
328342
$vars = [];
329343
$query = $this->buildQuery();
330344
$vars = array_merge($vars, $query->vars);
331345

332-
return $this->run('DELETE FROM `' . UloleORM::getTableName($this->model) . '`' . $query->query . ';', $vars, true);
346+
$deletedAt = $this->modelInformation->getDeletedAt();
347+
if ($deletedAt !== null)
348+
$this->set($this->modelInformation->getFieldName($deletedAt), date("Y-m-d H:i:s"))->update();
349+
350+
return $this->run('DELETE FROM `' . UloleORM::getTableName($this->model) . '`' . $query->query . ';', $vars, true) !== false;
333351
}
334352

335353
public function run(string $query, array $vars = [], bool $returnResult = false): PDOStatement|bool|null {
@@ -345,13 +363,17 @@ public function run(string $query, array $vars = [], bool $returnResult = false)
345363
}
346364

347365
protected function buildQuery(): object {
366+
$deletedAt = $this->modelInformation->getDeletedAt();
367+
if ($deletedAt !== null && !$this->withDeleted)
368+
$this->isNull($this->modelInformation->getFieldName($deletedAt));
369+
348370
$out = (object)["query" => '', 'vars' => []];
349371

350372
$usedWhere = $this->temporaryQuery;
351373
$usedSet = false;
352374
$useCondition = false;
353375

354-
foreach (array_filter($this->queries, fn ($q) => $q["type"] == "SET") as $query) {
376+
foreach (array_filter($this->queries, fn($q) => $q["type"] == "SET") as $query) {
355377
if (!$usedSet) {
356378
$out->query .= " SET ";
357379
$usedSet = true;
@@ -390,10 +412,10 @@ protected function buildQuery(): object {
390412
$out->query .= $where->query;
391413
$out->query .= ') ';
392414
}
393-
} else if ($query["type"] == 'WHERE_EXISTS' || $query["type"] == 'WHERE_NOT_EXISTS') {
394-
$out->query .= " WHERE " . ($query["type"] == 'WHERE_NOT_EXISTS' ? "NOT " : "") . "EXISTS (".$query["query"].")";
395-
} else if ($query["type"] == 'WHERE_IN') {
396-
$out->query .= " WHERE " . $query["column"] . ($query["not"] ? " NOT " : ' ')." IN (".$query["query"].")";
415+
} else if ($query["type"] == 'WHERE_EXISTS' || $query["type"] == 'WHERE_NOT_EXISTS') {
416+
$out->query .= " WHERE " . ($query["type"] == 'WHERE_NOT_EXISTS' ? "NOT " : "") . "EXISTS (" . $query["query"] . ")";
417+
} else if ($query["type"] == 'WHERE_IN') {
418+
$out->query .= " WHERE " . $query["column"] . ($query["not"] ? " NOT " : ' ') . " IN (" . $query["query"] . ")";
397419
$out->vars = $query["vars"];
398420
}
399421
}
@@ -411,6 +433,11 @@ public function getQueries(): array {
411433
return $this->queries;
412434
}
413435

436+
public function withDeleted($withDeleted = true): Query {
437+
$this->withDeleted = $withDeleted;
438+
return $this;
439+
}
440+
414441
/**
415442
* @return $this
416443
*/

de/interaapps/ulole/orm/UloleORM.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ public static function getTableName($modelClazz): string {
7575
*/
7676
public static function getModelInformation($model): ModelInformation {
7777
if (!isset(self::$modelInformation[$model]))
78-
throw new \Exception("Register the model first with UloleORM::register(".$model."::class);");
78+
throw new \Exception("Register the model first with UloleORM::register(" . $model . "::class);");
7979
return self::$modelInformation[$model];
8080
}
8181

de/interaapps/ulole/orm/attributes/Column.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@
44

55
use Attribute;
66

7-
#[Attribute]
7+
#[Attribute(Attribute::TARGET_PROPERTY)]
88
class Column {
99
public function __construct(
1010
public ?string $name = null,
1111
public ?string $sqlType = null,
1212
public string|int|null $size = null,
1313
public bool $index = false,
14+
public bool $id = false,
15+
public bool $unique = false,
1416
) {
1517
}
1618
}

0 commit comments

Comments
 (0)