aboutsummaryrefslogtreecommitdiffhomepage
path: root/WpfTest/Model.php
diff options
context:
space:
mode:
Diffstat (limited to 'WpfTest/Model.php')
-rw-r--r--WpfTest/Model.php46
1 files changed, 39 insertions, 7 deletions
diff --git a/WpfTest/Model.php b/WpfTest/Model.php
index 26a7b49..c006ffd 100644
--- a/WpfTest/Model.php
+++ b/WpfTest/Model.php
@@ -3,8 +3,6 @@ namespace WpfTest;
abstract class Model {
private static function mangleName(string $name): string {
- if ($name == 'self')
- return 'uri';
$chars = str_split($name);
$chars[0] = strtolower($chars[0]);
for ($i = 0; $i < count($chars); $i++) {
@@ -17,8 +15,6 @@ abstract class Model {
}
private static function unmangleName(string $name): string {
- if ($name == 'uri')
- return 'self';
$chars = str_split($name);
for ($i = 0; $i < count($chars); $i++) {
if ($chars[$i] == '_') {
@@ -41,32 +37,68 @@ abstract class Model {
public static function fromDbRow(array|false $columns): ?static {
if ($columns === false)
return null;
+ // create the model
$obj = new static();
$refl = new \ReflectionObject($obj);
+ // for each field of the db row ...
foreach (array_keys($columns) as $name) {
$value = $columns[$name];
- $name = self::unmangleName($name);
+ $name = self::unmangleName($name); // guess the appropriate field in the model
try {
+ // try to assign it directly (works for simple values)
$obj->{$name} = $value;
} catch (\TypeError $e) {
+ // if it's not the right type we have to try to wrangle it into the right one
+ // there's a few strategies for this
$type = $refl->getProperty($name)->getType();
if ($type == null || !is_a($type, \ReflectionNamedType::class))
throw $e;
- $obj->{$name} = new ($type->getName())($value);
+ $typeClass = $type->getName();
+ if (enum_exists($typeClass)) {
+ // if it's an enum we can find the enum case with the same name
+ $obj->{$name} = (new \ReflectionEnum($typeClass))->getCase($value)->getValue();
+ } elseif (is_subclass_of($typeClass, Model::class) && is_int($value)) {
+ // if it's another model we can try to look it up by id automatically
+ $obj->{$name} = $typeClass::find($value);
+ } else {
+ // otherwise try to instantiate the correct class and pass it the simple value
+ $obj->{$name} = new $typeClass($value);
+ }
}
}
+ // set up any extra-complicated fields if needed
+ $obj->hydrate($columns);
return $obj;
}
+ /**
+ * Initialises fields of the model that contain more complex objects
+ * @param array $row the row of the database
+ * @return void
+ */
+ protected function hydrate(array $row) {
+ }
+
public static function findWhere(string $whereClause, array $parameters): ?static {
$classNameParts = explode('\\', static::class);
$className = $classNameParts[count($classNameParts) - 1];
$tableName = self::mangleName($className);
- $stmt = Db::getInstance()->getPdo()->prepare("SELECT * FROM $tableName WHERE $whereClause");
+ $stmt = Db::getInstance()->getPdo()->prepare("SELECT * FROM $tableName WHERE $whereClause LIMIT 1");
$stmt->execute($parameters);
return static::fromDbRow($stmt->fetch(\PDO::FETCH_ASSOC));
}
+ public static function findAllWhere(string $whereClause, array $parameters): array {
+ $classNameParts = explode('\\', static::class);
+ $className = $classNameParts[count($classNameParts) - 1];
+ $tableName = self::mangleName($className);
+ $stmt = Db::getInstance()->getPdo()->prepare("SELECT * FROM $tableName WHERE $whereClause");
+ $stmt->execute($parameters);
+ return array_map(function ($row) {
+ return static::fromDbRow($row);
+ }, $stmt->fetchAll(\PDO::FETCH_ASSOC));
+ }
+
public static function find(int $id): ?static {
return static::findWhere('id = ?', [$id]);
}