schema with beans instead of arrays
This commit is contained in:
parent
13fa680b87
commit
024e6e73cb
@ -1,6 +1,7 @@
|
||||
<?php
|
||||
namespace DatabaseHelper;
|
||||
|
||||
use DatabaseHelper\beans\Schema;
|
||||
use DatabaseHelper\enums\Operator;
|
||||
|
||||
trait Conditionable
|
||||
|
@ -1,6 +1,8 @@
|
||||
<?php
|
||||
namespace DatabaseHelper;
|
||||
|
||||
use DatabaseHelper\beans\Schema;
|
||||
|
||||
class Database
|
||||
{
|
||||
/**
|
||||
|
@ -1,6 +1,7 @@
|
||||
<?php
|
||||
namespace DatabaseHelper;
|
||||
|
||||
use DatabaseHelper\beans\Schema;
|
||||
use Exception;
|
||||
use InvalidArgumentException;
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
<?php
|
||||
namespace DatabaseHelper;
|
||||
|
||||
use DatabaseHelper\beans\Schema;
|
||||
use InvalidArgumentException;
|
||||
|
||||
class Insertion
|
||||
|
@ -1,6 +1,7 @@
|
||||
<?php
|
||||
namespace DatabaseHelper;
|
||||
|
||||
use DatabaseHelper\beans\Schema;
|
||||
use DatabaseHelper\enums\Propagation;
|
||||
use DatabaseHelper\enums\Type;
|
||||
use InvalidArgumentException;
|
||||
@ -36,7 +37,7 @@ class Migration
|
||||
|
||||
public function modify(string $name, Type $type, mixed $default = null, bool $isNullable = false, bool $isUnique = false): Migration {
|
||||
$this->schema->requireColumn($name);
|
||||
if (isset($this->schema->foreignKeys[$name]))
|
||||
if (isset($this->schema->references[$name]))
|
||||
throw new InvalidArgumentException('Referencing columns cannot be modified.');
|
||||
|
||||
$this->schema->columns[$name] = [
|
||||
@ -62,7 +63,7 @@ class Migration
|
||||
$name = $foreignTable->primaryKey();
|
||||
$this->schema->requireColumn($name);
|
||||
|
||||
$this->schema->foreignKeys[$name] = [
|
||||
$this->schema->references[$name] = [
|
||||
'name' => $name,
|
||||
'table' => $foreignTable->name,
|
||||
'onDelete' => $onDelete,
|
||||
@ -79,7 +80,7 @@ class Migration
|
||||
if ($this->schema->existsReference($foreignTable))
|
||||
throw new InvalidArgumentException('Foreign table is not referenced.');
|
||||
|
||||
unset($this->schema->foreignKeys[$name]);
|
||||
unset($this->schema->references[$name]);
|
||||
$this->drop($name);
|
||||
|
||||
$this->foreignKeysToDrop[] = $name;
|
||||
@ -131,7 +132,7 @@ class Migration
|
||||
|
||||
// Process foreign keys to add.
|
||||
foreach ($this->foreignKeysToAdd as $key) {
|
||||
$foreignKey = $this->schema->foreignKeys[$key];
|
||||
$foreignKey = $this->schema->references[$key];
|
||||
|
||||
$clause = " ADD CONSTRAINT `fk_{$foreignKey['name']}`";
|
||||
$clause .= " FOREIGN KEY (`{$foreignKey['name']}`)";
|
||||
|
@ -1,11 +1,11 @@
|
||||
<?php
|
||||
namespace DatabaseHelper;
|
||||
|
||||
use DatabaseHelper\beans\Schema;
|
||||
use DatabaseHelper\enums\Aggregation;
|
||||
use DatabaseHelper\enums\Join;
|
||||
use DatabaseHelper\enums\Order;
|
||||
use http\Exception\InvalidArgumentException;
|
||||
use SimplePie\Exception;
|
||||
|
||||
class Query
|
||||
{
|
||||
@ -41,9 +41,9 @@ class Query
|
||||
public function join(Join $join, Schema $other): Query {
|
||||
$foreignKey = null;
|
||||
if($this->schema->existsReference($other))
|
||||
$foreignKey = $this->schema->foreignKeys[$other->name];
|
||||
$foreignKey = $this->schema->references[$other->name];
|
||||
if ($other->existsReference($this->schema))
|
||||
$foreignKey = $other->foreignKeys[$this->schema->name];
|
||||
$foreignKey = $other->references[$this->schema->name];
|
||||
|
||||
if (is_null($foreignKey))
|
||||
throw new InvalidArgumentException('Joins can only applied to referencing columns.');
|
||||
|
81
Schema.php
81
Schema.php
@ -1,81 +0,0 @@
|
||||
<?php
|
||||
namespace DatabaseHelper;
|
||||
|
||||
use DatabaseHelper\enums\Aggregation;
|
||||
use DatabaseHelper\enums\Charset;
|
||||
use DatabaseHelper\enums\Collation;
|
||||
use DatabaseHelper\enums\Engine;
|
||||
use http\Exception\InvalidArgumentException;
|
||||
|
||||
class Schema
|
||||
{
|
||||
public string $name = '';
|
||||
|
||||
public array $columns = [];
|
||||
public array $primaryKey = [];
|
||||
public array $foreignKeys = [];
|
||||
|
||||
public Engine $engine = Engine::INNODB;
|
||||
public Charset $charset = Charset::UTF8;
|
||||
public Collation $collation = Collation::UTF8_GENERAL_CI;
|
||||
|
||||
public function __construct(string $name) {
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
public function requireColumn(string $col): void {
|
||||
if (!$this->existsColumn($col))
|
||||
throw new InvalidArgumentException("Column '$col' is not defined.");
|
||||
}
|
||||
|
||||
public function existsColumn(string $col): bool {
|
||||
return isset($this->columns[$col]);
|
||||
}
|
||||
|
||||
public function existsReference(Schema $schema): bool {
|
||||
foreach ($this->foreignKeys as $foreignKey)
|
||||
if ($foreignKey['table'] == $schema->name)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public function countEntries(): int {
|
||||
return Database::makeQuery($this)
|
||||
->aggregate('*', 'count', Aggregation::COUNT)
|
||||
->query();
|
||||
}
|
||||
|
||||
public function columnType(string $col) {
|
||||
return $this->columns[$col]['type'];
|
||||
}
|
||||
|
||||
public function primaryKey() {
|
||||
return $this->columns['primary']['name'];
|
||||
}
|
||||
|
||||
public function copy(): Schema {
|
||||
$copy = new Schema($this->name);
|
||||
$copy->columns = genericDeepCopy($this->columns);
|
||||
$copy->primaryKey = genericDeepCopy($this->primaryKey);
|
||||
$copy->foreignKeys = genericDeepCopy($this->foreignKeys);
|
||||
$copy->engine = $this->engine;
|
||||
$copy->charset = $this->charset;
|
||||
$copy->collation = $this->collation;
|
||||
return $copy;
|
||||
}
|
||||
|
||||
public function include(Schema $other): void {
|
||||
// Create a copy of the other schema.
|
||||
$otherCopy = $other->copy();
|
||||
|
||||
// Add any column that isn't already defined.
|
||||
foreach ($otherCopy->columns as $colName => $colDef)
|
||||
if (!isset($this->columns[$colName]))
|
||||
$this->columns[$colName] = $colDef;
|
||||
|
||||
// Add any foreign key that doesn't already exist.
|
||||
foreach ($other->foreignKeys as $colName => $foreignKey)
|
||||
if (!isset($this->foreignKeys[$colName]))
|
||||
$this->foreignKeys[$colName] = $foreignKey;
|
||||
}
|
||||
}
|
94
Table.php
94
Table.php
@ -1,6 +1,10 @@
|
||||
<?php
|
||||
namespace DatabaseHelper;
|
||||
|
||||
use DatabaseHelper\beans\Column;
|
||||
use DatabaseHelper\beans\Primary;
|
||||
use DatabaseHelper\beans\Reference;
|
||||
use DatabaseHelper\beans\Schema;
|
||||
use DatabaseHelper\enums\Propagation;
|
||||
use DatabaseHelper\enums\Charset;
|
||||
use DatabaseHelper\enums\Collation;
|
||||
@ -18,42 +22,34 @@ class Table
|
||||
}
|
||||
|
||||
public function column(string $name, Type $type, mixed $default = null, bool $isNullable = false, bool $isUnique = false): Table {
|
||||
$this->table->columns[$name] = [
|
||||
'name' => $name,
|
||||
'default' => $default,
|
||||
'type' => $type,
|
||||
'isNullable' => $isNullable,
|
||||
'isUnique' => $isUnique
|
||||
];
|
||||
$col = new Column;
|
||||
$col->name = $name;
|
||||
$col->default = $default;
|
||||
$col->type = $type;
|
||||
$col->isUnique = $isUnique;
|
||||
$col->isNullable = $isNullable;
|
||||
|
||||
$this->table->columns[$name] = $col;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function primary(string $name, Type $type, bool $autoInc = false): Table {
|
||||
if(isset($this->primaryKey))
|
||||
throw new InvalidArgumentException('Primary column already exists.');
|
||||
|
||||
$this->table->primaryKey = [
|
||||
'name' => $name,
|
||||
'autoInc' => $autoInc
|
||||
];
|
||||
|
||||
return $this->column($name, $type);
|
||||
protected function id(): Table {
|
||||
$id = new Primary;
|
||||
$id->name = $this->table->name . '_id';
|
||||
$this->table->primary = $id;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function reference(Schema $foreignTable, Propagation $onDelete = Propagation::CASCADE, Propagation $onUpdate = Propagation::CASCADE): Table {
|
||||
$name = $foreignTable->primaryKey();
|
||||
if(isset($this->columns[$name]))
|
||||
throw new InvalidArgumentException('Column name already exists.');
|
||||
$name = $foreignTable->primary->name;
|
||||
|
||||
$this->table->foreignKeys[$name] = [
|
||||
'name' => $name,
|
||||
'table' => $foreignTable->name,
|
||||
'onDelete' => $onDelete,
|
||||
'onUpdate' => $onUpdate
|
||||
];
|
||||
$ref = new Reference;
|
||||
$ref->name = $name;
|
||||
$ref->otherTable = $foreignTable;
|
||||
$ref->onDelete = $onDelete;
|
||||
$ref->onUpdate = $onUpdate;
|
||||
|
||||
$this->table->columns[$name] = $foreignTable->columns[$name];
|
||||
$this->table->references[$name] = $ref;
|
||||
return $this;
|
||||
}
|
||||
|
||||
@ -72,26 +68,19 @@ class Table
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the SQL statement.
|
||||
* @return string SQL query.
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function toSql(): string {
|
||||
$primaryKey = $this->table->primaryKey();
|
||||
|
||||
$primaryKey = $this->table->primary->name;
|
||||
$clause = "CREATE TABLE `{$this->table->name}` (\n";
|
||||
$clause .= " PRIMARY KEY (`$primaryKey`),\n";
|
||||
|
||||
foreach ($this->table->columns as $col) {
|
||||
if ($col['name'] !== $primaryKey) {
|
||||
$clause .= " `{$col['name']}` {$col['type']->toString()}";
|
||||
if ($col->name !== $primaryKey) {
|
||||
$clause .= " `$col->name` {$col->type->toString()}";
|
||||
$clause .= !$col->isNullable ? ' NOT NULL' : '';
|
||||
$clause .= $col->isUnique ? ' UNIQUE' : '';
|
||||
|
||||
$clause .= !$col['isNullable'] ? ' NOT NULL' : '';
|
||||
$clause .= $col['isUnique'] ? ' UNIQUE' : '';
|
||||
|
||||
if (!is_null($col['default'])) {
|
||||
$default = is_string($col['default']) ? "'{$col['default']}'" : $col['default'];
|
||||
if (!is_null($col->default)) {
|
||||
$default = is_string($col->default) ? "'{$col->default}'" : $col->default;
|
||||
$clause .= " DEFAULT $default";
|
||||
}
|
||||
|
||||
@ -100,33 +89,34 @@ class Table
|
||||
}
|
||||
|
||||
// Add foreign keys
|
||||
foreach ($this->table->foreignKeys as $key) {
|
||||
$clause .= " FOREIGN KEY (`{$key['name']}`)";
|
||||
$clause .= " REFERENCES `{$key['table']}` (`{$key['name']}`)";
|
||||
$clause .= " ON DELETE {$key['onDelete']->toString()}";
|
||||
$clause .= " ON UPDATE {$key['onUpdate']->toString()},\n";
|
||||
foreach ($this->table->references as $ref) {
|
||||
$clause .= " FOREIGN KEY (`{$ref->name}`)";
|
||||
$clause .= " REFERENCES `{$ref->otherTable->name}` (`{$ref->name}`)";
|
||||
$clause .= " ON DELETE {$ref->onDelete->toString()}";
|
||||
$clause .= " ON UPDATE {$ref->onUpdate->toString()},\n";
|
||||
}
|
||||
|
||||
// Close the SQL string and add constraints
|
||||
$clause = rtrim($clause, ",\n") . "\n) ";
|
||||
$clause .= "ENGINE={$this->table->engine->toString()} ";
|
||||
$clause .= "CHARSET={$this->table->charset->toString()} ";
|
||||
$clause -= "COLLATE={$this->table->collation->toString()};";
|
||||
$clause .= "COLLATE={$this->table->collation->toString()};";
|
||||
return $clause;
|
||||
}
|
||||
|
||||
public function create(): Schema {
|
||||
global $wpdb;
|
||||
$this->id();
|
||||
|
||||
if (empty($this->primaryKey))
|
||||
throw new InvalidArgumentException('A primary key must be defined.');
|
||||
$table_name = $wpdb->prefix . $this->table->name;
|
||||
Database::standardizeTableNames($this->table->name);
|
||||
$tableName = $this->table->name;
|
||||
|
||||
if ($wpdb->get_var("SHOW TABLES LIKE '$table_name'") !== $table_name) {
|
||||
$foundTables = $wpdb->get_var("SHOW TABLES LIKE '$tableName'");
|
||||
if (is_null($foundTables)) {
|
||||
$sql = $this->toSql();
|
||||
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
|
||||
dbDelta($sql);
|
||||
}
|
||||
return $this->table;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
<?php
|
||||
namespace DatabaseHelper;
|
||||
|
||||
use DatabaseHelper\beans\Schema;
|
||||
use DatabaseHelper\enums\Type;
|
||||
use DatabaseHelper\enums\Operator;
|
||||
use InvalidArgumentException;
|
||||
|
15
beans/Column.php
Normal file
15
beans/Column.php
Normal file
@ -0,0 +1,15 @@
|
||||
<?php
|
||||
namespace DatabaseHelper\beans;
|
||||
|
||||
use DatabaseHelper\enums\Type;
|
||||
|
||||
class Column
|
||||
{
|
||||
public string $name;
|
||||
public ?string $default = null;
|
||||
|
||||
public Type $type;
|
||||
|
||||
public bool $isNullable = false;
|
||||
public bool $isUnique = false;
|
||||
}
|
10
beans/Primary.php
Normal file
10
beans/Primary.php
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
namespace DatabaseHelper\beans;
|
||||
|
||||
use DatabaseHelper\enums\Type;
|
||||
|
||||
class Primary extends Column
|
||||
{
|
||||
public string $name;
|
||||
public bool $autoInc = true;
|
||||
}
|
14
beans/Reference.php
Normal file
14
beans/Reference.php
Normal file
@ -0,0 +1,14 @@
|
||||
<?php
|
||||
namespace DatabaseHelper\beans;
|
||||
|
||||
use DatabaseHelper\enums\Propagation;
|
||||
use DatabaseHelper\enums\Type;
|
||||
|
||||
class Reference
|
||||
{
|
||||
public string $name;
|
||||
public ?Schema $otherTable;
|
||||
|
||||
public Propagation $onDelete;
|
||||
public Propagation $onUpdate;
|
||||
}
|
28
beans/Schema.php
Normal file
28
beans/Schema.php
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
namespace DatabaseHelper\beans;
|
||||
|
||||
use DatabaseHelper\enums\Aggregation;
|
||||
use DatabaseHelper\enums\Charset;
|
||||
use DatabaseHelper\enums\Collation;
|
||||
use DatabaseHelper\enums\Engine;
|
||||
use http\Exception\InvalidArgumentException;
|
||||
|
||||
class Schema
|
||||
{
|
||||
public string $name = '';
|
||||
public Primary $primary;
|
||||
|
||||
/**
|
||||
* @var array<string, Column>
|
||||
*/
|
||||
public array $columns = [];
|
||||
|
||||
/**
|
||||
* @var array<string, Reference>
|
||||
*/
|
||||
public array $references = [];
|
||||
|
||||
public Engine $engine = Engine::INNODB;
|
||||
public Charset $charset = Charset::UTF8;
|
||||
public Collation $collation = Collation::UTF8_GENERAL_CI;
|
||||
}
|
Loading…
Reference in New Issue
Block a user