Implement table class

This commit is contained in:
Jan-Niclas Loosen 2025-01-28 16:53:37 +01:00
parent ec6bc9aaaf
commit f601751391
11 changed files with 282 additions and 35 deletions

View File

@ -2,34 +2,36 @@
namespace DatabaseHelper; namespace DatabaseHelper;
use DatabaseHelper\interfaces\MigrationBlueprint; use DatabaseHelper\interfaces\MigrationBlueprint;
use DatabaseHelper\interfaces\QueryBuilder;
use DatabaseHelper\interfaces\TableBlueprint; use DatabaseHelper\interfaces\TableBlueprint;
use DatabaseHelper\interfaces\DeletionBuilder;
use DatabaseHelper\interfaces\UpdateBuilder; use DatabaseHelper\interfaces\UpdateBuilder;
use DatabaseHelper\interfaces\InsertionBuilder;
use DatabaseHelper\interfaces\QueryBuilder;
class Database implements interfaces\DatabaseHelper class Database implements interfaces\DatabaseHelper
{ {
public static function makeTable(string $tableName): TableBlueprint public static function makeTable(string $tableName): TableBlueprint {
{ return new Table($tableName);
// TODO: Implement makeTable() method.
} }
public static function makeMigration(TableBlueprint $table): MigrationBlueprint public static function makeMigration(TableBlueprint $table): MigrationBlueprint {
{
// TODO: Implement makeMigration() method. // TODO: Implement makeMigration() method.
} }
public static function makeQuery(TableBlueprint ...$tables): QueryBuilder public static function makeQuery(TableBlueprint ...$tables): QueryBuilder {
{
// TODO: Implement makeQuery() method. // TODO: Implement makeQuery() method.
} }
public static function makeInsertion(TableBlueprint ...$tables): QueryBuilder
{ public static function makeDeletion(TableBlueprint ...$tables): DeletionBuilder {
// TODO: Implement makeDeletion() method.
}
public static function makeInsertion(TableBlueprint ...$tables): InsertionBuilder {
// TODO: Implement makeInsertion() method. // TODO: Implement makeInsertion() method.
} }
public static function makeUpdate(TableBlueprint ...$tables): UpdateBuilder public static function makeUpdate(TableBlueprint ...$tables): UpdateBuilder {
{
// TODO: Implement makeUpdate() method. // TODO: Implement makeUpdate() method.
} }

138
Table.php Normal file
View File

@ -0,0 +1,138 @@
<?php
namespace DatabaseHelper;
use DatabaseHelper\enums\CascadeTypes;
use DatabaseHelper\enums\CharsetTypes;
use DatabaseHelper\enums\CollationTypes;
use DatabaseHelper\enums\ColumnTypes;
use DatabaseHelper\enums\EngineTypes;
use DatabaseHelper\interfaces\TableBlueprint;
use InvalidArgumentException;
class Table implements TableBlueprint
{
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 function __construct(string $tableName) {
$this->tableName = $tableName;
}
public function column(string $name, ColumnTypes $type, mixed $default = null, bool $nullable = false, bool $unique = false): TableBlueprint {
if(isset($this->columns[$name]))
throw new InvalidArgumentException('Column name already exists.');
$this->columns[$name] = [
'colName' => $name,
'defaultVal' => $default,
'colType' => $type,
'nullable' => $nullable,
'unique' => $unique
];
return $this;
}
public function primaryColumn(string $name, ColumnTypes $type, bool $autoincrement = false): TableBlueprint {
if(isset($this->primaryKey))
throw new InvalidArgumentException('Primary column already exists.');
$this->primaryKey = [
'colName' => $name,
'colType' => $type,
'autoincrement' => $autoincrement
];
return $this->column($name, $type);
}
public function foreignColumn(TableBlueprint $foreignTable, CascadeTypes $onDelete, CascadeTypes $onUpdate): TableBlueprint {
$colName = $foreignTable->primaryKey['colName'];
if(isset($this->columns[$colName]))
throw new InvalidArgumentException('Column name already exists.');
$this->foreignKeys[] = [
'colName' => $colName,
'tableName' => $foreignTable->tableName,
'onDelete' => $onDelete,
'onUpdate' => $onUpdate
];
$this->columns[$colName] = $foreignTable->columns[$colName];
return $this;
}
public function engine(EngineTypes $engine): TableBlueprint {
$this->engine = $engine;
return $this;
}
public function charset(CharsetTypes $charset): TableBlueprint {
$this->charset = $charset;
return $this;
}
public function collation(CollationTypes $collation): TableBlueprint {
$this->collation = $collation;
return $this;
}
public function toSql(): string {
$sql = "CREATE TABLE `{$this->tableName}` (\n";
if (!empty($this->primaryKey)) {
$sql .= " `{$this->primaryKey['colName']}` {$this->primaryKey['colType']->value}";
if ($this->primaryKey['autoincrement'])
$sql .= " AUTO_INCREMENT";
$sql .= " NOT NULL,\n";
}
foreach ($this->columns as $column) {
if ($column['colName'] !== $this->primaryKey['colName']) {
$sql .= " `{$column['colName']}` {$column['colType']->value}";
if (!$column['nullable'])
$sql .= " NOT NULL";
if ($column['unique'])
$sql .= " UNIQUE";
if ($column['defaultVal'] !== null) {
$default = is_string($column['defaultVal']) ? "'{$column['defaultVal']}'" : $column['defaultVal'];
$sql .= " DEFAULT $default";
}
$sql .= ",\n";
}
}
if (!empty($this->primaryKey))
$sql .= " PRIMARY KEY (`{$this->primaryKey['colName']}`),\n";
foreach ($this->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 = rtrim($sql, ",\n") . "\n";
$sql .= ") ENGINE={$this->engine->type()} CHARSET={$this->charset->type()} COLLATE={$this->collation->type()};";
return $sql;
}
public function create(): void {
$sql = $this->toSql();
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
dbDelta($sql);
}
}

21
build.php Normal file
View File

@ -0,0 +1,21 @@
<?php
// Require all enums
require './enums/CascadeTypes.php';
require './enums/CharsetTypes.php';
require './enums/CollationTypes.php';
require './enums/ColumnTypes.php';
require './enums/EngineTypes.php';
// Require all interfaces
require './interfaces/DatabaseHelper.php';
require './interfaces/TableBlueprint.php';
require './interfaces/MigrationBlueprint.php';
require './interfaces/QueryBuilder.php';
require './interfaces/InsertionBuilder.php';
require './interfaces/UpdateBuilder.php';
require './interfaces/DeletionBuilder.php';
// Require all classes

View File

@ -9,6 +9,14 @@ enum CharsetTypes
case ASCII; case ASCII;
case UTF16; case UTF16;
case UTF32; case UTF32;
case LATIN2;
case LATIN5;
case CP1251;
case CP850;
case TIS620;
case GREEK;
case HEBREW;
case BINARY;
public function type(): string { public function type(): string {
return match ($this) { return match ($this) {
@ -18,6 +26,15 @@ enum CharsetTypes
self::ASCII => 'ascii', self::ASCII => 'ascii',
self::UTF16 => 'utf16', self::UTF16 => 'utf16',
self::UTF32 => 'utf32', self::UTF32 => 'utf32',
self::LATIN2 => 'latin2',
self::LATIN5 => 'latin5',
self::CP1251 => 'cp1251',
self::CP850 => 'cp850',
self::TIS620 => 'tis620',
self::GREEK => 'greek',
self::HEBREW => 'hebrew',
self::BINARY => 'binary',
}; };
} }
} }

View File

@ -1,24 +1,32 @@
<?php <?php
namespace DatabaseHelper\enums; namespace DatabaseHelper\enums;
enum CollationTypes enum CollationTypes
{ {
case UTF8_GENERAL_CI; case UTF8_GENERAL_CI;
case UTF8_UNICODE_CI;
case UTF8_SPANISH_CI;
case UTF8MB4_UNICODE_CI; case UTF8MB4_UNICODE_CI;
case UTF8MB4_GENERAL_CI;
case UTF8MB4_UNICODE_520_CI;
case LATIN1_SWEDISH_CI; case LATIN1_SWEDISH_CI;
case UTF8MB4_BIN; case UTF8MB4_BIN;
case UTF8_BIN; case UTF8_BIN;
case UTF8_GENERAL_BIN; case LATIN1_BIN;
public function type(): string { public function type(): 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_SPANISH_CI => 'utf8_spanish_ci',
self::UTF8MB4_UNICODE_CI => 'utf8mb4_unicode_ci', self::UTF8MB4_UNICODE_CI => 'utf8mb4_unicode_ci',
self::UTF8MB4_GENERAL_CI => 'utf8mb4_general_ci',
self::UTF8MB4_UNICODE_520_CI => 'utf8mb4_unicode_520_ci',
self::LATIN1_SWEDISH_CI => 'latin1_swedish_ci', self::LATIN1_SWEDISH_CI => 'latin1_swedish_ci',
self::UTF8MB4_BIN => 'utf8mb4_bin', self::UTF8MB4_BIN => 'utf8mb4_bin',
self::UTF8_BIN => 'utf8_bin', self::UTF8_BIN => 'utf8_bin',
self::UTF8_GENERAL_BIN => 'utf8_general_bin', self::LATIN1_BIN => 'latin1_bin',
}; };
} }
} }

