Migrations and Models for shop on Laravel 8

This article is the first in a series of articles about creating a pizza shop on Laravel 8 + Inertia. Today I will talk about how to create migrations in Laravel 8, how to create models in Laravel and why they are needed.

Migration in Laravel 8

The first step in developing almost any web project is designing a database. Migrations in Laravel are responsible for creating tables in the database. They are very convenient if several developers are working on a project at once, as they allow one of them to quickly add changes to the other to his database.

For a pizza shop, I only need 3 migrations to create the corresponding tables: pizzas – for storing goods (pizzas), orders – for storing orders, and order_pizza – for storing links (which products were included in the order). In addition, Laravel initially has several migrations that create the users and password_resets tables, which will also be useful to me.

To create a new migration, Laravel has a special Artisan command that runs in the root of the project:

php artisan make:migration create_pizzas_table

After running the command, a migration template will be created in the database/migrations folder to create a new table. And in this template, you should add the columns that you want to create. If you know how to create tables in SQL, then using the Laravel migration documentation, you will quickly master them.

For example, this is how the migration for creating the pizzas table for store on Laravel looks like:

<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreatePizzasTable extends Migration
{
    public function up()
    {
        Schema::create('pizzas', function (Blueprint $table) {
            $table->id();
            $table->string('name')->index();
            $table->text('description');
            $table->decimal('price',12,2)->index();
            $table->string('image_url');
            $table->timestamps();
        });
    }

    public function down()
    {
        Schema::dropIfExists('pizzas');
    }
}

Now, if you create a database (in utf8mb4_unicode_ci format), configure its connection in the project’s .env file and run the command:

php artisan migrate

A table with the fields specified in the migration will be created in the database.

The up method contains the creation of the table, and the down method contains its deletion. The latter will be launched when the command is invoked:

php artisan migrate: rollback

It will roll back migrations that were run the last time the migrate command was run.

I create the orders table in the same way.

Schema::create('orders', function (Blueprint $table) {
    $table->id();
    $table->bigInteger('user_id')->unsigned()->index()->nullable();
    $table->string('firstname')->index();
    $table->string('lastname')->index();
    $table->text('address');
    $table->string('phone')->index();
    $table->string('email')->index();
    $table->decimal('subtotal',12,2)->index();
    $table->decimal('delivery',12,2)->index();
    $table->decimal('discount',12,2)->index();
    $table->decimal('total',12,2)->index();
    $table->timestamps();
    $table->foreign('user_id')->references('id')->on('users');
});

And the order_pizza table:

Schema::create('order_pizza', function (Blueprint $table) {
    $table->bigInteger('order_id')->unsigned()->index();
    $table->bigInteger('pizza_id')->unsigned()->index();
    $table->decimal('price',12,2)->index();
    $table->integer('count')->index();
    $table->foreign('order_id')->references('id')->on('orders');
    $table->foreign('pizza_id')->references('id')->on('pizzas');
});

Now that the necessary tables have been created and appeared in the database, we will need to somehow work with them, for this there are models in the framework.

Models in Laravel 8

Models in Laravel are needed in order to simply get data from the database directly from the project code without writing complex queries.

Models are stored in the app\Models folder. I create a new model for accessing the pizzas table there and call it Pizza.

<?php
namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Pizza extends Model
{
    protected $table = 'pizzas';

    const DELIVERY_PRICE = 1.00;
    const DISCOUNT_PRICE = 0.00;
    const CURRENCY_EUR = 'EUR';
    const CURRENCY_EUR_RATE = 0.84;
    const CURRENCY_USD_SIGN = '$';
    const CURRENCY_EUR_SIGN = '€';

    protected $fillable = [
        'name',
        'description',
        'price',
        'image_url',
    ];

    protected $visible = [
        'id',
        'name',
        'description',
        'price',
        'image_url',
    ];
}

In the model code, the table property is responsible for which table it works with, the fillable property is responsible for which fields will be available for modification, and the visible property is responsible for which fields will be displayed. It is also convenient to store different constants in the model.

In shop on Laravel 8 model Order looks like this.

<?php
namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Order extends Model
{
    protected $table = 'orders';

    protected $fillable = [
        'user_id',
        'firstname',
        'lastname',
        'address',
        'phone',
        'email',
        'subtotal',
        'delivery',
        'discount',
        'total',
    ];

    protected $visible = [
        'id',
        'user_id',
        'firstname',
        'lastname',
        'address',
        'phone',
        'email',
        'subtotal',
        'delivery',
        'discount',
        'total',
    ];

    public function pizzas()
    {
        return $this->belongsToMany('App\Models\Pizza', 'order_pizza',
            'order_id', 'pizza_id',
            'id', 'id')->using('App\Models\OrderPizza')->withPivot('price','count');
    }
}

As you can see, there is a pizzas method in the code above, which is Laravel’s implementation of the many to many relationship. In the order_pizza junction table, in addition to the order_id and pizza_id fields, there are also the price and count fields. They are needed to store the quantity of goods in the order and the price change in the pizzas table does not affect the price of already placed orders.

The linking table is described in the OrderPizza model.

<?php
namespace App\Models;

use Illuminate\Database\Eloquent\Relations\Pivot;

class OrderPizza extends Pivot
{
    protected $table = 'order_pizza';
}

Now, after creating models in Laravel, to get user orders in the application code, you can use just a easy commands, without writing any sql queries

$orders = Order::where('user_id', $request->user_id)->orderByDesc('id')->get();

But we will talk about the backend for Shop on Laravel 8 in detail in the next part. Subscribe to my Twitter not to miss.