[Doctrine Migrations] 數據庫遷移組件的深入解析三:自定義數據字段類型

自定義type

根據官方文檔,新建TinyIntType類,集成Type,並重寫getNamegetSqlDeclarationconvertToPHPValuegetBindingType等方法。

TinyIntType.php完整代碼:

<?php
namespace db\types;
use Doctrine\DBAL\ParameterType;
use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Types\Type;
/**
 * 擴展DBAL組件類型
 *
 * 遷移組件依賴的DBAL組件默認並不支持tinyint類型
 * 此類是爲mysql支持tinyint類型而擴展的類
 *
 * @author tangbo<[email protected]>
 */
class TinyIntType extends Type
{
    public function getName()
    {
        return 'tinyint';
    }
    public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform)
    {
        $sql = 'TINYINT';
        if (is_numeric($fieldDeclaration['length']) && $fieldDeclaration['length'] > 1) {
            $sql .= '(' . ((int) $fieldDeclaration['length']) . ')';
        } else {
            $sql .= '(3)';
        }
        if (!empty($fieldDeclaration['unsigned'])) {
            $sql .= ' UNSIGNED';
        }
        if (!empty($fieldDeclaration['autoincrement'])) {
            $sql .= ' AUTO_INCREMENT';
        }
        return $sql;
    }
    public function convertToPHPValue($value, AbstractPlatform $platform)
    {
        return (null === $value) ? null : (int) $value;
    }
    public function getBindingType()
    {
        return ParameterType::INTEGER;
    }
}

其中getSqlDeclaration方法是用於生成sql語句,需要根據傳入的參數處理sql拼接。

註冊自定義類型

Type::addType(TinyIntType::TYPENAME, 'db\types\TinyIntType');
$connection->getDatabasePlatform()->registerDoctrineTypeMapping(TinyIntType::TYPENAME, TinyIntType::TYPENAME);

這樣,你在編寫遷移類代碼的時候就可以使用tinyint了,例如:

public function up(Schema $schema): void
{
    $table = $schema->createTable('test1');
    $table->addColumn('id', 'integer')->setUnsigned(true)->setAutoincrement(true);
    $table->addColumn('status', 'tinyint')->setLength(2)->setDefault(1);
    $table->setPrimaryKey(['id']);
}

解決enum類型衝突

遷移組件不支持enum類型,也無法自定義該類型。如果集成遷移組件的時候數據庫裏已經存在表且有enum類型的字段,那麼執行遷移命令時就會報錯。

爲了解決這個問題,我們需要把enum映射爲string類型即可:

$connection->getDatabasePlatform()->registerDoctrineTypeMapping('enum', 'string');

結語

至此,我們已經完成了遷移組件的所有遷移工作,並且已經能很好的在項目中使用它。

目前集成的是版本管理的方式,是遷移組件默認支持的,也是laravel框架集成的遷移方式。還有之前說到的另一種diff方式的遷移,diff方式能夠更精準的控制表結構。

下一章我們來詳細研究如何集成diff方式的數據遷移組件。

我的代碼庫可以查看這篇文章的詳細代碼,歡迎star。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章