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