#php #mysql #database #laravel #schema
#php #mysql #База данных #laravel #схема
Вопрос:
В схеме Laravel есть команда для перечисления, эквивалентная таблице. Какой набор эквивалентен таблице?
Комментарии:
1. Начиная с версии 5.8, поддерживаются также столбцы set $table-> set(‘flavors’, [‘strawberry’, ‘vanilla’]);
Ответ №1:
Шаг 1. Расширьте классы по умолчанию (добавьте этот код в файл миграции после use
разделов):
class ExtendedBlueprint extends Blueprint {
/**
* Create a new set column on the table.
*
* @param string $column
* @param array $allowed
* @return IlluminateSupportFluent
*/
public function set($column, array $allowed)
{
return $this->addColumn('set', $column, compact('allowed'));
}
}
class ExtendedMySqlGrammar extends IlluminateDatabaseSchemaGrammarsMySqlGrammar {
/**
* Create the column definition for an set type.
*
* @param IlluminateSupportFluent $column
* @return string
*/
protected function typeSet(IlluminateSupportFluent $column)
{
return "set('".implode("', '", $column->allowed)."')";
}
}
Шаг 2.Затем нам нужно изменить классы грамматики и схемы элементов по умолчанию на наши пользовательские:
// set new grammar class
DB::connection()->setSchemaGrammar(new ExtendedMySqlGrammar());
// get custom schema object
$schema = DB::connection()->getSchemaBuilder();
// bind new blueprint class
$schema->blueprintResolver(function($table, $callback) {
return new ExtendedBlueprint($table, $callback);
});
// then create tables
$schema->create('table name', function(ExtendedBlueprint $table)
{
$table->increments('id');
$table->text('sentence');
$table->string('author')->nullable();
$table->string('source')->nullable();
$table->set('difficulty', range(1, 10)); // use our new mysql type
$table->boolean('enabled')->default(true);
});
Этот метод также будет работать после composer update
, потому что мы не редактировали никакого кода фреймворка.
Комментарии:
1. При этом я получаю сообщение об ошибке.
Argument 1 passed to CreateTableName::{closure}() must be an instance of ExtendedBlueprint, instance of IlluminateDatabaseSchemaBlueprint given
Есть мысли? Я изменил Blueprint на ExtendedBlueprint в моем обратном вызове create.2. Я понял это. Я использовал
Schema::create( ... )
вместо $schema-> create( …)
Ответ №2:
На данный момент Laravel Schema Builder не поддерживает набор типов данных для столбцов. Итак, вот альтернативное решение, пока кто-нибудь не добавит этот код в Laravel.
Шаг 1: Создайте таблицу, используйте ENUM вместо SET .
Schema::create('schools', function($table)
{
$table->increments('id');
$table->char('id_number', 6);
$table->string('school_name');
$table->enum('level', array('Preschool', 'Kindergarten', 'Primary', 'Secondary'))->index(); // *** fix this
$table->string('phone');
$table->string('email');
$table->string('location');
$table->smallInteger('city')->unsigned()->index();
$table->smallInteger('country')->unsigned()->index();
$table->smallInteger('head_teacher')->unsigned()->index();
$table->smallInteger('director')->unsigned()->index();
$table->smallInteger('created_by')->unsigned();
$table->smallInteger('modified_by')->unsigned();
$table->timestamps();
});
Шаг 2: теперь измените ENUM на SET .
$table_prefix = DB::getTablePrefix();
DB::statement("ALTER TABLE `" . $table_prefix . "schools` CHANGE `level` `level` SET('Preschool','Kindergarten','Primary','Secondary');");
Если у вас есть лучшее решение, пожалуйста, дайте мне знать.
Комментарии:
1. Почему бы просто не добавить таблицу впоследствии (с помощью
DB::statement
вызова)? Почему вы добавляете его, а затем изменяете?2. @ajon Хороший вопрос. Я сделал это так, чтобы свести использование
DB::statement
к минимуму.
Ответ №3:
Метод Романа Назаркина работает почти идеально, однако есть небольшая проблема с префиксами таблиц (которые этот метод не учитывает), однако просто заставить это предложение работать с префиксами таблиц:
$grammar = DB::connection()->withTablePrefix(new ExtendedMySqlGrammar());
// set new grammar class
DB::connection()->setSchemaGrammar($grammar);
// get custom schema object
$schema = DB::connection()->getSchemaBuilder();
// bind new blueprint class
$schema->blueprintResolver(function($table, $callback) {
return new ExtendedBlueprint($table, $callback);
});
// then create tables
$schema->create('table name', function(ExtendedBlueprint $table)
{
$table->increments('id');
$table->text('sentence');
$table->string('author')->nullable();
$table->string('source')->nullable();
$table->set('difficulty', range(1, 10)); // use our new mysql type
$table->boolean('enabled')->default(true);
});
Ответ №4:
Laravel 5.8 и более поздние версии поддерживают набор типов данных при миграции. Для последних версий вам просто нужно использовать set()
function:
// SET equivalent column named flavors
// Allowed values: strawberry , vanilla
$table->set('flavors', ['strawberry', 'vanilla']);
Проверьте более подробную информацию в последней документации:
Ответ №5:
Мое простое одноразовое решение, когда вам нужно создать пользовательский столбец без создания дополнительных файлов для описания расширенной грамматики. Здесь я добавляю свой пользовательский тип rsvp_statuses
в PostgresGrammar
:
public function up()
{
DB::connection()->setSchemaGrammar(new class extends PostgresGrammar {
protected function typeRsvp_statuses(IlluminateSupportFluent $column)
{
return 'rsvp_statuses';
}
});
Schema::create('mytable', function (Blueprint $table) {
$table->bigIncrements('id');
//...
$table->addColumn('rsvp_statuses', 'status');
$table->timestamps();
});
}
Ответ №6:
Расширение методов схемы базы данных laravel не слишком сложно. Как писал Роман, вместо расширения вы также можете обновить свой
vendor/laravel/framework/src/Illuminate/Database/Schema/Grammers/MysqlGrammer.php
/**
* Create the column definition for an set type.
*
* @param IlluminateSupportFluent $column
* @return string
*/
protected function typeSet(Fluent $column){
return "set('".implode("', '", $column->allowed)."')";
}
vendor/laravel/framework/src/Illuminate/Database/Schema/Blueprint.php
/**
* Create a new set column on the table.
*
* @param string $column
* @param array $allowed
* @return IlluminateSupportFluent
*/
public function set($column, array $allowed){
return $this->addColumn('set', $column, compact('allowed'));
}
После этого завершите работу вашего сервера, нажав Ctrl C. Затем введите php artisan serve для запуска laravel.