Skip to content

Building the Data Model Creating Migration

Adarsh Kumar Maurya edited this page Nov 27, 2018 · 1 revision

Now we have done a couple of steps like to get the project installed, get the environment configured. That's basically it.

We are ready now to build our own code inside the framework.

The first step we want to take here though is to define our data model.

So actually connecting with the database. Trying to decide which kind of database structure we want to have. We are going to use Database Migration, it is a great migration tool set built into the framework. And this kind of gets us a code first data structure.

Some school of thoughts or some people are like, "Database first and then you get the code to line up with or you do code always inform what the database will be?"

We are actually doing code first, so we handle all changes to the database using these migrations. Initially we have migrations to create tables, create columns and kind of build out what we want the data structure to be and then later on in the life cycle of the project, we will actually make migrations to manipulate the database.

You can add a column or add a column or rename a column or add new tables, you would just build migrations for each of those types of things.

We have a couple of commands that we can run using Artisan to create these migrations. The first thing that we are going to do though is that stock Laravel comes with two migrations that are for users and passwords, password resets. We won't be using those..so lets start by removing through the command line as:

Adarsh:database adarshmaurya$ ls -la
total 8
drwxr-xr-x   6 adarshmaurya  staff  192 Nov 22 19:58 .
drwxr-xr-x  25 adarshmaurya  staff  800 Nov 27 01:29 ..
-rw-r--r--   1 adarshmaurya  staff    9 Nov 22 19:58 .gitignore
drwxr-xr-x   3 adarshmaurya  staff   96 Nov 22 19:58 factories
drwxr-xr-x   4 adarshmaurya  staff  128 Nov 22 19:58 migrations
drwxr-xr-x   3 adarshmaurya  staff   96 Nov 22 19:58 seeds
Adarsh:database adarshmaurya$ cd migrations
Adarsh:migrations adarshmaurya$ ls -la
total 16
drwxr-xr-x  4 adarshmaurya  staff  128 Nov 22 19:58 .
drwxr-xr-x  6 adarshmaurya  staff  192 Nov 22 19:58 ..
-rw-r--r--  1 adarshmaurya  staff  810 Nov 22 19:58 2014_10_12_000000_create_users_table.php
-rw-r--r--  1 adarshmaurya  staff  683 Nov 22 19:58 2014_10_12_100000_create_password_resets_table.php
Adarsh:migrations adarshmaurya$ rm -f 2014_10_12_000000_create_users_table.php
Adarsh:migrations adarshmaurya$ rm -f 2014_10_12_100000_create_password_resets_table.php 

So next things we gonna do is build our products and our descriptions migrations.We can use artisan tools to generate the code for us or you can manually build them by copying and pasting, there's some good documentation online.

At the bare minimum, all you need to do is get a hold of php artisan that there's a make namespace that you can use that has a whole bunch of other code generators in it.

We pull in the make namespace and then we are going to say is we want to make a migration.

php artisan make:migration create_product_table would generate the migration code for us, but there is an option which adds little more code for us. So, we can add an option create with a table name that you would like to have.

Adarsh:migrations adarshmaurya$ cd ..
Adarsh:database adarshmaurya$ cd ..
Adarsh:product-service adarshmaurya$ php artisan make:migration create_product_table  --create=products
Created Migration: 2018_11_26_233429_create_product_table

So now it won't be empty shell migration, it will be a migration with some plumbing already already put in that creates the products table for us. Created Migration: 2018_11_26_233429_create_product_table The name of the file includes a timestamp, so it can keep track of the order of the migrations themselves.

Now we would run the same for our description table.

Adarsh:product-service adarshmaurya$ php artisan make:migration create_descriptions_table  --create=descriptions 
Created Migration: 2018_11_26_234437_create_descriptions_table

Naming convention - We had used a plural for the migration name but when we are creating a model we would be going to use a singular table name.

Now let's check our database migration folder

