Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor column PHP type #862

Merged
merged 10 commits into from
Aug 9, 2024
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 @@
{
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 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)

Check warning on line 406 in src/Schema/AbstractSchema.php

View check run for this annotation

Codecov / codecov/patch

src/Schema/AbstractSchema.php#L406

Added line #L406 was not covered by tests
: 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
Loading