Laravel 5.4 Tutorial Part-6: Migrations

What is Laravel Migrations?

In Laravel, Migrations offer a file-based approach to changing the structure of your database, allowing you to create and drop tables, add, update and delete columns, and add indexes, among other tasks. Further, you can easily revert, or roll back, any changes if a mistake has been made or you otherwise reconsider the decision. Finally, because each migration is stored in a text file, you can manage them within your project repository.

Install Laravel Migration Table

To creates the database Migratin table that keeps track of which migrations you have and haven’t run; this is run automatically when you run your migrations.

php artisan migrate:install

See the example:

PHP Artisan Install Migration

PHP Artisan Install Migration

Now you can see migration table already created in your database:

Database Migration Table

Database Migration Table

Create New Laravel Migration File

To create a new migration file with model, use the make:model migration_file_name -m Artisan command:

php artisan make:model users -m

Lets See the output

Create New Migration File

Create New Migration File

There are two flags you can optionally pass to this command. --create=table_name prefills the migration with code designed to create a table named table_name, and --table=_table_name_ just prefills the migration for modifications to an existing table. Here are a few examples:

Defining Laravel Migrations

A migration is a single file that defines two things: the modifications desired when running this migration up and the modifications desired when running this migration down.

“Up” and “Down” in Migrations

Migrations are always run in order by date. Every migration file is named something like this: 2014_10_12_000000_create_users_table.php located at database/migrations folder. When a new system is migrated,the system grabs each migration, starting at the earliest date, and runs its up() method—you’re migrating it “up” at this point. But the migration system also allows you to “roll back” your most recent set of migrations. It’ll grab each of them and run its down() method, which should undo whatever changes the up migration made. So, the up() method of a migration should “do” its migration, and the down() method should “undo” it.

So Let’s see our “create_users_table” migration that looks like.

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateUsersTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('users', function (Blueprint $table) {
            $table->increments('id');
            $table->timestamps();
            $table->string('name');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('users');
    }
}


Configure Laravel Database

To work with laravel migration, first you need to connect your database in Laravel, you can utilizes the .env PHP library by Vance Lucas. In a fresh Laravel installation, the root directory of your application will contain a .env.example file. If you install Laravel via Composer, this file will automatically be renamed to .env. Otherwise, you should rename the file manually.

laravel database-connection in env file

laravel database-connection in env file

Creating tables

We already saw in ourcreate_users_table migration that our migrations depend on the Schema facade and its methods. Everything we can do in these migrations will rely on the methods of Schema. To create a new table in a migration, use the create() method—the first parameter is the table name, and the second is a closure that defines its columns:

Schema::create('tablename', function (Blueprint $table) {
// Create columns here
});

Dropping tables

If you want to drop a table, there’s a drop method on Schema that takes one parameter,the table name:

Schema::drop('users');

Creating columns

To create new columns in a table, whether in a create table call or a modify table call,use the instance of Blueprint that’s passed into your closure:

Schema::create('users', function (Blueprint $table) {
$table->string('name');
});

Let’s look at the various methods available on Blueprint instances for creating columns. I’ll describe how they work in MySQL, but if you’re using another database, Laravel will just use the closest equivalent.

Running Laravel Migrations

To run all of your outstanding migrations, execute the migrate Artisan command:

php artisan migrate

See the Output:

Laravel Running Migration in command line

Laravel Running Migration in command line

Laravel Running Migration

Laravel Running Migration

Migration Insert Data

We already create an users table and add 33 seed records using Faker Library. Open/database/migrations/2017_03_05_073454_create_users_table.php.

Add the following code:

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateUsersTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('users', function (Blueprint $table) {
            $table->increments('id');
            $table->timestamps();
            $table->string('name');

        });

        $faker = Faker\Factory::create();

        $limit = 33;

        for ($i = 0; $i < $limit; $i++) {
            DB::table('users')->insert([ //,
                'name' => $faker->name,
            ]);
        }
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('users');
    }
}

HERE,

$faker = Faker\Factory::create(); creates an instance of Faker factory
$limit = 33; sets the number of records that we want to add to the database.
for ($i = 0; $i < $limit; $i++) { DB::table('users')->insert([…]);} uses a for loop to add records to the database 33 times. $faker->name generates a faker name

Run the following command to run the migration

php artisan migrate:refresh

You will get the following message

PHP Artisan Make Fake Data

PHP Artisan Make Fake Data



And See The Output:
Laravel Fake Data

Laravel Fake Data

Forcing Migrations To Run In Production

Some migration operations are destructive, which means they may cause you to lose data. In order to protect you from running these commands against your production database, you will be prompted for confirmation before the commands are executed. To force the commands to run without a prompt, use the --force flag:

php artisan migrate --force

Rolling Back Migrations

To rollback the latest migration operation, you may use the rollback command. This command rolls back the last “batch” of migrations, which may include multiple migration files:

php artisan migrate:rollback

You may rollback a limited number of migrations by providing the step option to the rollback command. For example, the following command will rollback the last five migrations:

php artisan migrate:rollback --step=5

