Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ The format is based on Keep a Changelog.
### Changed
- **BREAKING:** Converted the constant classes `ReservedKeys`, `AuthKeys`, `Pagination` and the database `Type`, `Key` and `Relation` to PHP enums, and moved the table actions of `Table` into the new `TableAction` enum (#612). An enum case is not its value, so code that needs the text or number reads `->value`, and text that comes from outside is turned into a case with `::from()` or `::tryFrom()`:
- `ReservedKeys`, `AuthKeys`, `Pagination`, `Type`, `Key` and `Relation` are string-backed enums with the same case names and values, so `Relation::BELONGS_TO`, `Type::INT` and `Key::INDEX` are written as before. An application that uses a case as an array key, compares it with text, or passes it to a `string` parameter must add `->value`, for example `$this->keyFields[AuthKeys::USERNAME->value]`. Code that reads the constants with `ReflectionClass::getConstants()` uses `AuthKeys::cases()`.
- These methods take the enum and no longer accept text: `Table::addColumn()`, `Table::modifyColumn()` and `Column::__construct()` take `Type`, `Table::addIndex()` takes `Key` and `Table::setAction()` takes `TableAction`. A text value such as `addColumn('id', 'int')` throws a `TypeError`; write `Type::INT`. A subclass of `Table` or `Column` that overrides these methods must declare the enum types.
- `Table::addIndex()` takes `Key` and `Table::setAction()` takes `TableAction`, and no longer accept text: `addIndex('name', 'unique')` throws a `TypeError`; write `Key::UNIQUE`. A subclass of `Table` that overrides these methods must declare the enum types.
- `Table::addColumn()`, `Table::modifyColumn()` and `Column::__construct()` accept a `Type` case or the type as text. A text type is used as before, in upper case, so any SQL type name still works (`'integer'`, `'bigint'`, `'mediumtext'`), including those that `Type` has no case for. A subclass that overrides them must declare `Type|string`.
- `Table::CREATE`, `Table::ALTER`, `Table::DROP` and `Table::RENAME` are removed: use `TableAction::CREATE`, `TableAction::ALTER`, `TableAction::DROP` and `TableAction::RENAME`.
- The `type` of a model relation must be a `Relation` case. The text `'hasOne'` is rejected with the message "Relation type `hasOne` is not supported"; write `Relation::HAS_ONE`. `ModelException::unsupportedRelationType()` accepts a `Relation` or text.
- `Pagination` keeps the four names (`PAGINATION_CLASS`, `PAGINATION_CLASS_ACTIVE`, `PER_PAGE`, `PAGE`) as a string-backed enum, read with `->value`. The numbers `FIRST_PAGE_NUMBER`, `MINIMUM_PAGE_ITEMS_COUNT` and `EDGE_PADDING` moved to `PaginationLimit`, an enum that holds them as constants, read without `->value`.
Expand Down
6 changes: 3 additions & 3 deletions src/Database/Schemas/Column.php
Original file line number Diff line number Diff line change
Expand Up @@ -152,12 +152,12 @@ class Column
* Column constructor.
* @param mixed $constraint
*/
public function __construct(string $name, ?Type $type = null, $constraint = null)
public function __construct(string $name, Type|string|null $type = null, $constraint = null)
{
$this->name = $name;

if ($type !== null) {
$this->type = strtoupper($type->value);
if ($type) {
$this->type = strtoupper($type instanceof Type ? $type->value : $type);
$this->constraint = $constraint;
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/Database/Schemas/Table.php
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ public function setAction(TableAction $action, ?array $data = null): Table
* Adds column to the table
* @param mixed $constraint
*/
public function addColumn(string $name, Type $type, $constraint = null): Table
public function addColumn(string $name, Type|string $type, $constraint = null): Table
{
$this->columns[] = [
'column' => new Column($name, $type, $constraint),
Expand All @@ -121,7 +121,7 @@ public function addColumn(string $name, Type $type, $constraint = null): Table
* Modifies the column
* @param mixed $constraint
*/
public function modifyColumn(string $name, Type $type, $constraint = null): Table
public function modifyColumn(string $name, Type|string $type, $constraint = null): Table
{
if ($this->action === TableAction::ALTER) {
$this->columns[] = [
Expand Down
14 changes: 10 additions & 4 deletions tests/Unit/Database/Schema/ColumnTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
use Quantum\Database\Schemas\Column;
use Quantum\Database\Enums\Type;
use PHPUnit\Framework\TestCase;
use TypeError;

class ColumnTest extends TestCase
{
Expand All @@ -14,11 +13,18 @@ public function testColumnConstructor(): void
$this->assertInstanceOf(Column::class, new Column('test'));
}

public function testColumnRejectsTheTypeAsText(): void
public function testColumnAcceptsAnySqlTypeAsText(): void
{
$this->expectException(TypeError::class);
$this->assertSame('BIGINT', (new Column('test', 'bigint', 20))->get(Column::TYPE));
$this->assertSame('INTEGER', (new Column('test', 'integer'))->get(Column::TYPE));
}

new Column('test', 'int', 11);
public function testColumnTypeIsTheSameFromTheEnumAndFromText(): void
{
$this->assertSame(
(new Column('test', Type::VARCHAR, 255))->get(Column::TYPE),
(new Column('test', 'varchar', 255))->get(Column::TYPE)
);
}

public function testColumnRename(): void
Expand Down
16 changes: 10 additions & 6 deletions tests/Unit/Database/Schema/TableTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,24 +62,28 @@ public function testAddColumn(): void
$this->assertEquals($expectedSql, $table->getSql());
}

public function testAddColumnRejectsTheTypeAsText(): void
public function testAddColumnAcceptsAnySqlTypeAsText(): void
{
$table = new Table('test');
$table->setAction(TableAction::CREATE);
$table->addColumn('id', 'bigint', 20)->primary()->autoIncrement();
$table->addColumn('code', 'integer');
$table->addColumn('body', 'mediumtext');

$this->expectException(TypeError::class);
$expectedSql = 'CREATE TABLE `test` (`id` BIGINT(20) NOT NULL AUTO_INCREMENT, `code` INTEGER NOT NULL, `body` MEDIUMTEXT NOT NULL, PRIMARY KEY (`id`));';

$table->addColumn('id', 'int', 11);
$this->assertEquals($expectedSql, $table->getSql());
}

public function testModifyColumnRejectsTheTypeAsText(): void
public function testModifyColumnAcceptsTheTypeAsText(): void
{
$table = new Table('test');
$table->setAction(TableAction::ALTER);
$table->modifyColumn('name', 'varchar', 50);

$this->expectException(TypeError::class);
$expectedSql = 'ALTER TABLE `test` MODIFY COLUMN `name` VARCHAR(50) NOT NULL;';

$table->modifyColumn('name', 'varchar', 50);
$this->assertEquals($expectedSql, $table->getSql());
}

public function testAddColumnWithAttributes(): void
Expand Down
Loading