03. Laravel for Frontend developers – migrations and models

Read the previous post or watch a screencast version instead of reading it.

In the last post, we had a look over how routing works in a Laravel application and even added an endpoint returning some hardcoded JSON. In this post, we’ll see how we can connect to MySQL, start creating our database schema, and return actual records from a foods table.

Migrations

Every structure-related change in the database schema must be done through a migration file: creating tables, adding, removing, or modifying columns. Think of it as being a mini-versioning control system for your database.

A migration file consists of two methods: the up() method that is executed when the migration runs against the database and the down() method that gets called whenever you want to reverse your changes.

Consider the following example taken from Laravel’s default migrations:

<?php

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

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

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

The up() method uses the Schema::create method to define and create the users table, while the down() rolls back the changes by dropping the table. Whatever the up() method does to the database should be reversed by the down() method.

Creating a migration

In a similar fashion, we should create a migration file for our foods table. To do so, open your terminal and type in the following artisan command:

php artisan make:migration create_foods_table 

If you open up the newly created migration file, you’ll see that Laravel was smart enough to figure out the table name from the command argument we just ran. As long as you follow a create_TABLENAME_table structure, it will be able to pick up the correct name.

By default, every migration gets created with an id() column which is a big integer that autoincrements itself every time a new record is added, and timestamps(), which create two columns: created_at and updated_at that are filled in automatically whenever we create or update a record.

Schema::create('foods', function (Blueprint $table) {
    $table->id();
    $table->timestamps();
});

Since we are building an API for a food tracker application, our foods table should include the name of the food and its nutritional information:

Schema::create('foods', function (Blueprint $table) {
    $table->id();
    $table->string('name');
    $table->decimal('carbs');
    $table->decimal('fats');
    $table->decimal('proteins');
    $table->decimal('calories');
    $table->decimal('qty');
    $table->string('um');
    $table->timestamps();
});

Now that we have a migration for the foods table, we need to set up our database connection so we can run the migrations. To do so, create a new database – you can do that by using the command line, but I recommend installing a database management application like SequelPro (works only on macOS but I’m sure windows and Linux have similar apps).

Once you’ve created your database, open up your .env file and edit the DB_ related information. Most of the times you only need to change the DB_DATABASE to match your database name and the DB_USERNAME and DB_PASSWORD to match your database user and password if you’ve changed the defaults.

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=root
DB_PASSWORD=

To run the migrations, open your terminal and type in the following command:

php artisan migrate

If you go ahead and refresh your database, you should see the following tables: faild_jobs, food, migrations, and users.

Add a few records to your foods table so we have something to play with.

Creating a model

Now that we have a foods table, we need a way to access the data inside it. To do that, we have to create a model. Models are Laravel’s way of speaking with the database – they provide us methods that allow us to query, insert, and update records without writing any SQL code. Almost every table in the database will have a corresponding model.

To create a new model, open your terminal and type in the following command:

php artisan make:model Food

If you go to the app directory, you’ll see that you now have a Food.php file.

In 99% of the cases, Laravel is smart enough to match the model with its table by pluralizing the model name, but in our case, food is one of those words where the singular and plural versions are the same – food.

To make sure the Food model uses the correct table, add in the following line:

class Food extends Model
{
    public $table = 'foods';
}

Querying the database

Now that we have a Food model, we can use it to query the database and return the results whenever our api/foods endpoint is called.

To do that, first go to the api.php routes file and make the following changes:

Route::get('/foods', 'FoodsController@index');
Route::get('/foods/{id}', 'FoodsController@show');

We use the first route to retrieve a list of foods, while the second finds and returns a single food record by its id.

Open the FoodsController file and make the following changes:

public function index()
{
    return Food::paginate();
}

public function show($id)
{
    return Food::findOrFail($id);
}

The index() method will return a paginated list of foods, while the second, show() method, will query the foods table for a record matching the $id we pass through our route and if there’s no record to be found, a 404 response will be returned.

To test we did everything correctly, open your browser and go to theapi/foods route. If you get an error like the one below, you need to restart your PHP server.

Unknown database ‘laravel’. Either the database doesn’t exist or the .env hasn’t been loaded.

If you did everything correctly, you should see a list of foods like the one bellow.

Foods index API endpoint

If somehow something went wrong, please go ahead and skim through the video version, maybe you missed something – or perhaps I did! If that’s the case, leave a comment below 🙂

Read the previous post or watch a screencast version instead of reading it.


Playlist: LFFD

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.