Adarsh:product-service adarshmaurya$ cd database/migrations/
Adarsh:migrations adarshmaurya$ ls -la
total 16
drwxr-xr-x  4 adarshmaurya  staff  128 Nov 27 05:14 .
drwxr-xr-x  6 adarshmaurya  staff  192 Nov 22 19:58 ..
-rw-r--r--  1 adarshmaurya  staff  594 Nov 27 05:04 2018_11_26_233429_create_product_table.php
-rw-r--r--  1 adarshmaurya  staff  607 Nov 27 05:14 2018_11_26_234437_create_descriptions_table.php
Adarsh:product-service adarshmaurya$ cd database/migrations/
Adarsh:migrations adarshmaurya$ ls -la
total 16
drwxr-xr-x  4 adarshmaurya  staff  128 Nov 27 05:14 .
drwxr-xr-x  6 adarshmaurya  staff  192 Nov 22 19:58 ..
-rw-r--r--  1 adarshmaurya  staff  594 Nov 27 05:04 2018_11_26_233429_create_product_table.php
-rw-r--r--  1 adarshmaurya  staff  607 Nov 27 05:14 2018_11_26_234437_create_descriptions_table.php
Adarsh:migrations adarshmaurya$ vim 2018_11_26_233429_create_product_table.php

we can see we have create product table migration set up for us. If we have omitted the create option then the function up() and function down() method would be empty. If we add it then it adds a little bit of extra work. It automatically assumes we are going to want an incrementing ID and assumes that we want some basic audit column timestamps inside the table, it creates those for us.

<?php

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

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

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

The general make up of the Migration class is just basically the up method and the down method. So when we actually run migrations, its just going to go through and do all the ups we need. If we need to roll them back, it knows to go through and run the down. So, whatever the up is, the down is always going to be the thing that makes it go away.

Let's update our products table

<?php

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

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

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

We have added $table->string('name'); which give us the name of the product. Let's now update the descriptions table. As our descriptions actually have a relationship with the product themselves, we are going to need an extra column to define that relationship i.e a foreign key.

<?php

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

class CreateDescriptionsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('descriptions', function (Blueprint $table) {
            $table->increments('id');
            $table->integer('product_id')->unsigned();
            $table->text('body');
            $table->timestamps();
        });
    }

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

Because the increment of the products is a int,our foreign key is going to be $table->integer('product_id')->unsigned();, unsigned because it is a foreign key.

There is an extra sort of command that you want to tell the migration too to set up the relationship officially. This one is called where we need to tell which column i.e 'product_id' actually needs to have the foreign relationship, to what it references i.e 'id' on 'products' tables. $table->foreign('product_id)->references('id')->on('products');

Now let's go back to our command line, and use Artisan to do some more work for us. Run php artisan migrate it's going to look our file system: It's going yo say, we have these migrations to run, it's going to notice that the database does not have any of these tables created already & it's going to create migration table that manages the sequence of all of these and also manages our migrations themselves.

Please note before migration check your database configuration. I had to make a database manually and had to change the username and password as below:

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=homestead
DB_USERNAME=root
DB_PASSWORD=''
Adarsh:product-service adarshmaurya$ php artisan migrate -v
Migration table created successfully.
Migrating: 2018_11_26_233429_create_product_table
Migrated:  2018_11_26_233429_create_product_table
Migrating: 2018_11_26_234437_create_descriptions_table
Migrated:  2018_11_26_234437_create_descriptions_table

These timestamps are helpful in letting the framework know, what order to run things. So whenever one creates a migration, they can live inside the code base and no matter what, the code will always say this is what we need to run in what order but it always checks that migrations table to see what's already run or what need to be run.

We are handling all our sql via migration. Is there a time where we go in and manually input sql to do anything? Preferentially no, as long as the code represents what the database needs to be, you have lot more confidence that it's actually going to work all the time.

Time to check your migrated tables in the database!