Änderung der Laravel-Migration, um eine Spalte auf Null zu setzen

194

Ich habe eine Migration mit unsigned erstellt user_id. Wie kann ich user_ideine neue Migration bearbeiten , um sie auch zu erstellen nullable()?

Schema::create('throttle', function(Blueprint $table)
{
    $table->increments('id');
    // this needs to also be nullable, how should the next migration be?
    $table->integer('user_id')->unsigned();
}
user391986
quelle

Antworten:

262

Laravel 5 unterstützt jetzt das Ändern einer Spalte. Hier ist ein Beispiel aus der offiziellen Dokumentation:

Schema::table('users', function($table)
{
    $table->string('name', 50)->nullable()->change();
});

Quelle: http://laravel.com/docs/5.0/schema#changing-columns

Laravel 4 unterstützt das Ändern von Spalten nicht. Daher müssen Sie eine andere Technik verwenden, z. B. das Schreiben eines unformatierten SQL-Befehls. Beispielsweise:

// getting Laravel App Instance
$app = app();

// getting laravel main version
$laravelVer = explode('.',$app::VERSION);

switch ($laravelVer[0]) {

    // Laravel 4
    case('4'):

        DB::statement('ALTER TABLE `pro_categories_langs` MODIFY `name` VARCHAR(100) NULL;');
        break;

    // Laravel 5, or Laravel 6
    default:                

        Schema::table('pro_categories_langs', function(Blueprint $t) {
            $t->string('name', 100)->nullable()->change();
        });               

}
MURATSPLAT
quelle
3
Danke dafür. Aber wie kann ich das Gegenteil machen? Wie ändere ich eine Spalte so, dass sie nicht nullbar ist? Irgendwelche Ideen?
Algorithmus
@algorhythm Versuchen Sie diese '$ t-> Zeichenfolge (' Name ', 100) -> change ();'
MURATSPLAT
7
Sie müssen Doctrine \ dbal für die Migration benötigen
younes0
33
Mit @algorhythm ->nullable(false)können Sie die Spalte wieder ändern.
Colin
9
-> change () erfordert die Installation des Doctrine DBAL-Pakets und erkennt nicht von Natur aus alle Spaltentypen, die standardmäßig von laravel verfügbar sind. Beispielsweise ist double für DBAL kein erkannter Spaltentyp.
Will Vincent
174

Hier ist die vollständige Antwort für den zukünftigen Leser. Beachten Sie, dass dies nur in Laravel 5+ möglich ist.

Zunächst benötigen Sie das Doctrine / Dbal- Paket:

composer require doctrine/dbal

Jetzt in Ihrer Migration können Sie dies tun, um die Spalte nullbar zu machen:

public function up()
{
    Schema::table('users', function (Blueprint $table) {
        // change() tells the Schema builder that we are altering a table
        $table->integer('user_id')->unsigned()->nullable()->change();
    });
}

Möglicherweise fragen Sie sich, wie Sie diesen Vorgang rückgängig machen können. Leider wird diese Syntax nicht unterstützt:

// Sadly does not work :'(
$table->integer('user_id')->unsigned()->change();

Dies ist die richtige Syntax, um die Migration zurückzusetzen:

$table->integer('user_id')->unsigned()->nullable(false)->change();

Wenn Sie möchten, können Sie auch eine Rohabfrage schreiben:

public function down()
{
    /* Make user_id un-nullable */
    DB::statement('UPDATE `users` SET `user_id` = 0 WHERE `user_id` IS NULL;');
    DB::statement('ALTER TABLE `users` MODIFY `user_id` INTEGER UNSIGNED NOT NULL;');
}

Hoffentlich finden Sie diese Antwort hilfreich. :) :)

Dmitri Chebotarev
quelle
3
Dies ist die vollständigste Antwort für L5. Es sollte jedoch erwähnt werden, dass Sie, wenn 'user_id' ein Fremdschlüssel ist, diesen nicht ändern können, es sei denn, Sie führen die Anweisung 'DB ::' (SET FOREIGN_KEY_CHECKS) aus = 0 ');' zuerst. Und setzen Sie es wieder auf 1, wenn Sie fertig sind.
RZB
1
Danke, nullable(false)hat mich davor bewahrt, mir die Haare auszureißen, weil nullable()es nicht gut dokumentiert ist und es keine notNull()Funktion gibt.
Zack Morris
Dies funktioniert nicht für Fremdschlüssel mit Postgres. versuchen SET FOREIGN_KEY_CHECKS = 0gibt einen Fehler. Wahrscheinlich müssen Sie die Einschränkungen der Tabelle mithilfe einer Rohabfrage ändern. siehe hier: postgresql.org/docs/current/static/sql-altertable.html
rrrafalsz
Das bricht meine Tests. Die Tests beginnen zu laufen und hängen dann. Ich nehme an, der erste Rollback verursacht dies. Verursacht Hängetests sowohl für MySQL als auch für SQLite.
Thomas Praxl
155

Ich gehe davon aus, dass Sie versuchen, eine Spalte zu bearbeiten, zu der Sie bereits Daten hinzugefügt haben. Daher ist es nicht möglich, eine Spalte zu löschen und erneut als nullfähige Spalte hinzuzufügen, ohne Daten zu verlieren. Wir werden alterdie vorhandene Spalte.

