Skip to content

Commit

Permalink
Added postgres and sqlite support
Browse files Browse the repository at this point in the history
  • Loading branch information
JulianFun123 committed Jul 27, 2022
1 parent f9d3a33 commit 6159d29
Show file tree
Hide file tree
Showing 14 changed files with 610 additions and 308 deletions.
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Ulole-ORM `3.1`
# Ulole-ORM `3.2`

## Getting started
UloleORM is an Object Relation Mapper written in PHP.
Expand Down Expand Up @@ -54,12 +54,12 @@ class User {
```php
<?php
UloleORM::database("main", new Database(
'username',
'password',
'database',
'host', /* PORT: default localhost */
3306, /* PORT: default 3306 */
'mysql' /* DRIVER: default mysql (Every PDO Driver usable. ) */
username: 'root',
password: '1234',
database: 'testing',
host: 'localhost',
port: 3306,
driver: 'mysql' // You can also use sqlite for testing or pgsql for postgres
));

UloleORM::register(User::class);
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "interaapps/uloleorm",
"version": "3.1.3",
"version": "3.2.0",
"type": "library",
"authors": [
{
Expand Down
88 changes: 38 additions & 50 deletions de/interaapps/ulole/orm/Database.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,18 @@

namespace de\interaapps\ulole\orm;

use de\interaapps\ulole\orm\drivers\Driver;
use de\interaapps\ulole\orm\drivers\MySQLDriver;
use de\interaapps\ulole\orm\drivers\PostgresDriver;
use de\interaapps\ulole\orm\drivers\SQLiteDriver;
use de\interaapps\ulole\orm\migration\Blueprint;
use PDO;
use PDOStatement;

class Database {
private PDO $connection;
private Driver $driver;

private static $driverFactories = [];

/**
* @param string $username
Expand All @@ -17,61 +23,20 @@ class Database {
* @param int $port
* @param string $driver
*/
public function __construct(string $username, string|null $password = null, string|null $database = null, string $host = 'localhost', int $port = 3306, string $driver = "mysql") {
if ($driver == "sqlite")
$this->connection = new PDO($driver . ':' . $database);
else
$this->connection = new PDO($driver . ':host=' . $host . ';dbname=' . $database, $username, $password);
}

public function getConnection(): PDO {
return $this->connection;
public function __construct(string $username = "", string|null $password = null, string|null $database = null, string $host = 'localhost', int|null $port = null, string $driver = "mysql") {
$this->driver = self::getDriverFactories()[$driver]($username, $password, $database, $host, $port, $driver);
}

public function query($sql): PDOStatement|bool {
return $this->connection->query($sql);
public function create(string $name, callable $callable, bool $ifNotExists = false): bool {
return $this->driver->create($name, $callable);
}

public function create(string $name, $callable, bool $ifNotExists = false): PDOStatement|bool {
$blueprint = new Blueprint();
$callable($blueprint);
$sql = "CREATE TABLE " . ($ifNotExists ? "IF NOT EXISTS " : "") . "`" . $name . "` (\n";
$sql .= implode(",\n", $blueprint->getQueries(true));
$sql .= "\n) ENGINE = InnoDB;";

return $this->query($sql);
}

public function edit(string $name, $callable): PDOStatement|bool {
$statement = $this->connection->query("SHOW COLUMNS FROM " . $name . ";");
$existingColumns = [];
foreach ($statement->fetchAll(\PDO::FETCH_NUM) as $row) {
$existingColumns[] = $row[0];
}
$blueprint = new Blueprint();
$callable($blueprint);
$sql = "ALTER TABLE `" . $name . "`";
$comma = false;
foreach ($blueprint->getQueries() as $column => $query) {
if ($comma)
$sql .= ", ";

if (in_array($column, $existingColumns))
$sql .= (substr($query, 0, 4) === "DROP" ? "" : "CHANGE `" . $column . "` ") . $query;
else
$sql .= " ADD " . $query;

if (!$comma)
$comma = true;
}
$sql .= ";";

return $this->query($sql);
public function edit(string $name, callable $callable): bool {
return $this->driver->edit($name, $callable);
}


public function drop(string $name): PDOStatement|bool {
return $this->query("DROP TABLE `" . $name . "`;");
return $this->driver->drop($name);
}

public function autoMigrate(): Database {
Expand All @@ -85,4 +50,27 @@ public function autoMigrate(): Database {
return $this;
}

}
public function getDriver(): Driver {
return $this->driver;
}

public static function setDriverFactory(string $name, callable $callable) {
self::$driverFactories[$name] = $callable;
}

public static function getDriverFactories(): array {
return self::$driverFactories;
}
}

Database::setDriverFactory("mysql", function (string $username, string|null $password, string|null $database, string $host, int|null $port, string $driver) : Driver {
return new MySQLDriver(new PDO($driver . ':host=' . $host. ':' . ($port ?? 3306) . ';dbname=' . $database, $username, $password));
});

Database::setDriverFactory("pgsql", function (string $username, string|null $password, string|null $database, string $host, int|null $port, string $driver) : Driver {
return new PostgresDriver(new PDO($driver . ':host=' . $host . ';dbname=' . $database, $username, $password));
});

Database::setDriverFactory("sqlite", function (string $username, string|null $password, string|null $database, string $host, int|null $port, string $driver) : Driver {
return new SQLiteDriver(new PDO($driver . ':' . $database));
});
74 changes: 26 additions & 48 deletions de/interaapps/ulole/orm/ModelInformation.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use de\interaapps\ulole\orm\attributes\Identifier;
use de\interaapps\ulole\orm\attributes\Table;
use de\interaapps\ulole\orm\attributes\UpdatedAt;
use de\interaapps\ulole\orm\migration\Blueprint;
use ReflectionClass;
use ReflectionException;

Expand All @@ -31,7 +32,7 @@ class ModelInformation {
"int" => "INTEGER",
"float" => "FLOAT",
"string" => "TEXT",
"bool" => "TINYINT"
"bool" => "BOOL"
];

/**
Expand Down Expand Up @@ -133,74 +134,51 @@ public function autoMigrate(array|null $databases = null): ModelInformation {
$databases = UloleORM::getDatabases();

foreach ($databases as $database) {
$tables = [];
foreach ($database->query("SHOW TABLES;")->fetchAll() as $r) {
$tables[] = $r[0];
}
$tables = $database->getDriver()->getTables();

$fields = $this->getFields();

$columns = array_map(function ($field) {
$type = $field->getColumnAttribute()->sqlType;
if ($type == null) {
if (isset(self::PHP_SQL_TYPES[$field->getType()->getName()]))
if (isset(self::PHP_SQL_TYPES[$field->getType()->getName()])) {
$type = self::PHP_SQL_TYPES[$field->getType()->getName()];
if ($type == "TEXT" && $field->getColumnAttribute()->size !== null)
$type = "VARCHAR";
}
}

if ($field->getColumnAttribute()->size != null)
$type .= "(" . $field->getColumnAttribute()->size . ")";

$isIdentifier = $this->getIdentifier() == $field->getFieldName();

return [
"field" => $field->getFieldName(),
"type" => $type,
"hasIndex" => $field->getColumnAttribute()->index,
"identifier" => $isIdentifier,
"query" => "`" . $field->getFieldName() . "` "
. $type
. ($field->getType()->allowsNull() ? ' NULL' : ' NOT NULL')
. ($field->getColumnAttribute()->unique ? ' UNIQUE' : '')
. ($type == 'INTEGER' && $isIdentifier ? ' AUTO_INCREMENT' : '')
];
}, $fields);
"blueprintHandler" => function (Blueprint $blueprint) use ($isIdentifier, $type, $field) {
$col = $blueprint->custom($field->getFieldName(), $type, $field->getColumnAttribute()->size);

$indexes = array_filter($columns, fn($c) => $c["hasIndex"]);
if ($type == "INTEGER" && $isIdentifier)
$col->ai()->primary();

if (in_array($this->getName(), $tables)) {
$existingFields = array_map(fn($f) => $f[0], $database->query('SHOW COLUMNS FROM ' . $this->getName() . ';')->fetchAll());
$existingIndexes = array_map(fn($f) => $f[4], $database->query('SHOW INDEXES FROM ' . $this->getName() . ';')->fetchAll());

$q = "ALTER TABLE `" . $this->getName() . "` ";
$changes = [];
foreach ($columns as $column) {
if (in_array($column['field'], $existingFields)) {
$changes[] = "MODIFY COLUMN " . $column["query"];
} else {
$changes[] = "ADD " . $column["query"];
if ($field->getColumnAttribute()->unique)
$col->unqiue();

$col->nullable($field->getType()->allowsNull());
}
}
foreach ($indexes as $index) {
$index = $index["field"];
if (!in_array($index, $existingIndexes))
$changes[] = 'ADD INDEX (`' . $index . '`);';
}
];
}, $fields);

$q .= implode(", ", $changes) . ';';
$database->query($q);
if (in_array($this->getName(), $tables)) {
$database->edit($this->getName(), function (Blueprint $blueprint) use ($columns) {
foreach ($columns as $column)
$column["blueprintHandler"]($blueprint);
});
} else {
$q = "CREATE TABLE " . $this->getName() . " (" .
implode(', ', array_map(fn($c) => $c['query']
. ($c['identifier'] ? ' PRIMARY KEY' : ''
), $columns)
);

if (count($indexes) > 0) {
$q .= ", INDEX (" . implode(", ", array_map(fn($c) => $c["field"], $indexes)) . ")";
}

$q .= ");";
$database->query($q);
$database->create($this->getName(), function (Blueprint $blueprint) use ($columns) {
foreach ($columns as $column)
$column["blueprintHandler"]($blueprint);
});
}
}

Expand Down
22 changes: 6 additions & 16 deletions de/interaapps/ulole/orm/ORMModel.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,24 +49,14 @@ public function insert(string $database = 'main'): bool {
}
}

$query = 'INSERT INTO `' . UloleORM::getTableName(static::class) . '` (';
$insertion = UloleORM::getDatabase($database)->getDriver()->insert(UloleORM::getTableName(static::class), $fields, $values);

foreach ($fields as $i => $field)
$query .= ($i == 0 ? '' : ', ') . '`' . $field . '`';
if ($insertion === false)
return false;

$query .= ') VALUES (';

foreach ($values as $i => $value)
$query .= ($i == 0 ? '' : ', ') . '?';
$query .= ')';

$statement = UloleORM::getDatabase($database)->getConnection()->prepare($query);

$result = $statement->execute($values);
$this->{UloleORM::getModelInformation(static::class)->getIdentifier()} = UloleORM::getDatabase($database)->getConnection()->lastInsertId();
if ($result)
$this->ormInternals_entryExists = true;
return $result;
$this->{UloleORM::getModelInformation(static::class)->getIdentifier()} = $insertion;
$this->ormInternals_entryExists = true;
return true;
}

public function delete(string $database = 'main'): bool {
Expand Down
Loading

0 comments on commit 6159d29

Please sign in to comment.