The migrate:reset command will roll back all of your application’s migrations:

php artisan migrate:reset

Rollback & Migrate In Single Command

The migrate:refresh command will roll back all of your migrations and then execute the migrate command. This command effectively re-creates your entire database:

php artisan migrate:refresh

// Refresh the database and run all database seeds…

php artisan migrate:refresh --seed

You may rollback & re-migrate a limited number of migrations by providing the step option to the refresh command. For example, the following command will rollback & re-migrate the last five migrations:

php artisan migrate:refresh --step=5

Migration Add Column / Drop Colum

If you want to add a new column to users table for email. You want to add the new column after the name field.

Run the following command

php artisan make:migration add_email_to_users --table=users

HERE

--table=users tells Laravel you want to work with an existing table called users

Lets see Output:

add new field in table using migration

add new field in table using migration


Open the new migration file in /database/migration/2017_03_09_101140_add_email_to_users.php

Modify it to the following

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class AddEmailToUsers extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::table('users', function (Blueprint $table) {

             $table->string('email')->after('name');
            
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::table('users', function (Blueprint $table) {
             $table->dropColumn('email');
        });
    }
}

HERE,

public function up(){…} uses Schema::table(‘users’…) to add a new column email
public function down(){…} drops the new column from the table when we reverse the command. $table->dropColumn(’email’); is the command that drops the table.

Available Column Types

Of course, the schema builder contains a variety of column types that you may specify when building your tables:

Command Description
$table->bigIncrements('id'); Incrementing ID (primary key) using a "UNSIGNED BIG INTEGER" equivalent.
$table->bigInteger('votes'); BIGINT equivalent for the database.
$table->binary('data'); BLOB equivalent for the database.
$table->boolean('confirmed'); BOOLEAN equivalent for the database.
$table->char('name', 4); CHAR equivalent with a length.
$table->date('created_at'); DATE equivalent for the database.
$table->dateTime('created_at'); DATETIME equivalent for the database.
$table->dateTimeTz('created_at'); DATETIME (with timezone) equivalent for the database.
$table->decimal('amount', 5, 2); DECIMAL equivalent with a precision and scale.
$table->double('column', 15, 8); DOUBLE equivalent with precision, 15 digits in total and 8 after the decimal point.
$table->enum('choices', ['foo', 'bar']); ENUM equivalent for the database.
$table->float('amount', 8, 2); FLOAT equivalent for the database, 8 digits in total and 2 after the decimal point.
$table->increments('id'); Incrementing ID (primary key) using a "UNSIGNED INTEGER" equivalent.
$table->integer('votes'); INTEGER equivalent for the database.
$table->ipAddress('visitor'); IP address equivalent for the database.
$table->json('options'); JSON equivalent for the database.
$table->jsonb('options'); JSONB equivalent for the database.
$table->longText('description'); LONGTEXT equivalent for the database.
$table->macAddress('device'); MAC address equivalent for the database.
$table->mediumIncrements('id'); Incrementing ID (primary key) using a "UNSIGNED MEDIUM INTEGER" equivalent.
$table->mediumInteger('numbers'); MEDIUMINT equivalent for the database.
$table->mediumText('description'); MEDIUMTEXT equivalent for the database.
$table->morphs('taggable'); Adds unsigned INTEGER taggable_id and STRING taggable_type.
$table->nullableMorphs('taggable'); Nullable versions of the morphs() columns.
$table->nullableTimestamps(); Nullable versions of the timestamps() columns.
$table->rememberToken(); Adds remember_token as VARCHAR(100) NULL.
$table->smallIncrements('id'); Incrementing ID (primary key) using a "UNSIGNED SMALL INTEGER" equivalent.
$table->smallInteger('votes'); SMALLINT equivalent for the database.
$table->softDeletes(); Adds nullable deleted_at column for soft deletes.
$table->string('email'); VARCHAR equivalent column.
$table->string('name', 100); VARCHAR equivalent with a length.
$table->text('description'); TEXT equivalent for the database.
$table->time('sunrise'); TIME equivalent for the database.
$table->timeTz('sunrise'); TIME (with timezone) equivalent for the database.
$table->tinyInteger('numbers'); TINYINT equivalent for the database.
$table->timestamp('added_on'); TIMESTAMP equivalent for the database.
$table->timestampTz('added_on'); TIMESTAMP (with timezone) equivalent for the database.
$table->timestamps(); Adds nullable created_at and updated_at columns.
$table->timestampsTz(); Adds nullable created_at and updated_at (with timezone) columns.
$table->unsignedBigInteger('votes'); Unsigned BIGINT equivalent for the database.
$table->unsignedInteger('votes'); Unsigned INT equivalent for the database.
$table->unsignedMediumInteger('votes'); Unsigned MEDIUMINT equivalent for the database.
$table->unsignedSmallInteger('votes'); Unsigned SMALLINT equivalent for the database.
$table->unsignedTinyInteger('votes'); Unsigned TINYINT equivalent for the database.
$table->uuid('id'); UUID equivalent for the database.