Der Schema-Builder von Laravel unterstützt jedoch keine anderen Änderungen als das Umbenennen der Spalte. Sie müssen also folgende Rohdatenabfragen ausführen:

function up()
{
    DB::statement('ALTER TABLE `throttle` MODIFY `user_id` INTEGER UNSIGNED NULL;');
}

Und um sicherzustellen, dass Sie Ihre Migration weiterhin rückgängig machen können, werden wir dies auch tun down().

function down()
{
    DB::statement('ALTER TABLE `throttle` MODIFY `user_id` INTEGER UNSIGNED NOT NULL;');
}

Ein Hinweis ist, dass Sie, da Sie zwischen nullbar und nicht nullbar konvertieren, sicherstellen müssen, dass Sie die Daten vor / nach Ihrer Migration bereinigen. Tun Sie dies in Ihrem Migrationsskript in beide Richtungen:

function up()
{
    DB::statement('ALTER TABLE `throttle` MODIFY `user_id` INTEGER UNSIGNED NULL;');
    DB::statement('UPDATE `throttle` SET `user_id` = NULL WHERE `user_id` = 0;');
}

function down()
{
    DB::statement('UPDATE `throttle` SET `user_id` = 0 WHERE `user_id` IS NULL;');
    DB::statement('ALTER TABLE `throttle` MODIFY `user_id` INTEGER UNSIGNED NOT NULL;');
}
Unnawut
quelle
7
Für Laravel 4 ersetzen Sie querydurchstatement
Razor
2
Danke @Razor. Meine Antwort wurde entsprechend aktualisiert.
Unnawut
1
In der downFunktion im zweiten Codeblock sollte die SQL-Anweisung mit enden NOT NULL. (Die downFunktion im dritten Beispiel ist korrekt.)
Scott Weldon
46

Er ist die vollständige Migration für Laravel 5 :

public function up()
{
    Schema::table('users', function (Blueprint $table) {
        $table->unsignedInteger('user_id')->nullable()->change();
    });
}

public function down()
{
    Schema::table('users', function (Blueprint $table) {
        $table->unsignedInteger('user_id')->nullable(false)->change();
    });
}

Der Punkt ist, Sie können entfernen, nullableindem Sie falseals Argument übergeben.

Yauheni Prakopchyk
quelle
16

Wenn Sie zufällig die Spalten wechseln und weiter stolpern

'Doctrine\DBAL\Driver\PDOMySql\Driver' not found

dann einfach installieren

composer require doctrine/dbal

Ken
quelle
1
Dies hat mich
gebissen
9

Hinzufügen zu Dmitri Chebotarevs Antwort, wie für Laravel 5+.

Nach Anforderung des Doctrine / Dbal- Pakets:

composer require doctrine/dbal

Sie können dann eine Migration mit nullbaren Spalten durchführen, wie folgt:

public function up()
{
    Schema::table('users', function (Blueprint $table) {
        // change() tells the Schema builder that we are altering a table
        $table->integer('user_id')->unsigned()->nullable()->change();
    });
}

Gehen Sie wie folgt vor, um den Vorgang zurückzusetzen:

public function down()
{
    /* turn off foreign key checks for a moment */
    DB::statement('SET FOREIGN_KEY_CHECKS = 0');
    /* set null values to 0 first */
    DB::statement('UPDATE `users` SET `user_id` = 0 WHERE `user_id` IS NULL;');
    /* alter table */
    DB::statement('ALTER TABLE `users` MODIFY `user_id` INTEGER UNSIGNED NOT NULL;');
    /* finally turn foreign key checks back on */
    DB::statement('SET FOREIGN_KEY_CHECKS = 1');
}
rzb
quelle
3

Hinzufügen zu Dmitri Chebotarev Antwort,

Wenn Sie mehrere Spalten gleichzeitig ändern möchten, können Sie dies wie unten beschrieben tun

DB::statement('
     ALTER TABLE `events` 
            MODIFY `event_date` DATE NOT NULL,
            MODIFY `event_start_time` TIME NOT NULL,
            MODIFY `event_end_time` TIME NOT NULL;
');
Sameer
quelle
2

Versuch es:

$table->integer('user_id')->unsigned()->nullable();
Adil
quelle
1
Es ändert nicht vorhandene Spalte
dVaffection
9
Sie haben ->changeam Ende vergessen und nur Laravel 5+ zu erwähnen
Alexander Malakhov
Sie müssen benötigencomposer require doctrine/dbal
Lizesh Shakya
2

Für Laravel 4.2 ist die obige Antwort von Unnawut die beste. Wenn Sie jedoch ein Tabellenpräfix verwenden, müssen Sie Ihren Code ein wenig ändern.

function up()
{
    $table_prefix = DB::getTablePrefix();
    DB::statement('ALTER TABLE `' . $table_prefix . 'throttle` MODIFY `user_id` INTEGER UNSIGNED NULL;');
}

Und um sicherzustellen, dass Sie Ihre Migration weiterhin rückgängig machen können, werden wir dies auch tun down().

function down()
{
    $table_prefix = DB::getTablePrefix();
    DB::statement('ALTER TABLE `' . $table_prefix . 'throttle` MODIFY `user_id` INTEGER UNSIGNED NOT NULL;');
}
Debiprasad
quelle