Seperate table and schema
This commit is contained in:
parent
ed099a8bcb
commit
817513095e
@ -1,52 +1,72 @@
|
||||
<?php
|
||||
namespace DatabaseHelper;
|
||||
|
||||
namespace DatabaseHelper;
|
||||
use DatabaseHelper\enums\ColumnTypes;
|
||||
use InvalidArgumentException;
|
||||
use wpdb;
|
||||
|
||||
global $wpdb;
|
||||
|
||||
class Insertion
|
||||
{
|
||||
private Table $table;
|
||||
private array $currentRow = [];
|
||||
private array $batchRows = [];
|
||||
private bool $isReady = false;
|
||||
|
||||
public function __construct(Table $table) {
|
||||
$this->table = $table;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a single column-value pair to the row.
|
||||
* @param string $col Column name.
|
||||
* @param mixed $val Value to insert.
|
||||
* @return Insertion Current instance for method chaining.
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function data(string $col, mixed $val): Insertion {
|
||||
if (!isset($this->table->columns[$col]))
|
||||
throw new InvalidArgumentException("Column '$col' does not exist.");
|
||||
|
||||
$columnType = $this->table->columns[$col]['colType'];
|
||||
$this->currentRow[$col] = $columnType->valCast($val);
|
||||
$this->currentRow[$col] = $columnType->dbCast($val);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function done(): Insertion {
|
||||
if (!empty($this->currentRow)) {
|
||||
/**
|
||||
* Adds multiple column-value pairs to the row.
|
||||
* @param array $data Associative array of column-value pairs.
|
||||
* @return Insertion Current instance for method chaining.
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function batchData(array $data): Insertion {
|
||||
foreach ($data as $key => $value)
|
||||
$this->data($key, $value);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finalizes the current row and stacks it for insertion.
|
||||
* @return Insertion Current instance for method chaining.
|
||||
*/
|
||||
public function stack(): Insertion {
|
||||
if (!empty($this->currentRow))
|
||||
$this->stackForInsertion();
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function stackForInsertion(): void {
|
||||
$this->batchRows[] = $this->currentRow;
|
||||
$this->currentRow = [];
|
||||
}
|
||||
$this->isReady = true;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the insertion of all batched rows into the database.
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function insert(): void {
|
||||
global $wpdb;
|
||||
|
||||
// Convert single to batch queries.
|
||||
if (!$this->isReady and !empty($this->currentRow)) {
|
||||
$this->batchRows[] = $this->currentRow;
|
||||
$this->currentRow = [];
|
||||
$this->isReady = true;
|
||||
}
|
||||
if (!empty($this->currentRow))
|
||||
$this->stackForInsertion();
|
||||
|
||||
if (empty($this->batchRows))
|
||||
throw new InvalidArgumentException("No data set for insertion.");
|
||||
|
23
Schema.php
Normal file
23
Schema.php
Normal file
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
namespace DatabaseHelper;
|
||||
|
||||
use DatabaseHelper\enums\CharsetTypes;
|
||||
use DatabaseHelper\enums\CollationTypes;
|
||||
use DatabaseHelper\enums\EngineTypes;
|
||||
|
||||
class Schema
|
||||
{
|
||||
public string $name = '';
|
||||
|
||||
public array $columns = [];
|
||||
public array $primaryKey = [];
|
||||
public array $foreignKeys = [];
|
||||
|
||||
public EngineTypes $engine = EngineTypes::INNODB;
|
||||
public CharsetTypes $charset = CharsetTypes::UTF8;
|
||||
public CollationTypes $collation = CollationTypes::UTF8_GENERAL_CI;
|
||||
|
||||
public function __construct(string $tableName) {
|
||||
$this->name = $tableName;
|
||||
}
|
||||
}
|
51
Table.php
51
Table.php
@ -10,29 +10,18 @@ use InvalidArgumentException;
|
||||
|
||||
class Table
|
||||
{
|
||||
public string $tableName;
|
||||
|
||||
public array $columns = [];
|
||||
|
||||
public array $primaryKey;
|
||||
|
||||
public array $foreignKeys = [];
|
||||
|
||||
// Table settings
|
||||
protected EngineTypes $engine = EngineTypes::INNODB;
|
||||
protected CharsetTypes $charset = CharsetTypes::UTF8;
|
||||
protected CollationTypes $collation = CollationTypes::UTF8_GENERAL_CI;
|
||||
public Schema $table;
|
||||
|
||||
public function __construct(string $tableName) {
|
||||
Database::standardizeTableNames($tableName);
|
||||
$this->tableName = $tableName;
|
||||
$this->table = new Schema($tableName);
|
||||
}
|
||||
|
||||
public function column(string $colName, ColumnTypes $colType, mixed $default = null, bool $nullable = false, bool $unique = false): Table {
|
||||
if(isset($this->columns[$colName]))
|
||||
throw new InvalidArgumentException('Column name already exists.');
|
||||
|
||||
$this->columns[$colName] = [
|
||||
$this->table->columns[$colName] = [
|
||||
'colName' => $colName,
|
||||
'defaultVal' => $default,
|
||||
'colType' => $colType,
|
||||
@ -47,7 +36,7 @@ class Table
|
||||
if(isset($this->primaryKey))
|
||||
throw new InvalidArgumentException('Primary column already exists.');
|
||||
|
||||
$this->primaryKey = [
|
||||
$this->table->primaryKey = [
|
||||
'colName' => $colName,
|
||||
'colType' => $colType,
|
||||
'autoincrement' => $autoInc
|
||||
@ -56,46 +45,46 @@ class Table
|
||||
return $this->column($colName, $colType);
|
||||
}
|
||||
|
||||
public function referenceColumn(Table $foreignTable, CascadeTypes $onDelete = CascadeTypes::CASCADE, CascadeTypes $onUpdate = CascadeTypes::CASCADE): Table {
|
||||
public function reference(Schema $foreignTable, CascadeTypes $onDelete = CascadeTypes::CASCADE, CascadeTypes $onUpdate = CascadeTypes::CASCADE): Table {
|
||||
$colName = $foreignTable->primaryKey['colName'];
|
||||
if(isset($this->columns[$colName]))
|
||||
throw new InvalidArgumentException('Column name already exists.');
|
||||
|
||||
$this->foreignKeys[] = [
|
||||
$this->table->foreignKeys[] = [
|
||||
'colName' => $colName,
|
||||
'tableName' => $foreignTable->tableName,
|
||||
'tableName' => $foreignTable->name,
|
||||
'onDelete' => $onDelete,
|
||||
'onUpdate' => $onUpdate
|
||||
];
|
||||
|
||||
$this->columns[$colName] = $foreignTable->columns[$colName];
|
||||
$this->table->columns[$colName] = $foreignTable->columns[$colName];
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function engine(EngineTypes $engine): Table {
|
||||
$this->engine = $engine;
|
||||
$this->table->engine = $engine;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function charset(CharsetTypes $charset): Table {
|
||||
$this->charset = $charset;
|
||||
$this->table->charset = $charset;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function collation(CollationTypes $collation): Table {
|
||||
$this->collation = $collation;
|
||||
$this->table->collation = $collation;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function toSql(): string {
|
||||
$sql = "CREATE TABLE `{$this->tableName}` (\n";
|
||||
$sql = "CREATE TABLE `{$this->table->name}` (\n";
|
||||
|
||||
// Add primary key constraint if present
|
||||
if (!empty($this->primaryKey))
|
||||
$sql .= " PRIMARY KEY (`{$this->primaryKey['colName']}`),\n";
|
||||
|
||||
foreach ($this->columns as $column) {
|
||||
if ($column['colName'] !== $this->primaryKey['colName']) {
|
||||
foreach ($this->table->columns as $column) {
|
||||
if ($column['colName'] !== $this->table->primaryKey['colName']) {
|
||||
$sql .= " `{$column['colName']}` {$column['colType']->value}";
|
||||
|
||||
// Handle nulls, uniqueness, and defaults
|
||||
@ -113,30 +102,30 @@ class Table
|
||||
}
|
||||
|
||||
// Add secondary constraints if present
|
||||
foreach ($this->foreignKeys as $foreignKey) {
|
||||
foreach ($this->table->foreignKeys as $foreignKey) {
|
||||
$sql .= " FOREIGN KEY (`{$foreignKey['colName']}`) REFERENCES `{$foreignKey['tableName']}` (`{$foreignKey['colName']}`)";
|
||||
$sql .= " ON DELETE {$foreignKey['onDelete']->type()} ON UPDATE {$foreignKey['onUpdate']->type()},\n";
|
||||
$sql .= " ON DELETE {$foreignKey['onDelete']->toString()} ON UPDATE {$foreignKey['onUpdate']->toString()},\n";
|
||||
}
|
||||
|
||||
// Close the SQL string and add constraints
|
||||
$sql = rtrim($sql, ",\n") . "\n";
|
||||
$sql .= ") ENGINE={$this->engine->type()} CHARSET={$this->charset->type()} COLLATE={$this->collation->type()};";
|
||||
$sql .= ") ENGINE={$this->table->engine->toString()} CHARSET={$this->table->charset->toString()} COLLATE={$this->table->collation->toString()};";
|
||||
|
||||
return esc_sql($sql);
|
||||
}
|
||||
|
||||
public function create(): Table {
|
||||
public function create(): Schema {
|
||||
global $wpdb;
|
||||
|
||||
if (empty($this->primaryKey))
|
||||
throw new InvalidArgumentException('A primary key must be defined.');
|
||||
$table_name = $wpdb->prefix . $this->tableName;
|
||||
$table_name = $wpdb->prefix . $this->table->name;
|
||||
|
||||
if ($wpdb->get_var("SHOW TABLES LIKE '$table_name'") !== $table_name) {
|
||||
$sql = $this->toSql();
|
||||
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
|
||||
dbDelta($sql);
|
||||
}
|
||||
return $this;
|
||||
return $this->table;
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ enum CascadeTypes
|
||||
case RESTRICT;
|
||||
case SET_DEFAULT;
|
||||
|
||||
public function type(): string {
|
||||
public function toString(): string {
|
||||
return match ($this) {
|
||||
self::CASCADE => 'CASCADE',
|
||||
self::SET_NULL => 'SET NULL',
|
||||
|
@ -18,7 +18,7 @@ enum CharsetTypes
|
||||
case HEBREW;
|
||||
case BINARY;
|
||||
|
||||
public function type(): string {
|
||||
public function toString(): string {
|
||||
return match ($this) {
|
||||
self::UTF8 => 'utf8',
|
||||
self::UTF8MB4 => 'utf8mb4',
|
||||
|
@ -14,7 +14,7 @@ enum CollationTypes
|
||||
case UTF8_BIN;
|
||||
case LATIN1_BIN;
|
||||
|
||||
public function type(): string {
|
||||
public function toString(): string {
|
||||
return match ($this) {
|
||||
self::UTF8_GENERAL_CI => 'utf8_general_ci',
|
||||
self::UTF8_UNICODE_CI => 'utf8_unicode_ci',
|
||||
|
@ -26,14 +26,14 @@ enum ColumnTypes
|
||||
return match ($this) {
|
||||
self::INT => intval($value),
|
||||
self::FLOAT => floatval($value),
|
||||
self::STRING => esc_sql($value),
|
||||
self::BOOL => filter_var($value, FILTER_VALIDATE_BOOLEAN) ? "TRUE" : "FALSE",
|
||||
self::ARRAY => json_encode($value),
|
||||
self::DATE => $value instanceof DateTime ? $value->format('Y-m-d H:i:s') : json_encode($value),
|
||||
default => is_object($value) ? json_encode($value) : $value,
|
||||
self::DATE => $value instanceof DateTime ? $value->format('Y-m-d H:i:s') : json_encode($value)
|
||||
};
|
||||
}
|
||||
|
||||
public function type(): string {
|
||||
public function toString(): string {
|
||||
return match ($this) {
|
||||
self::INT => 'INTEGER',
|
||||
self::FLOAT => 'FLOAT',
|
||||
|
@ -6,7 +6,7 @@ enum EngineTypes
|
||||
case INNODB;
|
||||
case MYISAM;
|
||||
|
||||
public function type(): string {
|
||||
public function toString(): string {
|
||||
return match ($this) {
|
||||
self::INNODB => 'InnoDB',
|
||||
self::MYISAM => 'MyISAM',
|
||||
|
Loading…
Reference in New Issue
Block a user