- How to add a custom DBAL type to the Laravel database configuration? - StackOverflow Answer
The Laravel framework utilizes the doctrine/dbal
package to update column parameters. The dbal package has its own naming conventions, so for instance, the bigInteger
used in Laravel corresponds to bigint
in dbal. However, there is no equivalent for mediumInteger
used in Laravel within dbal; there is no mediumint
(as dbal convention) or mediuminteger (as Laravel convention)
.
The solution involves implementing mediumint.
If you want to update to mediumInteger
, you can use the DB::statement
call and simply accomplish this using NATIVE SQL.
Why dbal does not support mediumInteger
is unknown. I created this description for those who prefer not to rewrite many already written mediumInteger
calls into NATIVE SQL format.
public const BIGINT = 'bigint';
+ public const MEDIUMINT = 'mediuminteger'; // NEW (mediuminteger by Laravel)
The dbal convention suggests 'mediumint'
, but to avoid altering Laravel, which passes 'mediuminteger'
strings, we'll stick with 'mediuminteger'
here.
For more details, see the getDoctrineColumnType
function in the ChangeColumn.php
file, where the default $type
passed by the match
will be 'mediuminteger'
(in row 163).
/**
* {@inheritDoc}
*/
public function getBigIntTypeDeclarationSQL(array $column)
{
return 'BIGINT' . $this->_getCommonIntegerTypeDeclarationSQL($column);
}
+ /**
+ * {@inheritDoc}
+ */
+ public function getMediumIntTypeDeclarationSQL(array $column) // NEW (we're doing all this because of invoking this function)
+ {
+ return 'MEDIUMINT' . $this->_getCommonIntegerTypeDeclarationSQL($column);
+ }
abstract public function getBigIntTypeDeclarationSQL(array $column);
+ /**
+ * Returns the SQL snippet that declares an 3 byte integer column.
+ *
+ * @param mixed[] $column
+ *
+ * @return string
+ */
+ abstract public function getMediumIntTypeDeclarationSQL(array $column); // NEW
<?php
/**************/
/** NEW FILE **/
/**************/
namespace Doctrine\DBAL\Types;
use Doctrine\DBAL\ParameterType;
use Doctrine\DBAL\Platforms\AbstractPlatform;
/**
* Type that maps a database MEDIUMINT to a PHP string.
*/
class MediumIntType extends Type implements PhpIntegerMappingType
{
/**
* {@inheritDoc}
*/
public function getName()
{
return Types::MEDIUMINT;
}
/**
* {@inheritDoc}
*/
public function getSQLDeclaration(array $column, AbstractPlatform $platform)
{
return $platform->getMediumIntTypeDeclarationSQL($column); // use the getMediumIntTypeDeclarationSQL function of the AbstractMySQLPlatform class
}
/**
* {@inheritDoc}
*/
public function getBindingType()
{
return ParameterType::INTEGER;
}
/**
* {@inheritDoc}
*
* @param T $value
*
* @return (T is null ? null : string)
*
* @template T
*/
public function convertToPHPValue($value, AbstractPlatform $platform)
{
return $value === null ? null : (string) $value;
}
}
/**
* The map of supported doctrine mapping types.
*/
private const BUILTIN_TYPES_MAP = [
// ...
Types::BIGINT => BigIntType::class,
+ Types::MEDIUMINT => MediumIntType::class, // NEW (use the new MediumIntType class)
// ...
];
If you have created the new class to handle MediumInt
(alias mediuminteger
) and integrated it into your dbal library with the listed file modifications, your mediumInteger()
column modification called from Laravel Schema will now function properly.
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up()
{
Schema::table('example_table', function (Blueprint $table) {
$table->unsignedMediumInteger('example_column_1')->change(); // will work
$table->mediumInteger('example_column_2')->change(); // will work
});
}
}