Laravel Travel Agency API From Scratch

In this first lesson, we will create our DB structure with Migrations and Models. We have that structure from the client, so we must implement it. But it won't be that simple. There will be a few caveats along the way.

Plan of this lesson:

  • Create Models and Migrations
  • Solve the problem with word "Travel(s)" irregular plural form in Laravel
  • Create a Travel Model Accessor for the "number_of_nights" field
  • Create a Tour Model price() Attribute for float/integer conversion
  • Convert primary key integer IDs to UUIDs

The final result of this lesson will be this visual DB schema generated from a real database:

I'm a big fan of starting the project by building a DB schema because it gives a good feeling about the whole project scope, and raises important potential questions to the client that should be asked as early as possible cause, otherwise, they would lead to a lot of code changes later.

Initial DB Schema from Client

The client is quite technical but not with Laravel. So they provide us with the list of tables and columns, and our task is to convert it to Laravel Migrations/Models.

This is how the client described what we need to create.


  • ID
  • Email
  • Password
  • Roles (M2M relationship)


  • ID
  • Name


  • ID
  • Is Public (bool)
  • Slug
  • Name
  • Description
  • Number of days
  • Number of nights (virtual, computed by numberOfDays - 1)


  • ID
  • Travel ID (M2O relationship)
  • Name
  • Starting date
  • Ending date
  • Price (integer, see below)

Also, here are a few points from the client's description that we need to keep in mind:

  • We use UUIDs as primary keys instead of incremental IDs;
  • Tours prices are integer multiplied by 100: for example, €999 euro will be 99900, but, when returned to Frontends, they will be formatted (99900 / 100).

With all that in mind, let's begin the creation process.

Obviously, we start with installing a new Laravel project, which I will call travelapi:

laravel new travelapi
cd travelapi

And now the database.

Role: Model and Migration

Laravel, by default, comes with a users DB table and Model, so we don't need to change anything there.

We need to create the table for roles and a pivot table between users and roles.

php artisan make:model Role -m

My personal preference is to create Eloquent Models with migrations right away. There are more options and classes to create, like Factories, Seeders, and more, but we will make them when we need them.

Migration file:

Schema::create('roles', function (Blueprint $table) {

Notice: yes, I remember the client asked for UUIDs. We will refactor all keys to the UUIDs at the end of this lesson.


class Role extends Model
use HasFactory;
protected $fillable = ['name'];

Notice about $fillable and Mass Assignment

Personally, I have a habit of filling in the $fillable array immediately when the migration is created. This is needed so we would be able to...

This lesson is only for Premium Members.
Want to access all lessons of this course?

You also get:

  • 59 courses (1057 lessons, 42 h 44 min total)
  • Premium tutorials
  • Access to repositories
  • Private Discord