Skip to content

Commit

Permalink
Refactor column PHP type (#862)
Browse files Browse the repository at this point in the history
Co-authored-by: Sergei Predvoditelev <[email protected]>
  • Loading branch information
Tigrov and vjik authored Aug 9, 2024
1 parent 23e8d43 commit 6a8ceea
Show file tree
Hide file tree
Showing 21 changed files with 237 additions and 211 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@
- Chg #847: Remove `SchemaInterface::getRawTableName()` and `AbstractSchema::getRawTableName()` methods (@Tigrov)
- Enh #852: Add method chaining for column classes (@Tigrov)
- Enh #855: Add array and JSON overlaps conditions (@Tigrov)
- Enh #860 Add `bit` abstract type (@Tigrov)
- Enh #860: Add `bit` abstract type (@Tigrov)
- Enh #862: Refactor PHP type of `ColumnSchemaInterface` instances (@Tigrov)

## 1.3.0 March 21, 2024

Expand Down
17 changes: 16 additions & 1 deletion UPGRADE.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,15 +65,22 @@ The interface and the abstract implementation `AbstractColumnSchema` were moved
and the following changes were made:

- `getName()` method can return `string` or `null`;
- `getPhpType()` method must return `string` PHP type of the column which used for generating related model properties;
- `name(string|null $name)` method is added;
- constructor of `AbstractColumnSchema` class is changed to `__construct(string $type, string|null $phpType = null)`;
- added method chaining.

### New classes with constants

- `Yiisoft\Db\Constant\PhpType` with PHP types constants;
- `Yiisoft\Db\Constant\GettypeResult` with `gettype()` function results constants.

### New classes for table columns

Each table column has its own class in the `Yiisoft\Db\Schema\Column` namespace according to the data type:

- `BooleanColumnSchema` for columns with boolean type;
- `BitColumnSchema` for columns with bit type;
- `IntegerColumnSchema` for columns with integer type (tinyint, smallint, integer, bigint);
- `BigIntColumnSchema` for columns with integer type with range outside `PHP_INT_MIN` and `PHP_INT_MAX`;
- `DoubleColumnSchema` for columns with fractional number type (float, double, decimal, money);
Expand All @@ -96,6 +103,7 @@ Each table column has its own class in the `Yiisoft\Db\Schema\Column` namespace
- `AbstractSchema::normalizeRowKeyCase()`
- `Quoter::unquoteParts()`
- `AbstractPdoCommand::logQuery()`
- `ColumnSchemaInterface::phpType()`

### Remove deprecated parameters

Expand All @@ -105,9 +113,16 @@ Each table column has its own class in the `Yiisoft\Db\Schema\Column` namespace
- `$rawSql` from `AbstractCommand::internalExecute()` method
- `$rawSql` from `AbstractPdoCommand::internalExecute()` method

### Remove deprecated constants
### Remove constants

- `SchemaInterface::TYPE_JSONB`
- `SchemaInterface::PHP_TYPE_INTEGER`
- `SchemaInterface::PHP_TYPE_STRING`
- `SchemaInterface::PHP_TYPE_BOOLEAN`
- `SchemaInterface::PHP_TYPE_DOUBLE`
- `SchemaInterface::PHP_TYPE_RESOURCE`
- `SchemaInterface::PHP_TYPE_ARRAY`
- `SchemaInterface::PHP_TYPE_NULL`

### Other changes

Expand Down
6 changes: 3 additions & 3 deletions src/Command/AbstractCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@
use Throwable;
use Yiisoft\Db\Exception\Exception;
use Yiisoft\Db\Expression\Expression;
use Yiisoft\Db\Constant\GettypeResult;
use Yiisoft\Db\Query\Data\DataReaderInterface;
use Yiisoft\Db\Query\QueryInterface;
use Yiisoft\Db\QueryBuilder\DMLQueryBuilderInterface;
use Yiisoft\Db\QueryBuilder\QueryBuilderInterface;
use Yiisoft\Db\Schema\Builder\ColumnInterface;
use Yiisoft\Db\Schema\SchemaInterface;

use function explode;
use function get_resource_type;
Expand Down Expand Up @@ -363,8 +363,8 @@ public function getRawSql(): string
$params[$name] = match ($param->getType()) {
DataType::INTEGER => (string) (int) $value,
DataType::STRING, DataType::LOB => match (gettype($value)) {
SchemaInterface::PHP_TYPE_RESOURCE => $name,
SchemaInterface::PHP_TYPE_DOUBLE => (string) $value,
GettypeResult::RESOURCE => $name,
GettypeResult::DOUBLE => (string) $value,
default => $value instanceof Expression
? (string) $value
: $quoter->quoteValue((string) $value),
Expand Down
50 changes: 50 additions & 0 deletions src/Constant/GettypeResult.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Db\Constant;

/**
* The following constants are returned by {@see gettype()} function.
*
* @link https://www.php.net/manual/en/function.gettype.php
*/
final class GettypeResult
{
/**
* Define the php type as `array`.
*/
public const ARRAY = 'array';
/**
* Define the php type as `boolean`.
*/
public const BOOLEAN = 'boolean';
/**
* Define the php type as `double`.
*/
public const DOUBLE = 'double';
/**
* Define the php type as `integer`.
*/
public const INTEGER = 'integer';
/**
* Define the php type as `NULL`.
*/
public const NULL = 'NULL';
/**
* Define the php type as `object`.
*/
public const OBJECT = 'object';
/**
* Define the php type as `resource`.
*/
public const RESOURCE = 'resource';
/**
* Define the php type as `string`.
*/
public const STRING = 'string';
/**
* Define the php type as `unknown type`.
*/
public const UNKNOWN = 'unknown type';
}
50 changes: 50 additions & 0 deletions src/Constant/PhpType.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Db\Constant;

use Yiisoft\Db\Schema\Column\ColumnSchemaInterface;

/**
* Defines the available PHP types.
* Used to generate properties of a related model class.
*
* @see ColumnSchemaInterface::getPhpType()
* @see https://www.php.net/manual/en/language.types.type-system.php
*/
final class PhpType
{
/**
* Define the php type as `array`.
*/
public const ARRAY = 'array';
/**
* Define the php type as `bool`.
*/
public const BOOL = 'bool';
/**
* Define the php type as `float`.
*/
public const FLOAT = 'float';
/**
* Define the php type as `int`.
*/
public const INT = 'int';
/**
* Define the php type as `mixed`.
*/
public const MIXED = 'mixed';
/**
* Define the php type as `null`.
*/
public const NULL = 'null';
/**
* Define the php type as `object`.
*/
public const OBJECT = 'object';
/**
* Define the php type as `string`.
*/
public const STRING = 'string';
}
71 changes: 21 additions & 50 deletions src/Schema/AbstractSchema.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use Yiisoft\Db\Constraint\Constraint;
use Yiisoft\Db\Constraint\IndexConstraint;
use Yiisoft\Db\Exception\NotSupportedException;
use Yiisoft\Db\Constant\GettypeResult;
use Yiisoft\Db\Schema\Column\BinaryColumnSchema;
use Yiisoft\Db\Schema\Column\BitColumnSchema;
use Yiisoft\Db\Schema\Column\BooleanColumnSchema;
Expand Down Expand Up @@ -139,10 +140,10 @@ public function getDataType(mixed $data): int
{
return match (gettype($data)) {
// php type => SQL data type
SchemaInterface::PHP_TYPE_BOOLEAN => DataType::BOOLEAN,
SchemaInterface::PHP_TYPE_INTEGER => DataType::INTEGER,
SchemaInterface::PHP_TYPE_RESOURCE => DataType::LOB,
SchemaInterface::PHP_TYPE_NULL => DataType::NULL,
GettypeResult::BOOLEAN => DataType::BOOLEAN,
GettypeResult::INTEGER => DataType::INTEGER,
GettypeResult::RESOURCE => DataType::LOB,
GettypeResult::NULL => DataType::NULL,
default => DataType::STRING,
};
}
Expand Down Expand Up @@ -387,62 +388,32 @@ protected function findTableNames(string $schema): array
protected function createColumnSchema(string $type, mixed ...$info): ColumnSchemaInterface
{
$isUnsigned = !empty($info['unsigned']);
$phpType = $this->getColumnPhpType($type, $isUnsigned);

$column = $this->createColumnSchemaFromPhpType($phpType, $type);
$column = $this->createColumnSchemaFromType($type, $isUnsigned);
$column->unsigned($isUnsigned);

return $column;
}

/**
* Get the PHP type from an abstract database type.
*
* @param string $type The abstract database type.
*
* @return string The PHP type name.
*/
protected function getColumnPhpType(string $type, bool $isUnsigned = false): string
protected function createColumnSchemaFromType(string $type, bool $isUnsigned = false): ColumnSchemaInterface
{
return match ($type) {
// abstract type => php type
SchemaInterface::TYPE_TINYINT => SchemaInterface::PHP_TYPE_INTEGER,
SchemaInterface::TYPE_SMALLINT => SchemaInterface::PHP_TYPE_INTEGER,
SchemaInterface::TYPE_BOOLEAN => new BooleanColumnSchema($type),
SchemaInterface::TYPE_BIT => new BitColumnSchema($type),
SchemaInterface::TYPE_TINYINT => new IntegerColumnSchema($type),
SchemaInterface::TYPE_SMALLINT => new IntegerColumnSchema($type),
SchemaInterface::TYPE_INTEGER => PHP_INT_SIZE !== 8 && $isUnsigned
? SchemaInterface::PHP_TYPE_STRING
: SchemaInterface::PHP_TYPE_INTEGER,
? new BigIntColumnSchema($type)
: new IntegerColumnSchema($type),
SchemaInterface::TYPE_BIGINT => PHP_INT_SIZE !== 8 || $isUnsigned
? SchemaInterface::PHP_TYPE_STRING
: SchemaInterface::PHP_TYPE_INTEGER,
SchemaInterface::TYPE_BIT => SchemaInterface::PHP_TYPE_INTEGER,
SchemaInterface::TYPE_BOOLEAN => SchemaInterface::PHP_TYPE_BOOLEAN,
SchemaInterface::TYPE_DECIMAL => SchemaInterface::PHP_TYPE_DOUBLE,
SchemaInterface::TYPE_FLOAT => SchemaInterface::PHP_TYPE_DOUBLE,
SchemaInterface::TYPE_DOUBLE => SchemaInterface::PHP_TYPE_DOUBLE,
SchemaInterface::TYPE_BINARY => SchemaInterface::PHP_TYPE_RESOURCE,
SchemaInterface::TYPE_JSON => SchemaInterface::PHP_TYPE_ARRAY,
default => SchemaInterface::PHP_TYPE_STRING,
};
}

protected function createColumnSchemaFromPhpType(string $phpType, string $type): ColumnSchemaInterface
{
if ($type === SchemaInterface::TYPE_BIT) {
return new BitColumnSchema($type, $phpType);
}

return match ($phpType) {
SchemaInterface::PHP_TYPE_STRING => match ($type) {
SchemaInterface::TYPE_INTEGER => new BigIntColumnSchema($type, $phpType),
SchemaInterface::TYPE_BIGINT => new BigIntColumnSchema($type, $phpType),
default => new StringColumnSchema($type, $phpType),
},
SchemaInterface::PHP_TYPE_INTEGER => new IntegerColumnSchema($type, $phpType),
SchemaInterface::PHP_TYPE_DOUBLE => new DoubleColumnSchema($type, $phpType),
SchemaInterface::PHP_TYPE_BOOLEAN => new BooleanColumnSchema($type, $phpType),
SchemaInterface::PHP_TYPE_RESOURCE => new BinaryColumnSchema($type, $phpType),
SchemaInterface::PHP_TYPE_ARRAY => new JsonColumnSchema($type, $phpType),
default => new StringColumnSchema($type, $phpType),
? new BigIntColumnSchema($type)
: new IntegerColumnSchema($type),
SchemaInterface::TYPE_DECIMAL => new DoubleColumnSchema($type),
SchemaInterface::TYPE_FLOAT => new DoubleColumnSchema($type),
SchemaInterface::TYPE_DOUBLE => new DoubleColumnSchema($type),
SchemaInterface::TYPE_BINARY => new BinaryColumnSchema($type),
SchemaInterface::TYPE_JSON => new JsonColumnSchema($type),
default => new StringColumnSchema($type),
};
}

Expand Down
13 changes: 4 additions & 9 deletions src/Schema/Column/AbstractColumnSchema.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

namespace Yiisoft\Db\Schema\Column;

use Yiisoft\Db\Constant\PhpType;

/**
* Represents the metadata of a column in a database table.
*
Expand Down Expand Up @@ -49,7 +51,6 @@ abstract class AbstractColumnSchema implements ColumnSchemaInterface

public function __construct(
private string $type,
private string|null $phpType = null,
) {
}

Expand Down Expand Up @@ -136,9 +137,9 @@ public function getPrecision(): int|null
return $this->precision;
}

public function getPhpType(): string|null
public function getPhpType(): string
{
return $this->phpType;
return PhpType::MIXED;
}

public function getScale(): int|null
Expand Down Expand Up @@ -187,12 +188,6 @@ public function name(string|null $name): static
return $this;
}

public function phpType(string|null $phpType): static
{
$this->phpType = $phpType;
return $this;
}

public function precision(int|null $precision): static
{
$this->precision = $precision;
Expand Down
21 changes: 15 additions & 6 deletions src/Schema/Column/BigIntColumnSchema.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,31 +5,35 @@
namespace Yiisoft\Db\Schema\Column;

use Yiisoft\Db\Expression\ExpressionInterface;
use Yiisoft\Db\Constant\GettypeResult;
use Yiisoft\Db\Constant\PhpType;
use Yiisoft\Db\Schema\SchemaInterface;

use function gettype;

use const PHP_INT_MAX;
use const PHP_INT_MIN;

class BigIntColumnSchema extends AbstractColumnSchema
{
public function __construct(
string $type = SchemaInterface::TYPE_BIGINT,
string|null $phpType = SchemaInterface::PHP_TYPE_STRING,
) {
parent::__construct($type, $phpType);
parent::__construct($type);
}

public function dbTypecast(mixed $value): int|string|ExpressionInterface|null
{
/** @var ExpressionInterface|int|string|null */
return match (gettype($value)) {
'string' => $value === '' ? null : (
GettypeResult::STRING => $value === '' ? null : (
$value <= PHP_INT_MAX && $value >= PHP_INT_MIN
? (int) $value
: $value
),
'NULL' => null,
'integer' => $value,
'boolean' => $value ? 1 : 0,
GettypeResult::NULL => null,
GettypeResult::INTEGER => $value,
GettypeResult::BOOLEAN => $value ? 1 : 0,
default => $value instanceof ExpressionInterface ? $value : (
($val = (string) $value) <= PHP_INT_MAX && $val >= PHP_INT_MIN
? (int) $val
Expand All @@ -38,6 +42,11 @@ public function dbTypecast(mixed $value): int|string|ExpressionInterface|null
};
}

public function getPhpType(): string
{
return PhpType::STRING;
}

public function phpTypecast(mixed $value): string|null
{
if ($value === null) {
Expand Down
Loading

0 comments on commit 6a8ceea

Please sign in to comment.