Column Modifiers

In addition to the column types listed above, there are several column "modifiers" you may use while adding a column to a database table. For example, to make the column "nullable", you may use the nullable method:

Schema::table('users', function (Blueprint $table) { $table->string('email')->nullable(); });

Below is a list of all the available column modifiers. This list does not include the index modifiers:

Modifier Description
->after('column') Place the column "after" another column (MySQL Only)
->comment('my comment') Add a comment to a column
->default($value) Specify a "default" value for the column
->first() Place the column "first" in the table (MySQL Only)
->nullable() Allow NULL values to be inserted into the column
->storedAs($expression) Create a stored generated column (MySQL Only)
->unsigned() Set integer columns to UNSIGNED
->virtualAs($expression) Create a virtual generated column (MySQL Only)

Modifying Columns

Prerequisites

Before modifying a column, be sure to add the doctrine/dbal dependency to your composer.json file. The Doctrine DBAL library is used to determine the current state of the column and create the SQL queries needed to make the specified adjustments to the column:

composer require doctrine/dbal

Updating Column Attributes

The change method allows you to modify some existing column types to a new type or modify the column's attributes. For example, you may wish to increase the size of a string column. To see the change method in action, let's increase the size of the name column from 25 to 50:

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

We could also modify a column to be nullable:

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

Renaming Columns

To rename a column, you may use the renameColumn method on the Schema builder. Before renaming a column, be sure to add the doctrine/dbal dependency to your composer.json file:

Schema::table('users', function (Blueprint $table) {
    $table->renameColumn('from', 'to');
});

Dropping Columns

To drop a column, use the dropColumn method on the Schema builder. Before dropping columns from a SQLite database, you will need to add the doctrine/dbal dependency to your composer.json file and run the composer update command in your terminal to install the library:

Schema::table('users', function (Blueprint $table) {
    $table->dropColumn('votes');
});

You may drop multiple columns from a table by passing an array of column names to the dropColumn method:

Schema::table('users', function (Blueprint $table) {
    $table->dropColumn(['votes', 'avatar', 'location']);
});

Creating Indexes

The schema builder supports several types of indexes. First, let's look at an example that specifies a column's values should be unique. To create the index, we can simply chain the unique method onto the column definition:

$table->string('email')->unique();

Alternatively, you may create the index after defining the column. For example:

$table->unique('email');

You may even pass an array of columns to an index method to create a compound index:

$table->index(['account_id', 'created_at']);

Laravel will automatically generate a reasonable index name, but you may pass a second argument to the method to specify the name yourself:

$table->index('email', 'my_index_name');

Available Index Types

Command Description
$table->primary('id'); Add a primary key.
$table->primary(['first', 'last']); Add composite keys.
$table->unique('email'); Add a unique index.
$table->unique('state', 'my_index_name'); Add a custom index name.
$table->unique(['first', 'last']); Add a composite unique index.
$table->index('state'); Add a basic index.

Index Lengths & MySQL / MariaDB

Laravel uses the utf8mb4 character set by default, which includes support for storing "emojis" in the database. If you are running a version of MySQL older than the 5.7.7 release or MariaDB older than the 10.2.2 release, you may need to manually configure the default string length generated by migrations in order for MySQL to create indexes for them. You may configure this by calling the Schema::defaultStringLength method within your AppServiceProvider:

use Illuminate\Support\Facades\Schema;

/**
 * Bootstrap any application services.
 *
 * @return void
 */
public function boot()
{
    Schema::defaultStringLength(191);
}

Alternatively, you may enable the innodb_large_prefix option for your database. Refer to your database's documentation for instructions on how to properly enable this option.

Dropping Indexes

To drop an index, you must specify the index's name. By default, Laravel automatically assigns a reasonable name to the indexes. Simply concatenate the table name, the name of the indexed column, and the index type. Here are some examples:

Command Description
$table->dropPrimary('users_id_primary'); Drop a primary key from the "users" table.
$table->dropUnique('users_email_unique'); Drop a unique index from the "users" table.
$table->dropIndex('geo_state_index'); Drop a basic index from the "geo" table.

If you pass an array of columns into a method that drops indexes, the conventional index name will be generated based on the table name, columns and key type:

Schema::table('geo', function (Blueprint $table) {
    $table->dropIndex(['state']); // Drops index 'geo_state_index'
});
Hi, My name is Masud Alam, love to work with Open Source Technologies, living in Dhaka, Bangladesh. I graduated in 2009 with a bachelor’s degree in Engineering from State University Of Bangladesh, I’m also a Certified Engineer on ZEND PHP 5.3, I served my first five years a number of leadership positions at Winux Soft Ltd, SSL Wireless Ltd, CIDA and MAX Group where I worked on ERP software and web development., but now i’m a co-founder and Chief Executive Officer and Managing Director of TechBeeo Software Consultancy Services Ltd. I’m also a Course Instructor of ZCPE PHP 7 Certification and professional web development course at w3programmers Training Institute – a leading Training Institute in the country.

Leave a Reply

Your email address will not be published. Required fields are marked *