View File

@ -1,6 +1,5 @@
<?php <?php
namespace DatabaseHelper\enums; namespace DatabaseHelper\enums;
enum ColumnTypes enum ColumnTypes
{ {
case INT; case INT;
@ -21,6 +20,20 @@ enum ColumnTypes
}; };
} }
public function isCastable(mixed $value): bool {
try {
return match ($this) {
self::INT, self::FLOAT => is_numeric($value),
self::STRING => is_scalar($value) || (is_object($value) && method_exists($value, '__toString')),
self::BOOL => is_bool($value) || in_array($value, [0, 1, '0', '1'], true),
self::ARRAY => is_array($value) || is_string($value) && json_decode($value, true) !== null,
self::DATE => $value instanceof \DateTime || (is_string($value) && strtotime($value) !== false),
};
} catch (\Throwable $e) {
return false;
}
}
public function type(): string { public function type(): string {
return match ($this) { return match ($this) {
self::INT => 'INTEGER', self::INT => 'INTEGER',

View File

@ -34,9 +34,18 @@ interface DatabaseHelper
* When multiple tables are provided, they will be joined automatically for the insertion. * When multiple tables are provided, they will be joined automatically for the insertion.
* *
* @param TableBlueprint ...$tables One or more Table instances. * @param TableBlueprint ...$tables One or more Table instances.
* @return QueryBuilder Generated Query instance. * @return InsertionBuilder Generated Query instance.
*/ */
public static function makeInsertion(TableBlueprint ...$tables): QueryBuilder; public static function makeInsertion(TableBlueprint ...$tables): InsertionBuilder;
/**
* Initializes a Deletion instance to delete records from the specified tables.
* When multiple tables are provided, they will be joined automatically.
*
* @param TableBlueprint ...$tables One or more Table instances.
* @return DeletionBuilder Generated Deletion instance.
*/
public static function makeDeletion(TableBlueprint ...$tables): DeletionBuilder;
/** /**
* Initializes an Update instance to perform updates on the specified tables. * Initializes an Update instance to perform updates on the specified tables.

View File

@ -0,0 +1,8 @@
<?php
namespace DatabaseHelper\interfaces;
interface DeletionBuilder
{
}

View File

@ -1,17 +1,59 @@
<?php <?php
namespace DatabaseHelper\interfaces; namespace DatabaseHelper\interfaces;
use DatabaseHelper\enums\CascadeTypes;
use DatabaseHelper\enums\ColumnTypes;
use DatabaseHelper\enums\ColumnTypes;
use DatabaseHelper\enums\CascadeTypes;
use DatabaseHelper\enums\EngineTypes;
use DatabaseHelper\enums\CharsetTypes;
use DatabaseHelper\enums\CollationTypes;
/**
* Defines a blueprint for building database tables with a fluent interface, which supports method chaining.
*/
interface TableBlueprint interface TableBlueprint
{ {
public function __construct(string $tableName);
/**
* Adds a column.
* @param string $name Column name.
* @param ColumnTypes $type Column type.
* @param mixed|null $default Default value (optional).
* @param bool $nullable Nullable column (default: false).
* @param bool $unique Unique constraint (default: false).
* @return TableBlueprint Current instance for method chaining.
*/
public function column(string $name, ColumnTypes $type, mixed $default = null, bool $nullable = false, bool $unique = false): TableBlueprint; public function column(string $name, ColumnTypes $type, mixed $default = null, bool $nullable = false, bool $unique = false): TableBlueprint;
public function primaryKey(string $colName, bool $autoIncrement = false): TableBlueprint; public function primaryColumn(string $name, ColumnTypes $type, bool $autoincrement = false): TableBlueprint;
public function foreignKey(string $colName, TableBlueprint $foreignTable, CascadeTypes $cascade): TableBlueprint; public function foreignColumn(TableBlueprint $foreignTable, CascadeTypes $onDelete, CascadeTypes $onUpdate): TableBlueprint;
/**
* Sets the table engine.
* @param EngineTypes $engine Storage engine.
* @return TableBlueprint Current instance for method chaining.
*/
public function engine(EngineTypes $engine): TableBlueprint;
/**
* Sets the character set.
* @param CharsetTypes $charset Character set.
* @return TableBlueprint Current instance for method chaining.
*/
public function charset(CharsetTypes $charset): TableBlueprint;
/**
* Sets the collation.
* @param CollationTypes $collation Collation to use.
* @return TableBlueprint Current instance for method chaining.
*/
public function collation(CollationTypes $collation): TableBlueprint;
/**
* Executes the blueprint.
* @return void
*/
public function create(): void;
}
public function exec() : void;
}

View File

@ -1,10 +0,0 @@
<?php
// Require all interfaces
require './src/interfaces/Database.php';
require './src/interfaces/Insertion.php';
require './src/interfaces/Migration.php';
require './src/interfaces/Query.php';
require './src/interfaces/Table.php';
require './src/interfaces/Update.php';
// Require all classes

View File

@ -1 +0,0 @@
<?php