Module 1: Setting Up Laravel 11 and SQL
Overview
In this module, we will set up the development environment for our Flight Reservation System using Laravel 11 and an SQL database. We will install necessary applications, set up the Laravel project, and connect it to GitHub. Additionally, we will document our setup process and create an initial project schema/diagram to outline the architecture of our system.
Step-by-Step Guide
1. Installation of Applications and Dependencies
1.1 Install PHP and Composer
- PHP: Download and install PHP from the official website.
- Composer: Download and install Composer from the official website.
Verify the installations:
php -v
composer -v
1.2 Install Laravel Installer
Install Laravel globally using Composer:
composer global require laravel/installer
Make sure to add Composer’s global vendor bin directory to your PATH:
export PATH="$HOME/.composer/vendor/bin:$PATH"
Verify the installation:
laravel -v
git --version
1.4 Install MySQL
- MySQL: Download and install MySQL from the official website.
Verify the installation:
mysql --version
2. Setting Up the Laravel Project
2.1 Create a New Laravel Project
Create a new Laravel project using the Laravel installer:
laravel new flight-reservation-system
cd flight-reservation-system
2.2 Configure the Database
Edit the .env
file in the root of your project to configure your database connection:
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=flight_reservation_system
DB_USERNAME=root
DB_PASSWORD=password
Create the database in MySQL:
CREATE DATABASE flight_reservation_system;
2.3 Install Laravel Sanctum
We will use Laravel Sanctum for API authentication:
composer require laravel/sanctum
Publish the Sanctum configuration:
php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
Run the Sanctum migrations:
php artisan migrate
3. Setting Up GitHub
3.1 Initialize a Git Repository
Initialize a git repository in your project directory:
git init
Create a .gitignore
file to exclude vendor
and other unnecessary files:
echo "/vendor/" >> .gitignore
3.2 Connect to GitHub
Create a repository on GitHub and follow the instructions to link it to your local project:
git remote add origin <repository_url>
git add .
git commit -m "Initial commit"
git push -u origin master
3.3 Connect VS Code to GitHub
- Open your project in VS Code.
- Use the Source Control panel to commit changes and push them to GitHub.
4. Initial Project Schema/Diagram
We will create a high-level diagram to outline the architecture of our flight reservation system. This includes entities like flights, passengers, airlines, airports, bookings, and payments, and their relationships.
(This is a placeholder for an actual diagram you would create)
5. Documentation
Documenting our setup process is crucial for future reference and onboarding new developers.
Create a README.md
file in the root directory of your project:
touch README.md
Add the following content to README.md
:
# Flight Reservation System
## Overview
This project is a backend system for managing airline reservations. It includes features such as flight management, passenger management, airline management, airport management, booking management, and payment processing.
## Installation
1. Install PHP and Composer from [PHP](https://www.php.net/downloads) and [Composer](https://getcomposer.org/download/).
2. Install MySQL from [MySQL](https://dev.mysql.com/downloads/installer/).
3. Clone the repository:
```sh
git clone <repository_url>
Install dependencies:
composer install
Configure the database in the .env
file:
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=flight_reservation_system
DB_USERNAME=root
DB_PASSWORD=password
Run the migrations:
php artisan migrate
The command php artisan migrate
is used in the context of Laravel, a popular PHP framework for web development. This command is used to run all of your outstanding migrations. Migrations are like version control for your database, allowing a team to define and share the application’s database schema definition.
Here’s a step-by-step explanation of what this command does:
Command Invocation:
php
: This is the PHP interpreter.artisan
: This is the command-line interface included with Laravel. It’s used to perform various tasks.migrate
: This is the specific command you’re running via Artisan.
What It Does:
- When you run
php artisan migrate
, Laravel will look for all migration files in thedatabase/migrations
directory. - Each migration file contains two main methods:
up
anddown
. Theup
method is used to apply changes to the database (like creating a table or adding a column), and thedown
method is used to reverse those changes. - Laravel keeps track of which migrations have already been run using a database table called
migrations
. This table records the migrations that have been applied.
- When you run
Execution:
- Laravel executes the
up
method for any migration that hasn’t been run yet. - If any of the migrations fail (e.g., due to a syntax error in the migration file or a conflict with the current database schema), the process will stop, and an error message will be displayed
- Laravel executes the
Start the development server:
php artisan serve
Project Structure
app/
: Application core files.config/
: Configuration files.database/
: Database migrations and seeds.public/
: Publicly accessible files.resources/
: Views, languages, and other resources.routes/
: API routes.storage/
: Storage files.tests/
: Test files.vendor/
: Composer dependencies.
Contributing
- Fork the repository.
- Create a new branch (
git checkout -b feature-branch
). - Make your changes.
- Commit your changes (
git commit -am 'Add new feature'
). - Push to the branch (
git push origin feature-branch
). - Create a new Pull Request.
When you run this command, Laravel will start the development server at http://localhost:8000
Module 2: Database Design
Overview
In this module, we will design the database schema for our Flight Reservation System using Laravel 11 and an SQL database. This design will cover all necessary entities, their attributes, and the relationships between them. We will create the migration files to set up the database schema.
Entity Descriptions and Relationships
Based on the provided features, we will create the following entities:
- Flight
- Passenger
- Airline
- Airport
- Booking
- Payment
Database Schema
1. Create Migrations
We will create migration files to define the schema for each table.
1.1 Create Flight Table Migration
php artisan make:migration create_flights_table
The php artisan make:migration create_flights_table
command is used in Laravel to create a new migration file for creating a new table in your database. The command generates a new migration file with the necessary boilerplate code for defining the table’s schema.
database/migrations/yyyy_mm_dd_hhmmss_create_flights_table.php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateFlightsTable extends Migration
{
public function up()
{
Schema::create('flights', function (Blueprint $table) {
$table->id();
$table->string('flight_number')->unique();
$table->timestamp('departure_datetime');
$table->timestamp('arrival_datetime');
$table->string('origin_airport_code');
$table->string('destination_airport_code');
$table->unsignedInteger('available_seats');
$table->foreignId('airline_id')->constrained()->onDelete('cascade');
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists('flights');
}
}
Breakdown of the Migration File
Imports:
use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema;
- These imports bring in the necessary classes for creating migrations and defining the schema.
Migration Class Definition:
class CreateFlightsTable extends Migration { // Migration methods will go here }
Up Method:
- This method is used to define the schema of the
flights
table and will be executed when you run the migration.
public function up() { Schema::create('flights', function (Blueprint $table) { $table->id(); $table->string('flight_number')->unique(); $table->timestamp('departure_datetime'); $table->timestamp('arrival_datetime'); $table->string('origin_airport_code'); $table->string('destination_airport_code'); $table->unsignedInteger('available_seats'); $table->foreignId('airline_id')->constrained()->onDelete('cascade'); $table->timestamps(); }); }
Schema::create('flights', function (Blueprint $table) {...});
: Creates theflights
table with the defined columns.$table->id();
: Adds an auto-incrementing primary key column namedid
.$table->string('flight_number')->unique();
: Adds aflight_number
column that must be unique.$table->timestamp('departure_datetime');
: Adds adeparture_datetime
column for storing departure timestamps.$table->timestamp('arrival_datetime');
: Adds anarrival_datetime
column for storing arrival timestamps.$table->string('origin_airport_code');
: Adds anorigin_airport_code
column for storing the code of the origin airport.$table->string('destination_airport_code');
: Adds adestination_airport_code
column for storing the code of the destination airport.$table->unsignedInteger('available_seats');
: Adds anavailable_seats
column for storing the number of available seats, which is an unsigned integer.$table->foreignId('airline_id')->constrained()->onDelete('cascade');
: Adds a foreign key columnairline_id
that references theid
column on theairlines
table, and sets the foreign key constraint to cascade on delete.$table->timestamps();
: Addscreated_at
andupdated_at
timestamp columns.
- This method is used to define the schema of the
Down Method:
- This method is used to reverse the changes made in the
up
method. It will be executed when you roll back the migration.
public function down() { Schema::dropIfExists('flights'); }
Schema::dropIfExists('flights');
: Drops theflights
table if it exists.
- This method is used to reverse the changes made in the
Running the Migration
To run this migration and create the flights
table in your database, execute the following command in your terminal:
php artisan migrate
This command will look for all migration files that haven’t been run yet and execute the up
method to create the necessary tables and columns in your database.
1.2 Create Passenger Table Migration
php artisan make:migration create_passengers_table
To create a new migration for a passengers
table in Laravel, you can use the php artisan make:migration
command. Here’s how you can do it:
Open Terminal:
- Open your terminal or command prompt.
Navigate to Your Laravel Project Directory:
- Use the
cd
command to navigate to the root directory of your Laravel project. For example:cd path/to/your/laravel/project
- Use the
Run the Migration Command:
- Execute the following command to create a new migration file for creating the
passengers
table:php artisan make:migration create_passengers_table
- Execute the following command to create a new migration file for creating the
Check the Generated Migration File:
- After running the command, you will see a new migration file in the
database/migrations
directory. The file name will have a timestamp prefix and will look something like this:2024_06_27_123456_create_passengers_table.php
.
- After running the command, you will see a new migration file in the
database/migrations/yyyy_mm_dd_hhmmss_create_passengers_table.php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreatePassengersTable extends Migration
{
public function up()
{
Schema::create('passengers', function (Blueprint $table) {
$table->id();
$table->string('first_name');
$table->string('last_name');
$table->string('email')->unique();
$table->string('passport_number')->unique();
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists('passengers');
}
}
This migration defines the schema for the passengers
table with columns for first name, last name, email, and passport number. Below is a complete explanation of the migration file you provided.
Explanation of the Migration File
Imports:
use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema;
- These imports bring in the necessary classes for creating migrations and defining the schema.
Migration Class Definition:
class CreatePassengersTable extends Migration { // Migration methods will go here }
Up Method:
- This method is used to define the schema of the
passengers
table and will be executed when you run the migration.
public function up() { Schema::create('passengers', function (Blueprint $table) { $table->id(); $table->string('first_name'); $table->string('last_name'); $table->string('email')->unique(); $table->string('passport_number')->unique(); $table->timestamps(); }); }
Schema::create('passengers', function (Blueprint $table) {...});
: Creates thepassengers
table with the defined columns.$table->id();
: Adds an auto-incrementing primary key column namedid
.$table->string('first_name');
: Adds afirst_name
column for storing the passenger’s first name.$table->string('last_name');
: Adds alast_name
column for storing the passenger’s last name.$table->string('email')->unique();
: Adds anemail
column that must be unique.$table->string('passport_number')->unique();
: Adds apassport_number
column that must be unique.$table->timestamps();
: Addscreated_at
andupdated_at
timestamp columns.
- This method is used to define the schema of the
Down Method:
- This method is used to reverse the changes made in the
up
method. It will be executed when you roll back the migration.
public function down() { Schema::dropIfExists('passengers'); }
Schema::dropIfExists('passengers');
: Drops thepassengers
table if it exists.
- This method is used to reverse the changes made in the
Summary
Your migration file sets up a passengers
table with the following columns:
id
: An auto-incrementing primary key.first_name
: A string column for the passenger’s first name.last_name
: A string column for the passenger’s last name.email
: A string column for the passenger’s email, which must be unique.passport_number
: A string column for the passenger’s passport number, which must be unique.timestamps
: Two timestamp columns,created_at
andupdated_at
.
Running the Migration
To run this migration and create the passengers
table in your database, execute the following command in your terminal:
php artisan migrate
This command will look for all migration files that haven’t been run yet and execute the up
method to create the necessary tables and columns in your database.
1.3 Create Airline Table Migration
php artisan make:migration create_airlines_table
To create a new migration for an airlines
table in Laravel, you can use the php artisan make:migration
command. Here’s how you can do it:
Open Terminal:
- Open your terminal or command prompt.
Navigate to Your Laravel Project Directory:
- Use the
cd
command to navigate to the root directory of your Laravel project. For example:cd path/to/your/laravel/project
- Use the
Run the Migration Command:
- Execute the following command to create a new migration file for creating the
airlines
table:php artisan make:migration create_airlines_table
- Execute the following command to create a new migration file for creating the
Check the Generated Migration File:
- After running the command, you will see a new migration file in the
database/migrations
directory. The file name will have a timestamp prefix and will look something like this:2024_06_27_123456_create_airlines_table.php
.
- After running the command, you will see a new migration file in the
database/migrations/yyyy_mm_dd_hhmmss_create_airlines_table.php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateAirlinesTable extends Migration
{
public function up()
{
Schema::create('airlines', function (Blueprint $table) {
$table->id();
$table->string('name')->unique();
$table->string('contact_number');
$table->string('operating_region');
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists('airlines');
}
}
Here’s a complete explanation of the migration file :
Explanation of the Migration File
Imports:
use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema;
- These imports bring in the necessary classes for creating migrations and defining the schema.
Migration Class Definition:
class CreateAirlinesTable extends Migration { // Migration methods will go here }
Up Method:
- This method is used to define the schema of the
airlines
table and will be executed when you run the migration.
public function up() { Schema::create('airlines', function (Blueprint $table) { $table->id(); $table->string('name')->unique(); $table->string('contact_number'); $table->string('operating_region'); $table->timestamps(); }); }
Schema::create('airlines', function (Blueprint $table) {...});
: Creates theairlines
table with the defined columns.$table->id();
: Adds an auto-incrementing primary key column namedid
.$table->string('name')->unique();
: Adds aname
column that must be unique.$table->string('contact_number');
: Adds acontact_number
column for storing the airline’s contact number.$table->string('operating_region');
: Adds anoperating_region
column for storing the airline’s operating region.$table->timestamps();
: Addscreated_at
andupdated_at
timestamp columns.
- This method is used to define the schema of the
Down Method:
- This method is used to reverse the changes made in the
up
method. It will be executed when you roll back the migration.
public function down() { Schema::dropIfExists('airlines'); }
Schema::dropIfExists('airlines');
: Drops theairlines
table if it exists.
- This method is used to reverse the changes made in the
Running the Migration
To run this migration and create the airlines
table in your database, execute the following command in your terminal:
php artisan migrate
This command will look for all migration files that haven’t been run yet and execute the up
method to create the necessary tables and columns in your database.
Your migration file sets up an airlines
table with the following columns:
id
: An auto-incrementing primary key.name
: A string column for the airline’s name, which must be unique.contact_number
: A string column for the airline’s contact number.operating_region
: A string column for the airline’s operating region.timestamps
: Two timestamp columns,created_at
andupdated_at
.
Running php artisan migrate
will create this table in your database, enabling you to store and manage airline information.
1.4 Create Airport Table Migration
php artisan make:migration create_airports_table
Execute the following command to create a new migration file for creating the airports
table:
database/migrations/yyyy_mm_dd_hhmmss_create_airports_table.php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateAirportsTable extends Migration
{
public function up()
{
Schema::create('airports', function (Blueprint $table) {
$table->string('code')->primary();
$table->string('name');
$table->string('location');
$table->text('facilities')->nullable();
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists('airports');
}
}
This migration defines the schema for the airports
table with fields for the airport code, name, location, and facilities.
Here’s a detailed explanation of the migration file you provided:
Explanation of the Migration File
Imports:
use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema;
- These imports bring in the necessary classes for creating migrations and defining the schema.
Migration Class Definition:
phpclass CreateAirportsTable extends Migration { // Migration methods will go here }
- This method is used to define the schema of the
airports
table and will be executed when you run the migration.Up Method:
- This method is used to define the schema of the
public function up() { Schema::create('airports', function (Blueprint $table) { $table->string('code')->primary(); $table->string('name'); $table->string('location'); $table->text('facilities')->nullable(); $table->timestamps(); }); }
Schema::create('airports', function (Blueprint $table) {...});
: Creates theairports
table with the defined columns.$table->string('code')->primary();
: Adds acode
column as the primary key.$table->string('name');
: Adds aname
column for storing the airport’s name.$table->string('location');
: Adds alocation
column for storing the airport’s location.$table->text('facilities')->nullable();
: Adds afacilities
column for storing information about the facilities at the airport, which can be null.$table->timestamps();
: Addscreated_at
andupdated_at
timestamp columns.
Down Method:
- This method is used to reverse the changes made in the
up
method. It will be executed when you roll back the migration.
public function down() { Schema::dropIfExists('airports'); }
Schema::dropIfExists('airports');
: Drops theairports
table if it exists.
- This method is used to reverse the changes made in the
Running the Migration
To run this migration and create the airports
table in your database, execute the following command in your terminal:
php artisan migrate
This command will look for all migration files that haven’t been run yet and execute the up
method to create the necessary tables and columns in your database.
Your migration file sets up an airports
table with the following columns:
code
: A string column that serves as the primary key.name
: A string column for the airport’s name.location
: A string column for the airport’s location.facilities
: A text column for the airport’s facilities, which can be null.timestamps
: Two timestamp columns,created_at
andupdated_at
.
Running php artisan migrate
will create this table in your database, enabling you to store and manage airport information.
1.5 Create Booking Table Migration
php artisan make:migration create_bookings_table
database/migrations/yyyy_mm_dd_hhmmss_create_bookings_table.php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateBookingsTable extends Migration
{
public function up()
{
Schema::create('bookings', function (Blueprint $table) {
$table->id();
$table->foreignId('flight_id')->constrained()->onDelete('cascade');
$table->foreignId('passenger_id')->constrained()->onDelete('cascade');
$table->string('payment_status');
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists('bookings');
}
}
This migration defines the schema for the bookings
table with fields for the booking ID, flight ID, passenger ID, and payment status. It also sets up foreign key constraints for the flight_id
and passenger_id
columns.
Here’s a detailed explanation of the migration file you provided:
Explanation of the Migration File
Imports:
use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema;
- These imports bring in the necessary classes for creating migrations and defining the schema.
Migration Class Definition:
class CreateBookingsTable extends Migration { // Migration methods will go here }
Up Method:
- This method is used to define the schema of the
bookings
table and will be executed when you run the migration.
public function up() { Schema::create('bookings', function (Blueprint $table) { $table->id(); $table->foreignId('flight_id')->constrained()->onDelete('cascade'); $table->foreignId('passenger_id')->constrained()->onDelete('cascade'); $table->string('payment_status'); $table->timestamps(); }); }
Schema::create('bookings', function (Blueprint $table) {...});
: Creates thebookings
table with the defined columns.$table->id();
: Adds an auto-incrementing primary key column namedid
.$table->foreignId('flight_id')->constrained()->onDelete('cascade');
: Adds aflight_id
column, sets it up as a foreign key that references theid
column on theflights
table, and specifies that if a flight is deleted, the related bookings should also be deleted.$table->foreignId('passenger_id')->constrained()->onDelete('cascade');
: Adds apassenger_id
column, sets it up as a foreign key that references theid
column on thepassengers
table, and specifies that if a passenger is deleted, the related bookings should also be deleted.$table->string('payment_status');
: Adds apayment_status
column for storing the payment status of the booking.$table->timestamps();
: Addscreated_at
andupdated_at
timestamp columns.
- This method is used to define the schema of the
Down Method:
- This method is used to reverse the changes made in the
up
method. It will be executed when you roll back the migration.
public function down() { Schema::dropIfExists('bookings'); }
Schema::dropIfExists('bookings');
: Drops thebookings
table if it exists.
- This method is used to reverse the changes made in the
Running the Migration
To run this migration and create the bookings
table in your database, execute the following command in your terminal:
php artisan migrate
This command will look for all migration files that haven’t been run yet and execute the up
method to create the necessary tables and columns in your database.
1.6 Create Payment Table Migration
php artisan make:migration create_payments_table
database/migrations/yyyy_mm_dd_hhmmss_create_payments_table.php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreatePaymentsTable extends Migration
{
public function up()
{
Schema::create('payments', function (Blueprint $table) {
$table->id();
$table->foreignId('booking_id')->constrained()->onDelete('cascade');
$table->string('payment_method');
$table->decimal('amount', 10, 2);
$table->timestamp('transaction_datetime');
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists('payments');
}
}
This migration defines the schema for the payments
table with fields for the payment ID, booking ID, payment method, amount, and transaction datetime. It also sets up a foreign key constraint for the booking_id
column.
Here’s a detailed explanation of the migration file you provided:
Explanation of the Migration File
Imports:
use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema;
- These imports bring in the necessary classes for creating migrations and defining the schema.
Migration Class Definition:
class CreatePaymentsTable extends Migration { // Migration methods will go here }
Up Method:
- This method is used to define the schema of the
payments
table and will be executed when you run the migration.
public function up() { Schema::create('payments', function (Blueprint $table) { $table->id(); $table->foreignId('booking_id')->constrained()->onDelete('cascade'); $table->string('payment_method'); $table->decimal('amount', 10, 2); $table->timestamp('transaction_datetime'); $table->timestamps(); }); }
Schema::create('payments', function (Blueprint $table) {...});
: Creates thepayments
table with the defined columns.$table->id();
: Adds an auto-incrementing primary key column namedid
.$table->foreignId('booking_id')->constrained()->onDelete('cascade');
: Adds abooking_id
column, sets it up as a foreign key that references theid
column on thebookings
table, and specifies that if a booking is deleted, the related payments should also be deleted.$table->string('payment_method');
: Adds apayment_method
column for storing the payment method used.$table->decimal('amount', 10, 2);
: Adds anamount
column for storing the payment amount, with a precision of 10 and a scale of 2.$table->timestamp('transaction_datetime');
: Adds atransaction_datetime
column for storing the date and time of the transaction.$table->timestamps();
: Addscreated_at
andupdated_at
timestamp columns.
- This method is used to define the schema of the
Down Method:
- This method is used to reverse the changes made in the
up
method. It will be executed when you roll back the migration.
public function down() { Schema::dropIfExists('payments'); }
Schema::dropIfExists('payments');
: Drops thepayments
table if it exists.
- This method is used to reverse the changes made in the
Running the Migration
To run this migration and create the payments
table in your database, execute the following command in your terminal:
php artisan migrate
This command will look for all migration files that haven’t been run yet and execute the up
method to create the necessary tables and columns in your database.
Relationships
Flight – Booking Relationship
- One-to-Many: One flight can have multiple bookings, but each booking corresponds to only one flight.
Passenger – Booking Relationship
- One-to-Many: One passenger can make multiple bookings, but each booking corresponds to only one passenger.
Flight – Airport Relationship
- Many-to-One: Multiple flights can depart from or arrive at the same airport, but each flight has only one origin and one destination airport.
Airline – Flight Relationship
- One-to-Many: One airline can operate multiple flights, but each flight is operated by only one airline.
Payment – Booking Relationship
- One-to-One: Each payment corresponds to only one booking, and each booking can have only one payment.
Run Migrations
Run the migrations to create the database schema:
php artisan migrate
In this module, we defined the database schema for the Flight Reservation System using Laravel and an SQL database. We created migration files for each entity and defined the relationships between them. Running the migrations set up our database schema, which will allow us to efficiently manage our data. In the next module, we will focus on implementing user authentication and authorization.
Module 3: User Authentication and Authorization
Overview
In this module, we will implement user registration and login functionalities with error validation, full authorization, and authentication using Laravel Sanctum. Additionally, we will create middleware for error handling and protecting routes.
Step-by-Step Guide
1. Install Laravel Sanctum
If you haven’t already installed Laravel Sanctum, run the following command:
composer require laravel/sanctum
Publish the Sanctum configuration:
php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
Run the Sanctum migrations:
php artisan migrate
2. Configure Sanctum
In the config/sanctum.php
file, configure the necessary settings. Ensure you have set the expiration time for tokens if required.
Update the api
middleware group in app/Http/Kernel.php
to include Sanctum middleware:
'api' => [
\Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
'throttle:api',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
In Laravel, middleware are filters that handle HTTP requests entering your application. They can be used to perform various tasks before a request is processed by your application. The code snippet you provided is part of a configuration array, typically found in the app/Http/Kernel.php
file, which defines the middleware stack for different groups of routes.
- EnsureFrontendRequestsAreStateful: Ensures that frontend requests are treated as stateful, important for SPAs using Laravel Sanctum.
- throttle
- SubstituteBindings: Automatically resolves route parameters to their corresponding Eloquent models, simplifying route handling.
These middleware are applied to the api
middleware group, which means they will be executed for all routes defined within the api.php
routes file. This setup ensures that API requests are properly authenticated, rate-limited, and have their parameters automatically resolved.
3. Create User Model and Migration
We will use Laravel’s default User model for authentication. Make sure the User model is configured to use Sanctum.
app/Models/User.php
<?php
namespace App\Models;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
class User extends Authenticatable
{
use HasApiTokens, HasFactory, Notifiable;
/**
* The attributes that are mass assignable.
*
* @var array<int, string>
*/
protected $fillable = [
'name',
'email',
'password',
];
/**
* The attributes that should be hidden for serialization.
*
* @var array<int, string>
*/
protected $hidden = [
'password',
'remember_token',
];
/**
* The attributes that should be cast.
*
* @var array<string, string>
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
}
The User
model in Laravel is an Eloquent model that represents the users of your application. It extends Authenticatable
, making it compatible with Laravel’s authentication system. This model uses several traits to provide additional functionality and configurations.
Here’s a detailed breakdown of the User
model:
Namespaces and Imports
namespace App\Models;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
- namespace App\Models;: Defines the namespace for this model, placing it in the
App\Models
directory. - use Illuminate\Contracts\Auth\MustVerifyEmail;: Import for email verification (not used directly in this model but can be implemented).
- use Illuminate\Database\Eloquent\Factories\HasFactory;: Import for factory support to easily create model instances for testing and seeding.
- use Illuminate\Foundation\Auth\User as Authenticatable;: Import for the base user authentication model provided by Laravel.
- use Illuminate\Notifications\Notifiable;: Import for notification support, allowing the model to send notifications.
- use Laravel\Sanctum\HasApiTokens;: Import for API token support provided by Laravel Sanctum.
Class Definition and Traits
class User extends Authenticatable
{
use HasApiTokens, HasFactory, Notifiable;
- class User extends Authenticatable: Defines the
User
class, which extendsAuthenticatable
, making it a part of Laravel’s authentication system. - use HasApiTokens, HasFactory, Notifiable;: Uses traits to add functionality:
- HasApiTokens: Adds API token authentication capabilities via Laravel Sanctum.
- HasFactory: Adds factory methods for creating instances of the model.
- Notifiable: Adds methods to send notifications.
Mass Assignment
/**
* The attributes that are mass assignable.
*
* @var array<int, string>
*/
protected $fillable = [
'name',
'email',
'password',
];
- $fillable: An array of attributes that can be mass assigned. This means these attributes can be set in bulk operations like
create
orupdate
.
Hidden Attributes
/**
* The attributes that should be hidden for serialization.
*
* @var array<int, string>
*/
protected $hidden = [
'password',
'remember_token',
];
- $hidden: An array of attributes that should be hidden when the model is converted to an array or JSON. This typically includes sensitive information like
password
andremember_token
.
Casts
/**
* The attributes that should be cast.
*
* @var array<string, string>
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
- $casts: An array that specifies how attributes should be cast when the model is accessed or mutated. For example, casting
email_verified_at
to adatetime
ensures it is treated as a Carbon instance.
The User
model is a central part of Laravel’s authentication system. It uses various traits to handle API tokens, notifications, and factory creation. The $fillable
property defines which attributes can be mass-assigned, while $hidden
specifies which attributes should be hidden when serializing the model. The $casts
property is used to cast attributes to specific data types, ensuring proper handling of those attributes.
This setup allows the User
model to integrate seamlessly with Laravel’s features, providing a robust foundation for user management in your application.
4. Create Authentication Controllers
We will create controllers to handle user registration, login, and logout.
app/Http/Controllers/Auth/RegisterController.php
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
class RegisterController extends Controller
{
public function register(Request $request)
{
$validator = Validator::make($request->all(), [
'name' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users',
'password' => 'required|string|min:8|confirmed',
]);
if ($validator->fails()) {
return response()->json($validator->errors(), 422);
}
$user = User::create([
'name' => $request->name,
'email' => $request->email,
'password' => Hash::make($request->password),
]);
$token = $user->createToken('auth_token')->plainTextToken;
return response()->json([
'access_token' => $token,
'token_type' => 'Bearer',
]);
}
}
The RegisterController
is an authentication controller responsible for handling user registration in a Laravel application. It validates the registration request, creates a new user, and generates an authentication token using Laravel Sanctum.
Here’s a detailed breakdown of the RegisterController
:
Namespaces and Imports
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
- namespace App\Http\Controllers\Auth;: Defines the namespace for this controller, placing it in the
App\Http\Controllers\Auth
directory. - use App\Http\Controllers\Controller;: Imports the base controller class.
- use App\Models\User;: Imports the
User
model. - use Illuminate\Http\Request;: Imports the
Request
class to handle HTTP requests. - use Illuminate\Support\Facades\Hash;: Imports the
Hash
facade for hashing passwords. - use Illuminate\Support\Facades\Validator;: Imports the
Validator
facade for validating input data.
Class Definition
class RegisterController extends Controller
{
// Controller methods will go here
}
- class RegisterController extends Controller: Defines the
RegisterController
class, which extends Laravel’s baseController
class.
Register Method
public function register(Request $request)
{
$validator = Validator::make($request->all(), [
'name' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users',
'password' => 'required|string|min:8|confirmed',
]);
if ($validator->fails()) {
return response()->json($validator->errors(), 422);
}
$user = User::create([
'name' => $request->name,
'email' => $request->email,
'password' => Hash::make($request->password),
]);
$token = $user->createToken('auth_token')->plainTextToken;
return response()->json([
'access_token' => $token,
'token_type' => 'Bearer',
]);
}
Validation
$validator = Validator::make($request->all(), […]);: Creates a new validator instance for the incoming request data.
- ‘name’ => ‘required|string|max:255’: Validates that the
name
field is required, is a string, and has a maximum length of 255 characters. - ’email’ => ‘required|string|email|max:255|unique
email
field is required, is a string, is a valid email address, has a maximum length of 255 characters, and is unique in theusers
table. - ‘password’ => ‘required|string|min:8|confirmed’: Validates that the
password
field is required, is a string, has a minimum length of 8 characters, and is confirmed (meaning apassword_confirmation
field must match).
- ‘name’ => ‘required|string|max:255’: Validates that the
if ($validator->fails()) { … }: Checks if the validation fails.
- return response()->json($validator->errors(), 422);: Returns a JSON response with the validation errors and a 422 Unprocessable Entity status code.
User Creation
- $user = User::create([…]);: Creates a new user record in the database with the provided data.
- ‘name’ => $request->name: Sets the user’s name.
- ’email’ => $request->email: Sets the user’s email.
- ‘password’ => Hash::make($request->password): Hashes the password and sets it.
Token Generation
- $token = $user->createToken(‘auth_token’)->plainTextToken;: Generates a new personal access token for the user using Laravel Sanctum and retrieves the plain text version of the token.
Response
- return response()->json([…]);: Returns a JSON response with the generated access token and token type (Bearer).
The RegisterController
handles user registration by:
- Validating the incoming registration request to ensure all required fields are present and valid.
- Creating a new user in the database with the provided information.
- Hashing the user’s password before storing it.
- Generating an authentication token for the newly created user using Laravel Sanctum.
- Returning a JSON response containing the access token and token type.
This setup ensures that users can register, have their information securely stored, and receive a token for subsequent authenticated requests.
app/Http/Controllers/Auth/LoginController.php
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Auth;
class LoginController extends Controller
{
public function login(Request $request)
{
$request->validate([
'email' => 'required|string|email',
'password' => 'required|string',
]);
$user = User::where('email', $request->email)->first();
if (!$user || !Hash::check($request->password, $user->password)) {
return response()->json(['message' => 'Invalid login details'], 401);
}
$token = $user->createToken('auth_token')->plainTextToken;
return response()->json([
'access_token' => $token,
'token_type' => 'Bearer',
]);
}
public function logout(Request $request)
{
$request->user()->currentAccessToken()->delete();
return response()->json(['message' => 'Logged out successfully']);
}
}
The LoginController
is responsible for handling user login and logout functionalities in a Laravel application. This controller verifies the user’s credentials, generates an authentication token for successful logins, and deletes the token for logouts.
Here’s a detailed breakdown of the LoginController
:
Namespaces and Imports
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Auth;
- namespace App\Http\Controllers\Auth;: Defines the namespace for this controller, placing it in the
App\Http\Controllers\Auth
directory. - use App\Http\Controllers\Controller;: Imports the base controller class.
- use App\Models\User;: Imports the
User
model. - use Illuminate\Http\Request;: Imports the
Request
class to handle HTTP requests. - use Illuminate\Support\Facades\Hash;: Imports the
Hash
facade for verifying passwords. - use Illuminate\Support\Facades\Auth;: Imports the
Auth
facade (not used in this example but commonly needed in authentication).
Class Definition
class LoginController extends Controller
{
// Controller methods will go here
}
- class LoginController extends Controller: Defines the
LoginController
class, which extends Laravel’s baseController
class.
Login Method
public function login(Request $request)
{
$request->validate([
'email' => 'required|string|email',
'password' => 'required|string',
]);
$user = User::where('email', $request->email)->first();
if (!$user || !Hash::check($request->password, $user->password)) {
return response()->json(['message' => 'Invalid login details'], 401);
}
$token = $user->createToken('auth_token')->plainTextToken;
return response()->json([
'access_token' => $token,
'token_type' => 'Bearer',
]);
}
Request Validation
- $request->validate([…]);: Validates the incoming login request to ensure the
email
andpassword
fields are present and correctly formatted.- ’email’ => ‘required|string|email’: Validates that the
email
field is required, is a string, and is a valid email address. - ‘password’ => ‘required|string’: Validates that the
password
field is required and is a string.
- ’email’ => ‘required|string|email’: Validates that the
User Verification
- $user = User::where(’email’, $request->email)->first();: Retrieves the first user record with the provided email address.
- if (!$user || !Hash::check($request->password, $user->password)) { … }: Checks if the user exists and if the provided password matches the stored hashed password.
- Hash::check($request->password, $user->password): Uses the
Hash
facade to verify the provided password against the hashed password stored in the database. - return response()->json([‘message’ => ‘Invalid login details’], 401);: Returns a JSON response with an error message and a 401 Unauthorized status code if the credentials are invalid.
- Hash::check($request->password, $user->password): Uses the
Token Generation
- $token = $user->createToken(‘auth_token’)->plainTextToken;: Generates a new personal access token for the user using Laravel Sanctum and retrieves the plain text version of the token.
Response
- return response()->json([…]);: Returns a JSON response with the generated access token and token type (Bearer).
Logout Method
public function logout(Request $request)
{
$request->user()->currentAccessToken()->delete();
return response()->json(['message' => 'Logged out successfully']);
}
Token Deletion
- $request->user()->currentAccessToken()->delete();: Retrieves the currently authenticated user and deletes their current access token.
Response
- return response()->json([‘message’ => ‘Logged out successfully’]);: Returns a JSON response indicating the user has been logged out successfully.
The LoginController
handles user login and logout by:
Login:
- Validates the login request to ensure all required fields are present and correctly formatted.
- Retrieves the user by email and verifies the password.
- Generates an authentication token using Laravel Sanctum for successful logins.
- Returns a JSON response containing the access token and token type.
Logout:
- Deletes the currently authenticated user’s access token.
- Returns a JSON response indicating successful logout.
This setup ensures that users can log in to the application securely, receive a token for authenticated requests, and log out, invalidating their token to prevent further access.
5. Create Authentication Routes
We will define the routes for user registration, login, and logout.
routes/api.php
use App\Http\Controllers\Auth\RegisterController;
use App\Http\Controllers\Auth\LoginController;
Route::post('register', [RegisterController::class, 'register']);
Route::post('login', [LoginController::class, 'login']);
Route::middleware('auth:sanctum')->post('logout', [LoginController::class, 'logout']);
The provided code defines routes for user registration, login, and logout in a Laravel application. The routes utilize the RegisterController
and LoginController
to handle the respective actions. Here’s a detailed breakdown of what each part does:
Import Controllers
use App\Http\Controllers\Auth\RegisterController;
use App\Http\Controllers\Auth\LoginController;
- use App\Http\Controllers\Auth\RegisterController;: Imports the
RegisterController
class. - use App\Http\Controllers\Auth\LoginController;: Imports the
LoginController
class.
Define Routes
Route::post('register', [RegisterController::class, 'register']);
Route::post('login', [LoginController::class, 'login']);
Route::middleware('auth:sanctum')->post('logout', [LoginController::class, 'logout']);
Register Route
Route::post('register', [RegisterController::class, 'register']);
- Route::post(‘register’, …);: Defines a POST route for user registration.
- [RegisterController::class, ‘register’]: Specifies that the
register
method in theRegisterController
will handle this route.
Login Route
Route::post('login', [LoginController::class, 'login']);
- Route::post(‘login’, …);: Defines a POST route for user login.
- [LoginController::class, ‘login’]: Specifies that the
login
method in theLoginController
will handle this route.
Logout Route
Route::middleware('auth:sanctum')->post('logout', [LoginController::class, 'logout']);
- Route::middleware(‘auth
- middleware(‘auth
auth:sanctum
middleware to this route, ensuring that only authenticated users can access it.
- middleware(‘auth
- [LoginController::class, ‘logout’]: Specifies that the
logout
method in theLoginController
will handle this route.
The defined routes handle user registration, login, and logout. They use the appropriate controllers and methods to perform these actions. The auth:sanctum
middleware ensures that the logout route can only be accessed by authenticated users, providing a secure way to manage user sessions.
6. Protecting Routes
To protect the routes, we will use Sanctum’s middleware. Ensure the routes that need protection are within the auth:sanctum
middleware group.
routes/api.php (Updated)
Route::middleware('auth:sanctum')->group(function () {
// Protected routes go here
Route::get('/user', function (Request $request) {
return $request->user();
});
Route::resource('flights', FlightController::class);
Route::resource('passengers', PassengerController::class);
Route::resource('airlines', AirlineController::class);
Route::resource('airports', AirportController::class);
Route::resource('bookings', BookingController::class);
Route::resource('payments', PaymentController::class);
});
The provided code defines a group of routes that are protected by the auth:sanctum
middleware. This means that only authenticated users with valid Sanctum tokens can access these routes. The group includes routes for retrieving user information and resources for managing flights, passengers, airlines, airports, bookings, and payments.
Detailed Breakdown
Middleware Group
Route::middleware('auth:sanctum')->group(function () {
// Protected routes go here
});
- Route::middleware(‘auth
auth:sanctum
middleware. This middleware ensures that only authenticated users with valid Sanctum tokens can access these routes.
Get Authenticated User
Route::get('/user', function (Request $request) {
return $request->user();
});
- Route::get(‘/user’, function (Request $request) {…});: Defines a GET route to retrieve the authenticated user’s information.
- $request->user();: Returns the currently authenticated user.
Resource Routes
Route::resource('flights', FlightController::class);
Route::resource('passengers', PassengerController::class);
Route::resource('airlines', AirlineController::class);
Route::resource('airports', AirportController::class);
Route::resource('bookings', BookingController::class);
Route::resource('payments', PaymentController::class);
- Route::resource(‘flights’, FlightController::class);: Generates RESTful routes for the
FlightController
. - Route::resource(‘passengers’, PassengerController::class);: Generates RESTful routes for the
PassengerController
. - Route::resource(‘airlines’, AirlineController::class);: Generates RESTful routes for the
AirlineController
. - Route::resource(‘airports’, AirportController::class);: Generates RESTful routes for the
AirportController
. - Route::resource(‘bookings’, BookingController::class);: Generates RESTful routes for the
BookingController
. - Route::resource(‘payments’, PaymentController::class);: Generates RESTful routes for the
PaymentController
.
RESTful Resource Routes
Using Route::resource
creates the following routes for each resource:
- index:
GET /resource
– Display a listing of the resource. - create:
GET /resource/create
– Show the form for creating a new resource. - store:
POST /resource
– Store a newly created resource in storage. - show:
GET /resource/{id}
– Display the specified resource. - edit:
GET /resource/{id}/edit
– Show the form for editing the specified resource. - update:
PUT/PATCH /resource/{id}
– Update the specified resource in storage. - destroy:
DELETE /resource/{id}
– Remove the specified resource from storage.
- The routes are protected by the
auth:sanctum
middleware, ensuring only authenticated users with valid Sanctum tokens can access them. - The
/user
route returns the authenticated user’s information. - Resource routes for flights, passengers, airlines, airports, bookings, and payments are created using
Route::resource
, which generates standard RESTful routes for these resources.
This setup provides a secure and organized way to manage various resources in your Laravel application.
In this module, we implemented user authentication and authorization using Laravel Sanctum. We created controllers for user registration, login, and logout, and protected our routes using Sanctum middleware. In the next module, we will focus on creating models for the various entities such as flights, passengers, airlines, airports, bookings, and payments.
Module 4: Models Creation
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut elit tellus, luctus nec ullamcorper mattis, pulvinar dapibus leo.
Overview
In this module, we will create Eloquent models for the various entities in our Flight Reservation System, including flights, passengers, airlines, airports, bookings, and payments. These models will help us interact with our SQL database and manage the data for our application.
Step-by-Step Guide
1. Flight Model
The Flight model will store information about individual flights, including flight numbers, departure and arrival times, origin and destination airports, available seats, and the airline operating the flight.
app/Models/Flight.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Flight extends Model
{
use HasFactory;
protected $fillable = [
'flight_number',
'departure_datetime',
'arrival_datetime',
'origin_airport_code',
'destination_airport_code',
'available_seats',
'airline_id'
];
public function airline()
{
return $this->belongsTo(Airline::class);
}
public function bookings()
{
return $this->hasMany(Booking::class);
}
public function originAirport()
{
return $this->belongsTo(Airport::class, 'origin_airport_code', 'code');
}
public function destinationAirport()
{
return $this->belongsTo(Airport::class, 'destination_airport_code', 'code');
}
}
The Flight
model in Laravel represents a flight in your application. It extends the Model
class, uses the HasFactory
trait for factory support, defines fillable attributes for mass assignment, and establishes relationships with other models such as Airline
, Booking
, and Airport
.
Namespaces and Imports
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
- namespace App\Models;: Defines the namespace for this model, placing it in the
App\Models
directory. - use Illuminate\Database\Eloquent\Factories\HasFactory;: Imports the
HasFactory
trait to enable factory support. - use Illuminate\Database\Eloquent\Model;: Imports the base
Model
class provided by Laravel.
Class Definition and Traits
class Flight extends Model
{
use HasFactory;
}
- class Flight extends Model: Defines the
Flight
class, which extends theModel
class, making it an Eloquent model. - use HasFactory;: Uses the
HasFactory
trait to enable factory support for the model.
Fillable Attributes
protected $fillable = [
'flight_number',
'departure_datetime',
'arrival_datetime',
'origin_airport_code',
'destination_airport_code',
'available_seats',
'airline_id'
];
- $fillable: An array of attributes that are mass assignable. This means these attributes can be set in bulk operations like
create
orupdate
.- ‘flight_number’: The flight number.
- ‘departure_datetime’: The departure date and time.
- ‘arrival_datetime’: The arrival date and time.
- ‘origin_airport_code’: The code of the origin airport.
- ‘destination_airport_code’: The code of the destination airport.
- ‘available_seats’: The number of available seats.
- ‘airline_id’: The ID of the associated airline.
Relationships
Airline Relationship
public function airline()
{
return $this->belongsTo(Airline::class);
}
- airline(): Defines a one-to-many inverse relationship with the
Airline
model.- belongsTo(Airline::class): Indicates that each flight belongs to one airline.
Bookings Relationship
public function bookings()
{
return $this->hasMany(Booking::class);
}
- bookings(): Defines a one-to-many relationship with the
Booking
model.- hasMany(Booking::class): Indicates that a flight can have many bookings.
Origin Airport Relationship
public function originAirport()
{
return $this->belongsTo(Airport::class, 'origin_airport_code', 'code');
}
- originAirport(): Defines a one-to-many inverse relationship with the
Airport
model for the origin airport.- belongsTo(Airport::class, ‘origin_airport_code’, ‘code’): Indicates that each flight belongs to one origin airport, linking the
origin_airport_code
column in theflights
table to thecode
column in theairports
table.
- belongsTo(Airport::class, ‘origin_airport_code’, ‘code’): Indicates that each flight belongs to one origin airport, linking the
Destination Airport Relationship
public function destinationAirport()
{
return $this->belongsTo(Airport::class, 'destination_airport_code', 'code');
}
- destinationAirport(): Defines a one-to-many inverse relationship with the
Airport
model for the destination airport.- belongsTo(Airport::class, ‘destination_airport_code’, ‘code’): Indicates that each flight belongs to one destination airport, linking the
destination_airport_code
column in theflights
table to thecode
column in theairports
table.
- belongsTo(Airport::class, ‘destination_airport_code’, ‘code’): Indicates that each flight belongs to one destination airport, linking the
The Flight
model represents a flight in your application and includes:
- fillable attributes: Defines the attributes that can be mass assigned.
- relationships: Defines relationships with the
Airline
,Booking
, andAirport
models.
This setup allows you to easily manage and interact with flight data, including associated airlines, bookings, and airports, using Laravel’s Eloquent ORM.
2. Passenger Model
The Passenger model will store details about passengers, including their names, contact information, and passport numbers.
app/Models/Passenger.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Passenger extends Model
{
use HasFactory;
protected $fillable = [
'first_name',
'last_name',
'email',
'passport_number'
];
public function bookings()
{
return $this->hasMany(Booking::class);
}
}
The Passenger
model in Laravel represents a passenger in your application. It extends the Model
class, uses the HasFactory
trait for factory support, defines fillable attributes for mass assignment, and establishes a relationship with the Booking
model.
Detailed Breakdown of the Passenger
Model
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Passenger extends Model
{
use HasFactory;
protected $fillable = [
‘first_name’,
‘last_name’,
’email’,
‘passport_number’
];
public function bookings()
{
return $this->hasMany(Booking::class);
}
}
Namespaces and Imports
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
- namespace App\Models;: Defines the namespace for this model, placing it in the
App\Models
directory. - use Illuminate\Database\Eloquent\Factories\HasFactory;: Imports the
HasFactory
trait to enable factory support. - use Illuminate\Database\Eloquent\Model;: Imports the base
Model
class provided by Laravel.
Class Definition and Traits
class Passenger extends Model
{
use HasFactory;
}
- class Passenger extends Model: Defines the
Passenger
class, which extends theModel
class, making it an Eloquent model. - use HasFactory;: Uses the
HasFactory
trait to enable factory support for the model.
Fillable Attributes
protected $fillable = [
'first_name',
'last_name',
'email',
'passport_number'
];
- $fillable: An array of attributes that are mass assignable. This means these attributes can be set in bulk operations like
create
orupdate
.- ‘first_name’: The first name of the passenger.
- ‘last_name’: The last name of the passenger.
- ’email’: The email address of the passenger.
- ‘passport_number’: The passport number of the passenger.
Relationships
Bookings Relationship
public function bookings()
{
return $this->hasMany(Booking::class);
}
- bookings(): Defines a one-to-many relationship with the
Booking
model.- hasMany(Booking::class): Indicates that a passenger can have many bookings.
Summary
The Passenger
model represents a passenger in your application and includes:
- fillable attributes: Defines the attributes that can be mass assigned.
- relationships: Defines a relationship with the
Booking
model.
This setup allows you to easily manage and interact with passenger data, including associated bookings, using Laravel’s Eloquent ORM.
3. Airline Model
The Airline model will store information about airlines, including their names, contact details, and operating regions.
app/Models/Airline.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Airline extends Model
{
use HasFactory;
protected $fillable = [
'name',
'contact_number',
'operating_region'
];
public function flights()
{
return $this->hasMany(Flight::class);
}
}
The Airline
model in Laravel represents an airline in your application. It extends the Model
class, uses the HasFactory
trait for factory support, defines fillable attributes for mass assignment, and establishes a relationship with the Flight
model.
Detailed Breakdown of the Airline
Model
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Airline extends Model
{
use HasFactory;
protected $fillable = [
'name',
'contact_number',
'operating_region'
];
public function flights()
{
return $this->hasMany(Flight::class);
}
}
Namespaces and Imports
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
- namespace App\Models;: Defines the namespace for this model, placing it in the
App\Models
directory. - use Illuminate\Database\Eloquent\Factories\HasFactory;: Imports the
HasFactory
trait to enable factory support. - use Illuminate\Database\Eloquent\Model;: Imports the base
Model
class provided by Laravel.
Class Definition and Traits
class Airline extends Model
{
use HasFactory;
}
- class Airline extends Model: Defines the
Airline
class, which extends theModel
class, making it an Eloquent model. - use HasFactory;: Uses the
HasFactory
trait to enable factory support for the model.
Fillable Attributes
protected $fillable = [
'name',
'contact_number',
'operating_region'
];
- $fillable: An array of attributes that are mass assignable. This means these attributes can be set in bulk operations like
create
orupdate
.- ‘name’: The name of the airline.
- ‘contact_number’: The contact number of the airline.
- ‘operating_region’: The operating region of the airline.
Relationships
Flights Relationship
public function flights()
{
return $this->hasMany(Flight::class);
}
- flights(): Defines a one-to-many relationship with the
Flight
model.- hasMany(Flight::class): Indicates that an airline can have many flights.
Summary
The Airline
model represents an airline in your application and includes:
- fillable attributes: Defines the attributes that can be mass assigned.
- relationships: Defines a relationship with the
Flight
model.
This setup allows you to easily manage and interact with airline data, including associated flights, using Laravel’s Eloquent ORM.
4. Airport Model
The Airport model will store information about airports, including their codes, names, locations, and available facilities.
app/Models/Airport.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Airport extends Model
{
use HasFactory;
protected $primaryKey = 'code';
public $incrementing = false;
protected $keyType = 'string';
protected $fillable = [
'code',
'name',
'location',
'facilities'
];
public function originFlights()
{
return $this->hasMany(Flight::class, 'origin_airport_code', 'code');
}
public function destinationFlights()
{
return $this->hasMany(Flight::class, 'destination_airport_code', 'code');
}
}
The Airport
model in Laravel represents an airport in your application. This model uses a non-incrementing string primary key (code
), includes fillable attributes for mass assignment, and defines relationships with the Flight
model for origin and destination flights.
Namespaces and Imports
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
- namespace App\Models;: Defines the namespace for this model, placing it in the
App\Models
directory. - use Illuminate\Database\Eloquent\Factories\HasFactory;: Imports the
HasFactory
trait to enable factory support. - use Illuminate\Database\Eloquent\Model;: Imports the base
Model
class provided by Laravel.
Class Definition and Traits
class Airport extends Model
{
use HasFactory;
}
- class Airport extends Model: Defines the
Airport
class, which extends theModel
class, making it an Eloquent model. - use HasFactory;: Uses the
HasFactory
trait to enable factory support for the model.
Primary Key Configuration
protected $primaryKey = 'code';
public $incrementing = false;
protected $keyType = 'string';
- protected $primaryKey = ‘code’;: Sets the primary key to the
code
column. - public $incrementing = false;: Disables auto-incrementing for the primary key.
- protected $keyType = ‘string’;: Sets the key type to
string
.
Fillable Attributes
protected $fillable = [
'code',
'name',
'location',
'facilities'
];
- $fillable: An array of attributes that are mass assignable. This means these attributes can be set in bulk operations like
create
orupdate
.- ‘code’: The code of the airport.
- ‘name’: The name of the airport.
- ‘location’: The location of the airport.
- ‘facilities’: The facilities available at the airport.
Relationships
Origin Flights Relationship
public function originFlights()
{
return $this->hasMany(Flight::class, 'origin_airport_code', 'code');
}
- originFlights(): Defines a one-to-many relationship with the
Flight
model for flights originating from this airport.- hasMany(Flight::class, ‘origin_airport_code’, ‘code’): Indicates that an airport can have many flights that originate from it, linking the
origin_airport_code
column in theflights
table to thecode
column in theairports
table.
- hasMany(Flight::class, ‘origin_airport_code’, ‘code’): Indicates that an airport can have many flights that originate from it, linking the
Destination Flights Relationship
public function destinationFlights()
{
return $this->hasMany(Flight::class, 'destination_airport_code', 'code');
}
- destinationFlights(): Defines a one-to-many relationship with the
Flight
model for flights arriving at this airport.- hasMany(Flight::class, ‘destination_airport_code’, ‘code’): Indicates that an airport can have many flights that arrive at it, linking the
destination_airport_code
column in theflights
table to thecode
column in theairports
table.
- hasMany(Flight::class, ‘destination_airport_code’, ‘code’): Indicates that an airport can have many flights that arrive at it, linking the
Summary
The Airport
model represents an airport in your application and includes:
- Primary Key Configuration: Uses
code
as a non-incrementing string primary key. - fillable attributes: Defines the attributes that can be mass assigned.
- relationships: Defines relationships with the
Flight
model for origin and destination flights.
This setup allows you to easily manage and interact with airport data, including associated flights, using Laravel’s Eloquent ORM.
5. Booking Model
The Booking model will handle flight reservations, including the flight details, passenger information, and payment status.
app/Models/Booking.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Booking extends Model
{
use HasFactory;
protected $fillable = [
'flight_id',
'passenger_id',
'payment_status'
];
public function flight()
{
return $this->belongsTo(Flight::class);
}
public function passenger()
{
return $this->belongsTo(Passenger::class);
}
public function payment()
{
return $this->hasOne(Payment::class);
}
}
The Booking
model in Laravel represents a booking in your application. It extends the Model
class, uses the HasFactory
trait for factory support, defines fillable attributes for mass assignment, and establishes relationships with the Flight
, Passenger
, and Payment
models.
Namespaces and Imports
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
- namespace App\Models;: Defines the namespace for this model, placing it in the
App\Models
directory. - use Illuminate\Database\Eloquent\Factories\HasFactory;: Imports the
HasFactory
trait to enable factory support. - use Illuminate\Database\Eloquent\Model;: Imports the base
Model
class provided by Laravel.
Class Definition and Traits
class Booking extends Model
{
use HasFactory;
}
- class Booking extends Model: Defines the
Booking
class, which extends theModel
class, making it an Eloquent model. - use HasFactory;: Uses the
HasFactory
trait to enable factory support for the model.
Fillable Attributes
protected $fillable = [
'flight_id',
'passenger_id',
'payment_status'
];
- $fillable: An array of attributes that are mass assignable. This means these attributes can be set in bulk operations like
create
orupdate
.- ‘flight_id’: The ID of the associated flight.
- ‘passenger_id’: The ID of the associated passenger.
- ‘payment_status’: The payment status of the booking.
Relationships
Flight Relationship
public function flight()
{
return $this->belongsTo(Flight::class);
}
- flight(): Defines a one-to-many inverse relationship with the
Flight
model.- belongsTo(Flight::class): Indicates that each booking belongs to one flight.
Passenger Relationship
public function passenger()
{
return $this->belongsTo(Passenger::class);
}
- passenger(): Defines a one-to-many inverse relationship with the
Passenger
model.- belongsTo(Passenger::class): Indicates that each booking belongs to one passenger.
Payment Relationship
public function payment()
{
return $this->hasOne(Payment::class);
}
- payment(): Defines a one-to-one relationship with the
Payment
model.- hasOne(Payment::class): Indicates that each booking can have one payment associated with it.
Summary
The Booking
model represents a booking in your application and includes:
- fillable attributes: Defines the attributes that can be mass assigned.
- relationships: Defines relationships with the
Flight
,Passenger
, andPayment
models.
This setup allows you to easily manage and interact with booking data, including associated flights, passengers, and payments, using Laravel’s Eloquent ORM.
6. Payment Model
The Payment model will store information about payments made for flight bookings, including transaction details and amounts.
app/Models/Payment.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Payment extends Model
{
use HasFactory;
protected $fillable = [
'booking_id',
'payment_method',
'amount',
'transaction_datetime'
];
public function booking()
{
return $this->belongsTo(Booking::class);
}
}
The Payment
model in Laravel represents a payment in your application. It extends the Model
class, uses the HasFactory
trait for factory support, defines fillable attributes for mass assignment, and establishes a relationship with the Booking
model.
Namespaces and Imports
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
- namespace App\Models;: Defines the namespace for this model, placing it in the
App\Models
directory. - use Illuminate\Database\Eloquent\Factories\HasFactory;: Imports the
HasFactory
trait to enable factory support. - use Illuminate\Database\Eloquent\Model;: Imports the base
Model
class provided by Laravel.
Class Definition and Traits
class Payment extends Model
{
use HasFactory;
}
- class Payment extends Model: Defines the
Payment
class, which extends theModel
class, making it an Eloquent model. - use HasFactory;: Uses the
HasFactory
trait to enable factory support for the model.
Fillable Attributes
protected $fillable = [
'booking_id',
'payment_method',
'amount',
'transaction_datetime'
];
- $fillable: An array of attributes that are mass assignable. This means these attributes can be set in bulk operations like
create
orupdate
.- ‘booking_id’: The ID of the associated booking.
- ‘payment_method’: The method of payment (e.g., credit card, PayPal).
- ‘amount’: The amount of the payment.
- ‘transaction_datetime’: The date and time of the transaction.
Relationships
Booking Relationship
public function booking()
{
return $this->belongsTo(Booking::class);
}
- booking(): Defines a one-to-many inverse relationship with the
Booking
model.- belongsTo(Booking::class): Indicates that each payment belongs to one booking.
Summary
The Payment
model represents a payment in your application and includes:
- fillable attributes: Defines the attributes that can be mass assigned.
- relationships: Defines a relationship with the
Booking
model.
This setup allows you to easily manage and interact with payment data, including the associated bookings, using Laravel’s Eloquent ORM.
In this module, we created Eloquent models for the key entities in our Flight Reservation System. These models include Flight, Passenger, Airline, Airport, Booking, and Payment. Each model defines the schema for its respective entity and sets up the necessary relationships between them. In the next module, we will implement controllers and routes to manage these entities and handle various operations in our application.
Module 5: Controllers and Routes Creation
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut elit tellus, luctus nec ullamcorper mattis, pulvinar dapibus leo.
Overview
In this module, we will create controllers and routes for managing the various entities in our Flight Reservation System, including flights, passengers, airlines, airports, bookings, and payments. The controllers will handle the business logic, while the routes will define the endpoints for our API.
Step-by-Step Guide
1. Flight Controller and Routes
app/Http/Controllers/FlightController.php
<?php
namespace App\Http\Controllers;
use App\Models\Flight;
use Illuminate\Http\Request;
class FlightController extends Controller
{
public function index(Request $request)
{
$query = Flight::query();
// Filtering
if ($request->has('origin')) {
$query->where('origin_airport_code', $request->origin);
}
if ($request->has('destination')) {
$query->where('destination_airport_code', $request->destination);
}
if ($request->has('date')) {
$query->whereDate('departure_datetime', $request->date);
}
// Pagination
$flights = $query->paginate(10);
return response()->json($flights);
}
public function show($id)
{
$flight = Flight::find($id);
if (!$flight) {
return response()->json(['message' => 'Flight not found'], 404);
}
return response()->json($flight);
}
public function store(Request $request)
{
$request->validate([
'flight_number' => 'required|string|unique:flights',
'departure_datetime' => 'required|date',
'arrival_datetime' => 'required|date',
'origin_airport_code' => 'required|string|exists:airports,code',
'destination_airport_code' => 'required|string|exists:airports,code',
'available_seats' => 'required|integer',
'airline_id' => 'required|exists:airlines,id',
]);
$flight = Flight::create($request->all());
return response()->json($flight, 201);
}
public function update(Request $request, $id)
{
$flight = Flight::find($id);
if (!$flight) {
return response()->json(['message' => 'Flight not found'], 404);
}
$request->validate([
'flight_number' => 'string|unique:flights,flight_number,' . $id,
'departure_datetime' => 'date',
'arrival_datetime' => 'date',
'origin_airport_code' => 'string|exists:airports,code',
'destination_airport_code' => 'string|exists:airports,code',
'available_seats' => 'integer',
'airline_id' => 'exists:airlines,id',
]);
$flight->update($request->all());
return response()->json($flight);
}
public function destroy($id)
{
$flight = Flight::find($id);
if (!$flight) {
return response()->json(['message' => 'Flight not found'], 404);
}
$flight->delete();
return response()->json(['message' => 'Flight deleted successfully']);
}
}
The FlightController
handles various actions related to the Flight
model, such as listing flights, showing a specific flight, creating a new flight, updating an existing flight, and deleting a flight. Here’s a detailed breakdown of the FlightController
:
Namespaces and Imports
namespace App\Http\Controllers;
use App\Models\Flight;
use Illuminate\Http\Request;
- namespace App\Http\Controllers;: Defines the namespace for this controller, placing it in the
App\Http\Controllers
directory. - use App\Models\Flight;: Imports the
Flight
model. - use Illuminate\Http\Request;: Imports the
Request
class to handle HTTP requests.
Class Definition
class FlightController extends Controller
{
// Controller methods will go here
}
- class FlightController extends Controller: Defines the
FlightController
class, which extends Laravel’s baseController
class.
Index Method
public function index(Request $request)
{
$query = Flight::query();
// Filtering
if ($request->has('origin')) {
$query->where('origin_airport_code', $request->origin);
}
if ($request->has('destination')) {
$query->where('destination_airport_code', $request->destination);
}
if ($request->has('date')) {
$query->whereDate('departure_datetime', $request->date);
}
// Pagination
$flights = $query->paginate(10);
return response()->json($flights);
}
- Filtering: Checks if the request has certain filters (origin, destination, date) and applies them to the query.
- Pagination: Uses the
paginate
method to paginate the results, returning 10 flights per page. - Response: Returns the paginated flights as a JSON response.
Show Method
public function show($id)
{
$flight = Flight::find($id);
if (!$flight) {
return response()->json(['message' => 'Flight not found'], 404);
}
return response()->json($flight);
}
- find($id): Retrieves the flight with the given ID.
- Response: Returns the flight as a JSON response. If the flight is not found, it returns a 404 error.
Store Method
public function store(Request $request)
{
$request->validate([
'flight_number' => 'required|string|unique:flights',
'departure_datetime' => 'required|date',
'arrival_datetime' => 'required|date',
'origin_airport_code' => 'required|string|exists:airports,code',
'destination_airport_code' => 'required|string|exists:airports,code',
'available_seats' => 'required|integer',
'airline_id' => 'required|exists:airlines,id',
]);
$flight = Flight::create($request->all());
return response()->json($flight, 201);
}
- Validation: Validates the incoming request data to ensure all required fields are present and correctly formatted.
- Create Flight: Creates a new flight record using the validated data.
- Response: Returns the newly created flight as a JSON response with a 201 status code.
Update Method
public function update(Request $request, $id)
{
$flight = Flight::find($id);
if (!$flight) {
return response()->json(['message' => 'Flight not found'], 404);
}
$request->validate([
'flight_number' => 'string|unique:flights,flight_number,' . $id,
'departure_datetime' => 'date',
'arrival_datetime' => 'date',
'origin_airport_code' => 'string|exists:airports,code',
'destination_airport_code' => 'string|exists:airports,code',
'available_seats' => 'integer',
'airline_id' => 'exists:airlines,id',
]);
$flight->update($request->all());
return response()->json($flight);
}
- Find Flight: Retrieves the flight with the given ID.
- Validation: Validates the incoming request data for the fields that can be updated.
- Update Flight: Updates the flight record with the validated data.
- Response: Returns the updated flight as a JSON response.
Destroy Method
public function destroy($id)
{
$flight = Flight::find($id);
if (!$flight) {
return response()->json(['message' => 'Flight not found'], 404);
}
$flight->delete();
return response()->json(['message' => 'Flight deleted successfully']);
}
- Find Flight: Retrieves the flight with the given ID.
- Delete Flight: Deletes the flight record.
- Response: Returns a success message as a JSON response
routes/api.php
use App\Http\Controllers\FlightController;
Route::resource('flights', FlightController::class)->middleware('auth:sanctum');
FlightController
applies the auth:sanctum
middleware to all routes within this resource. This ensures that all the routes related to flights are protected and can only be accessed by authenticated users with a valid Sanctum token.
Here’s the complete code snippet with some additional context:
Adding the Route in routes/api.php
Make sure you add this route definition in your routes/api.php
file:
use App\Http\Controllers\FlightController;
use Illuminate\Support\Facades\Route;
// Apply Sanctum authentication middleware to the flights resource route
Route::resource('flights', FlightController::class)->middleware('auth:sanctum');
Explanation
- use App\Http\Controllers\FlightController;: Imports the
FlightController
class so that it can be referenced in the route definition. - Route::resource(‘flights’, FlightController::class): Creates a resource route for the
FlightController
, automatically generating all the CRUD routes (index, create, store, show, edit, update, destroy) for theFlight
model. - ->middleware(‘auth
auth:sanctum
middleware to all the routes within theflights
resource route. This ensures that only authenticated users can access these routes.
Generated Routes
The Route::resource
method generates the following routes:
- GET /flights: index method, lists all flights.
- GET /flights/create: create method, shows a form to create a new flight (typically not used in API-only applications).
- POST /flights: store method, saves a new flight.
- GET /flights/{flight}: show method, shows a single flight.
- GET /flights/{flight}/edit: edit method, shows a form to edit an existing flight (typically not used in API-only applications).
- PUT/PATCH /flights/{flight}: update method, updates an existing flight.
- DELETE /flights/{flight}: destroy method, deletes a flight.
2. Passenger Controller and Routes
app/Http/Controllers/PassengerController.php
<?php
namespace App\Http\Controllers;
use App\Models\Passenger;
use Illuminate\Http\Request;
class PassengerController extends Controller
{
public function index(Request $request)
{
$query = Passenger::query();
// Filtering and Search
if ($request->has('search')) {
$search = $request->search;
$query->where(function ($q) use ($search) {
$q->where('first_name', 'LIKE', "%{$search}%")
->orWhere('last_name', 'LIKE', "%{$search}%")
->orWhere('email', 'LIKE', "%{$search}%");
});
}
// Pagination
$passengers = $query->paginate(10);
return response()->json($passengers);
}
public function show($id)
{
$passenger = Passenger::find($id);
if (!$passenger) {
return response()->json(['message' => 'Passenger not found'], 404);
}
return response()->json($passenger);
}
public function store(Request $request)
{
$request->validate([
'first_name' => 'required|string',
'last_name' => 'required|string',
'email' => 'required|string|email|unique:passengers',
'passport_number' => 'required|string|unique:passengers',
]);
$passenger = Passenger::create($request->all());
return response()->json($passenger, 201);
}
public function update(Request $request, $id)
{
$passenger = Passenger::find($id);
if (!$passenger) {
return response()->json(['message' => 'Passenger not found'], 404);
}
$request->validate([
'first_name' => 'string',
'last_name' => 'string',
'email' => 'string|email|unique:passengers,email,' . $id,
'passport_number' => 'string|unique:passengers,passport_number,' . $id,
]);
$passenger->update($request->all());
return response()->json($passenger);
}
public function destroy($id)
{
$passenger = Passenger::find($id);
if (!$passenger) {
return response()->json(['message' => 'Passenger not found'], 404);
}
$passenger->delete();
return response()->json(['message' => 'Passenger deleted successfully']);
}
}
The PassengerController
handles various actions related to the Passenger
model, such as listing passengers, showing a specific passenger, creating a new passenger, updating an existing passenger, and deleting a passenger. Here’s a detailed breakdown of the PassengerController
:
Namespaces and Imports
namespace App\Http\Controllers;
use App\Models\Passenger;
use Illuminate\Http\Request;
- namespace App\Http\Controllers;: Defines the namespace for this controller, placing it in the
App\Http\Controllers
directory. - use App\Models\Passenger;: Imports the
Passenger
model. - use Illuminate\Http\Request;: Imports the
Request
class to handle HTTP requests.
Class Definition
class PassengerController extends Controller
{
// Controller methods will go here
}
- class PassengerController extends Controller: Defines the
PassengerController
class, which extends Laravel’s baseController
class.
Index Method
public function index(Request $request)
{
$query = Passenger::query();
// Filtering and Search
if ($request->has('search')) {
$search = $request->search;
$query->where(function ($q) use ($search) {
$q->where('first_name', 'LIKE', "%{$search}%")
->orWhere('last_name', 'LIKE', "%{$search}%")
->orWhere('email', 'LIKE', "%{$search}%");
});
}
// Pagination
$passengers = $query->paginate(10);
return response()->json($passengers);
}
- Filtering and Search: Checks if the request has a
search
parameter and applies the search query to filter passengers byfirst_name
,last_name
, oremail
. - Pagination: Uses the
paginate
method to paginate the results, returning 10 passengers per page. - Response: Returns the paginated passengers as a JSON response.
Show Method
public function show($id)
{
$passenger = Passenger::find($id);
if (!$passenger) {
return response()->json(['message' => 'Passenger not found'], 404);
}
return response()->json($passenger);
}
- find($id): Retrieves the passenger with the given ID.
- Response: Returns the passenger as a JSON response. If the passenger is not found, it returns a 404 error.
Store Method
public function store(Request $request)
{
$request->validate([
'first_name' => 'required|string',
'last_name' => 'required|string',
'email' => 'required|string|email|unique:passengers',
'passport_number' => 'required|string|unique:passengers',
]);
$passenger = Passenger::create($request->all());
return response()->json($passenger, 201);
}
- Validation: Validates the incoming request data to ensure all required fields are present and correctly formatted.
- Create Passenger: Creates a new passenger record using the validated data.
- Response: Returns the newly created passenger as a JSON response with a 201 status code.
Update Method
public function update(Request $request, $id)
{
$passenger = Passenger::find($id);
if (!$passenger) {
return response()->json(['message' => 'Passenger not found'], 404);
}
$request->validate([
'first_name' => 'string',
'last_name' => 'string',
'email' => 'string|email|unique:passengers,email,' . $id,
'passport_number' => 'string|unique:passengers,passport_number,' . $id,
]);
$passenger->update($request->all());
return response()->json($passenger);
}
- Find Passenger: Retrieves the passenger with the given ID.
- Validation: Validates the incoming request data for the fields that can be updated.
- Update Passenger: Updates the passenger record with the validated data.
- Response: Returns the updated passenger as a JSON response.
Destroy Method
public function destroy($id)
{
$passenger = Passenger::find($id);
if (!$passenger) {
return response()->json(['message' => 'Passenger not found'], 404);
}
$passenger->delete();
return response()->json(['message' => 'Passenger deleted successfully']);
}
- Find Passenger: Retrieves the passenger with the given ID.
- Delete Passenger: Deletes the passenger record.
- Response: Returns a success message as a JSON response.
routes/api.php
use App\Http\Controllers\PassengerController;
Route::resource('passengers', PassengerController::class)->middleware('auth:sanctum');
3. Airline Controller and Routes
app/Http/Controllers/AirlineController.php
<?php
namespace App\Http\Controllers;
use App\Models\Airline;
use Illuminate\Http\Request;
class AirlineController extends Controller
{
public function index(Request $request)
{
$query = Airline::query();
// Filtering and Search
if ($request->has('search')) {
$search = $request->search;
$query->where('name', 'LIKE', "%{$search}%");
}
if ($request->has('region')) {
$query->where('operating_region', $request->region);
}
// Pagination
$airlines = $query->paginate(10);
return response()->json($airlines);
}
public function show($id)
{
$airline = Airline::find($id);
if (!$airline) {
return response()->json(['message' => 'Airline not found'], 404);
}
return response()->json($airline);
}
public function store(Request $request)
{
$request->validate([
'name' => 'required|string|unique:airlines',
'contact_number' => 'required|string',
'operating_region' => 'required|string',
]);
$airline = Airline::create($request->all());
return response()->json($airline, 201);
}
public function update(Request $request, $id)
{
$airline = Airline::find($id);
if (!$airline) {
return response()->json(['message' => 'Airline not found'], 404);
}
$request->validate([
'name' => 'string|unique:airlines,name,' . $id,
'contact_number' => 'string',
'operating_region' => 'string',
]);
$airline->update($request->all());
return response()->json($airline);
}
public function destroy($id)
{
$airline = Airline::find($id);
if (!$airline) {
return response()->json(['message' => 'Airline not found'], 404);
}
$airline->delete();
return response()->json(['message' => 'Airline deleted successfully']);
}
}
The AirlineController
handles various actions related to the Airline
model, such as listing airlines, showing a specific airline, creating a new airline, updating an existing airline, and deleting an airline. Here’s a detailed breakdown of the AirlineController
:
Namespaces and Imports
namespace App\Http\Controllers;
use App\Models\Airline;
use Illuminate\Http\Request;
- namespace App\Http\Controllers;: Defines the namespace for this controller, placing it in the
App\Http\Controllers
directory. - use App\Models\Airline;: Imports the
Airline
model. - use Illuminate\Http\Request;: Imports the
Request
class to handle HTTP requests.
Class Definition
class AirlineController extends Controller
{
// Controller methods will go here
}
- class AirlineController extends Controller: Defines the
AirlineController
class, which extends Laravel’s baseController
class.
Index Method
public function index(Request $request)
{
$query = Airline::query();
// Filtering and Search
if ($request->has('search')) {
$search = $request->search;
$query->where('name', 'LIKE', "%{$search}%");
}
if ($request->has('region')) {
$query->where('operating_region', $request->region);
}
// Pagination
$airlines = $query->paginate(10);
return response()->json($airlines);
}
- Filtering and Search: Checks if the request has
search
andregion
parameters and applies filters to the query.- Search: Filters airlines by name using a LIKE query.
- Region: Filters airlines by operating region.
- Pagination: Uses the
paginate
method to paginate the results, returning 10 airlines per page. - Response: Returns the paginated airlines as a JSON response.
Show Method
public function show($id)
{
$airline = Airline::find($id);
if (!$airline) {
return response()->json(['message' => 'Airline not found'], 404);
}
return response()->json($airline);
}
- find($id): Retrieves the airline with the given ID.
- Response: Returns the airline as a JSON response. If the airline is not found, it returns a 404 error.
Store Method
public function store(Request $request)
{
$request->validate([
'name' => 'required|string|unique:airlines',
'contact_number' => 'required|string',
'operating_region' => 'required|string',
]);
$airline = Airline::create($request->all());
return response()->json($airline, 201);
}
- Validation: Validates the incoming request data to ensure all required fields are present and correctly formatted.
- Create Airline: Creates a new airline record using the validated data.
- Response: Returns the newly created airline as a JSON response with a 201 status code.
Update Method
public function update(Request $request, $id)
{
$airline = Airline::find($id);
if (!$airline) {
return response()->json(['message' => 'Airline not found'], 404);
}
$request->validate([
'name' => 'string|unique:airlines,name,' . $id,
'contact_number' => 'string',
'operating_region' => 'string',
]);
$airline->update($request->all());
return response()->json($airline);
}
- Find Airline: Retrieves the airline with the given ID.
- Validation: Validates the incoming request data for the fields that can be updated.
- Update Airline: Updates the airline record with the validated data.
- Response: Returns the updated airline as a JSON response.
Destroy Method
public function destroy($id)
{
$airline = Airline::find($id);
if (!$airline) {
return response()->json(['message' => 'Airline not found'], 404);
}
$airline->delete();
return response()->json(['message' => 'Airline deleted successfully']);
}
- Find Airline: Retrieves the airline with the given ID.
- Delete Airline: Deletes the airline record.
- Response: Returns a success message as a JSON response.
routes/api.php
use App\Http\Controllers\AirlineController;
Route::resource('airlines', AirlineController::class)->middleware('auth:sanctum');
4. Airport Controller and Routes
app/Http/Controllers/AirportController.php
<?php
namespace App\Http\Controllers;
use App\Models\Airport;
use Illuminate\Http\Request;
class AirportController extends Controller
{
public function index(Request $request)
{
$query = Airport::query();
// Filtering and Search
if ($request->has('search')) {
$search = $request->search;
$query->where('code', 'LIKE', "%{$search}%")
->orWhere('name', 'LIKE', "%{$search}%")
->orWhere('location', 'LIKE', "%{$search}%");
}
if ($request->has('location')) {
$query->where('location', 'LIKE', "%{$request->location}%");
}
// Pagination
$airports = $query->paginate(10);
return response()->json($airports);
}
public function show($code)
{
$airport = Airport::find($code);
if (!$airport) {
return response()->json(['message' => 'Airport not found'], 404);
}
return response()->json($airport);
}
public function store(Request $request)
{
$request->validate([
'code' => 'required|string|unique:airports',
'name' => 'required|string',
'location' => 'required|string',
'facilities' => 'nullable|string',
]);
$airport = Airport::create($request->all());
return response()->json($airport, 201);
}
public function update(Request $request, $code)
{
$airport = Airport::find($code);
if (!$airport) {
return response()->json(['message' => 'Airport not found'], 404);
}
$request->validate([
'code' => 'string|unique:airports,code,' . $code,
'name' => 'string',
'location' => 'string',
'facilities' => 'nullable|string',
]);
$airport->update($request->all());
return response()->json($airport);
}
public function destroy($code)
{
$airport = Airport::find($code);
if (!$airport) {
return response()->json(['message' => 'Airport not found'], 404);
}
$airport->delete();
return response()->json(['message' => 'Airport deleted successfully']);
}
}
The AirportController
handles various actions related to the Airport
model, such as listing airports, showing a specific airport, creating a new airport, updating an existing airport, and deleting an airport. Here’s a detailed breakdown of the AirportController
:
Namespaces and Imports
namespace App\Http\Controllers;
use App\Models\Airport;
use Illuminate\Http\Request;
- namespace App\Http\Controllers;: Defines the namespace for this controller, placing it in the
App\Http\Controllers
directory. - use App\Models\Airport;: Imports the
Airport
model. - use Illuminate\Http\Request;: Imports the
Request
class to handle HTTP requests.
Class Definition
class AirportController extends Controller
{
// Controller methods will go here
}
- class AirportController extends Controller: Defines the
AirportController
class, which extends Laravel’s baseController
class.
Index Method
public function index(Request $request)
{
$query = Airport::query();
// Filtering and Search
if ($request->has('search')) {
$search = $request->search;
$query->where('code', 'LIKE', "%{$search}%")
->orWhere('name', 'LIKE', "%{$search}%")
->orWhere('location', 'LIKE', "%{$search}%");
}
if ($request->has('location')) {
$query->where('location', 'LIKE', "%{$request->location}%");
}
// Pagination
$airports = $query->paginate(10);
return response()->json($airports);
}
- Filtering and Search: Checks if the request has
search
andlocation
parameters and applies filters to the query.- Search: Filters airports by code, name, or location using a LIKE query.
- Location: Filters airports by location using a LIKE query.
- Pagination: Uses the
paginate
method to paginate the results, returning 10 airports per page. - Response: Returns the paginated airports as a JSON response.
Show Method
public function show($code)
{
$airport = Airport::find($code);
if (!$airport) {
return response()->json(['message' => 'Airport not found'], 404);
}
return response()->json($airport);
}
- find($code): Retrieves the airport with the given code.
- Response: Returns the airport as a JSON response. If the airport is not found, it returns a 404 error.
Store Method
public function store(Request $request)
{
$request->validate([
'code' => 'required|string|unique:airports',
'name' => 'required|string',
'location' => 'required|string',
'facilities' => 'nullable|string',
]);
$airport = Airport::create($request->all());
return response()->json($airport, 201);
}
- Validation: Validates the incoming request data to ensure all required fields are present and correctly formatted.
- Create Airport: Creates a new airport record using the validated data.
- Response: Returns the newly created airport as a JSON response with a 201 status code.
Update Method
public function update(Request $request, $code)
{
$airport = Airport::find($code);
if (!$airport) {
return response()->json(['message' => 'Airport not found'], 404);
}
$request->validate([
'code' => 'string|unique:airports,code,' . $code,
'name' => 'string',
'location' => 'string',
'facilities' => 'nullable|string',
]);
$airport->update($request->all());
return response()->json($airport);
}
- Find Airport: Retrieves the airport with the given code.
- Validation: Validates the incoming request data for the fields that can be updated.
- Update Airport: Updates the airport record with the validated data.
- Response: Returns the updated airport as a JSON response.
Destroy Method
public function destroy($code)
{
$airport = Airport::find($code);
if (!$airport) {
return response()->json(['message' => 'Airport not found'], 404);
}
$airport->delete();
return response()->json(['message' => 'Airport deleted successfully']);
}
- Find Airport: Retrieves the airport with the given code.
- Delete Airport: Deletes the airport record.
- Response: Returns a success message as a JSON response.
routes/api.php
use App\Http\Controllers\AirportController;
Route::resource('airports', AirportController::class)->middleware('auth:sanctum');
5. Booking Controller and Routes
app/Http/Controllers/BookingController.php
<?php
namespace App\Http\Controllers;
use App\Models\Booking;
use Illuminate\Http\Request;
class BookingController extends Controller
{
public function index(Request $request)
{
$query = Booking::query();
// Filtering and Search
if ($request->has('passenger')) {
$query->where('passenger_id', $request->passenger);
}
if ($request->has('flight')) {
$query->where('flight_id', $request->flight);
}
if ($request->has('status')) {
$query->where('payment_status', $request->status);
}
// Pagination
$bookings = $query->paginate(10);
return response()->json($bookings);
}
public function show($id)
{
$booking = Booking::find($id);
if (!$booking) {
return response()->json(['message' => 'Booking not found'], 404);
}
return response()->json($booking);
}
public function store(Request $request)
{
$request->validate([
'flight_id' => 'required|exists:flights,id',
'passenger_id' => 'required|exists:passengers,id',
'payment_status' => 'required|string',
]);
$booking = Booking::create($request->all());
return response()->json($booking, 201);
}
public function update(Request $request, $id)
{
$booking = Booking::find($id);
if (!$booking) {
return response()->json(['message' => 'Booking not found'], 404);
}
$request->validate([
'flight_id' => 'exists:flights,id',
'passenger_id' => 'exists:passengers,id',
'payment_status' => 'string',
]);
$booking->update($request->all());
return response()->json($booking);
}
public function destroy($id)
{
$booking = Booking::find($id);
if (!$booking) {
return response()->json(['message' => 'Booking not found'], 404);
}
$booking->delete();
return response()->json(['message' => 'Booking deleted successfully']);
}
}
The BookingController
handles various actions related to the Booking
model, such as listing bookings, showing a specific booking, creating a new booking, updating an existing booking, and deleting a booking. Here’s a detailed breakdown of the BookingController
:
Namespaces and Imports
namespace App\Http\Controllers;
use App\Models\Booking;
use Illuminate\Http\Request;
- namespace App\Http\Controllers;: Defines the namespace for this controller, placing it in the
App\Http\Controllers
directory. - use App\Models\Booking;: Imports the
Booking
model. - use Illuminate\Http\Request;: Imports the
Request
class to handle HTTP requests.
Class Definition
class BookingController extends Controller
{
// Controller methods will go here
}
- class BookingController extends Controller: Defines the
BookingController
class, which extends Laravel’s baseController
class.
Index Method
public function index(Request $request)
{
$query = Booking::query();
// Filtering and Search
if ($request->has('passenger')) {
$query->where('passenger_id', $request->passenger);
}
if ($request->has('flight')) {
$query->where('flight_id', $request->flight);
}
if ($request->has('status')) {
$query->where('payment_status', $request->status);
}
// Pagination
$bookings = $query->paginate(10);
return response()->json($bookings);
}
- Filtering and Search: Checks if the request has
passenger
,flight
, andstatus
parameters and applies filters to the query.- Passenger: Filters bookings by passenger ID.
- Flight: Filters bookings by flight ID.
- Status: Filters bookings by payment status.
- Pagination: Uses the
paginate
method to paginate the results, returning 10 bookings per page. - Response: Returns the paginated bookings as a JSON response.
Show Method
public function show($id)
{
$booking = Booking::find($id);
if (!$booking) {
return response()->json(['message' => 'Booking not found'], 404);
}
return response()->json($booking);
}
- find($id): Retrieves the booking with the given ID.
- Response: Returns the booking as a JSON response. If the booking is not found, it returns a 404 error.
Store Method
public function store(Request $request)
{
$request->validate([
'flight_id' => 'required|exists:flights,id',
'passenger_id' => 'required|exists:passengers,id',
'payment_status' => 'required|string',
]);
$booking = Booking::create($request->all());
return response()->json($booking, 201);
}
- Validation: Validates the incoming request data to ensure all required fields are present and correctly formatted.
- Create Booking: Creates a new booking record using the validated data.
- Response: Returns the newly created booking as a JSON response with a 201 status code.
Update Method
public function update(Request $request, $id)
{
$booking = Booking::find($id);
if (!$booking) {
return response()->json(['message' => 'Booking not found'], 404);
}
$request->validate([
'flight_id' => 'exists:flights,id',
'passenger_id' => 'exists:passengers,id',
'payment_status' => 'string',
]);
$booking->update($request->all());
return response()->json($booking);
}
- Find Booking: Retrieves the booking with the given ID.
- Validation: Validates the incoming request data for the fields that can be updated.
- Update Booking: Updates the booking record with the validated data.
- Response: Returns the updated booking as a JSON response.
Destroy Method
public function destroy($id)
{
$booking = Booking::find($id);
if (!$booking) {
return response()->json(['message' => 'Booking not found'], 404);
}
$booking->delete();
return response()->json(['message' => 'Booking deleted successfully']);
}
- Find Booking: Retrieves the booking with the given ID.
- Delete Booking: Deletes the booking record.
- Response: Returns a success message as a JSON response.
routes/api.php
use App\Http\Controllers\BookingController;
Route::resource('bookings', BookingController::class)->middleware('auth:sanctum');
6. Payment Controller and Routes
app/Http/Controllers/PaymentController.php
<?php
namespace App\Http\Controllers;
use App\Models\Payment;
use Illuminate\Http\Request;
class PaymentController extends Controller
{
public function index(Request $request)
{
$query = Payment::query();
// Filtering and Search
if ($request->has('method')) {
$query->where('payment_method', $request->method);
}
if ($request->has('amountMin')) {
$query->where('amount', '>=', $request->amountMin);
}
if ($request->has('amountMax')) {
$query->where('amount', '<=', $request->amountMax);
}
// Pagination
$payments = $query->paginate(10);
return response()->json($payments);
}
public function show($id)
{
$payment = Payment::find($id);
if (!$payment) {
return response()->json(['message' => 'Payment not found'], 404);
}
return response()->json($payment);
}
public function store(Request $request)
{
$request->validate([
'booking_id' => 'required|exists:bookings,id',
'payment_method' => 'required|string',
'amount' => 'required|numeric',
'transaction_datetime' => 'required|date',
]);
$payment = Payment::create($request->all());
return response()->json($payment, 201);
}
public function update(Request $request, $id)
{
$payment = Payment::find($id);
if (!$payment) {
return response()->json(['message' => 'Payment not found'], 404);
}
$request->validate([
'booking_id' => 'exists:bookings,id',
'payment_method' => 'string',
'amount' => 'numeric',
'transaction_datetime' => 'date',
]);
$payment->update($request->all());
return response()->json($payment);
}
public function destroy($id)
{
$payment = Payment::find($id);
if (!$payment) {
return response()->json(['message' => 'Payment not found'], 404);
}
$payment->delete();
return response()->json(['message' => 'Payment deleted successfully']);
}
}
The PaymentController
handles various actions related to the Payment
model, such as listing payments, showing a specific payment, creating a new payment, updating an existing payment, and deleting a payment. Here’s a detailed breakdown of the PaymentController
:
Namespaces and Imports
namespace App\Http\Controllers;
use App\Models\Payment;
use Illuminate\Http\Request;
- namespace App\Http\Controllers;: Defines the namespace for this controller, placing it in the
App\Http\Controllers
directory. - use App\Models\Payment;: Imports the
Payment
model. - use Illuminate\Http\Request;: Imports the
Request
class to handle HTTP requests.
Class Definition
class PaymentController extends Controller
{
// Controller methods will go here
}
- class PaymentController extends Controller: Defines the
PaymentController
class, which extends Laravel’s baseController
class.
Index Method
public function index(Request $request)
{
$query = Payment::query();
// Filtering and Search
if ($request->has('method')) {
$query->where('payment_method', $request->method);
}
if ($request->has('amountMin')) {
$query->where('amount', '>=', $request->amountMin);
}
if ($request->has('amountMax')) {
$query->where('amount', '<=', $request->amountMax);
}
// Pagination
$payments = $query->paginate(10);
return response()->json($payments);
}
- Filtering and Search: Checks if the request has
method
,amountMin
, andamountMax
parameters and applies filters to the query.- Method: Filters payments by payment method.
- AmountMin: Filters payments with amounts greater than or equal to the specified minimum amount.
- AmountMax: Filters payments with amounts less than or equal to the specified maximum amount.
- Pagination: Uses the
paginate
method to paginate the results, returning 10 payments per page. - Response: Returns the paginated payments as a JSON response.
Show Method
public function show($id)
{
$payment = Payment::find($id);
if (!$payment) {
return response()->json(['message' => 'Payment not found'], 404);
}
return response()->json($payment);
}
- find($id): Retrieves the payment with the given ID.
- Response: Returns the payment as a JSON response. If the payment is not found, it returns a 404 error.
Store Method
public function store(Request $request)
{
$request->validate([
'booking_id' => 'required|exists:bookings,id',
'payment_method' => 'required|string',
'amount' => 'required|numeric',
'transaction_datetime' => 'required|date',
]);
$payment = Payment::create($request->all());
return response()->json($payment, 201);
}
- Validation: Validates the incoming request data to ensure all required fields are present and correctly formatted.
- Create Payment: Creates a new payment record using the validated data.
- Response: Returns the newly created payment as a JSON response with a 201 status code.
Update Method
public function update(Request $request, $id)
{
$payment = Payment::find($id);
if (!$payment) {
return response()->json(['message' => 'Payment not found'], 404);
}
$request->validate([
'booking_id' => 'exists:bookings,id',
'payment_method' => 'string',
'amount' => 'numeric',
'transaction_datetime' => 'date',
]);
$payment->update($request->all());
return response()->json($payment);
}
- Find Payment: Retrieves the payment with the given ID.
- Validation: Validates the incoming request data for the fields that can be updated.
- Update Payment: Updates the payment record with the validated data.
- Response: Returns the updated payment as a JSON response.
Destroy Method
public function destroy($id)
{
$payment = Payment::find($id);
if (!$payment) {
return response()->json(['message' => 'Payment not found'], 404);
}
$payment->delete();
return response()->json(['message' => 'Payment deleted successfully']);
}
- Find Payment: Retrieves the payment with the given ID.
- Delete Payment: Deletes the payment record.
- Response: Returns a success message as a JSON response.
routes/api.php
use App\Http\Controllers\PaymentController;
Route::resource('payments', PaymentController::class)->middleware('auth:sanctum');
In this module, we created controllers and routes for managing flights, passengers, airlines, airports, bookings, and payments in our Flight Reservation System. The controllers handle the business logic, while the routes define the API endpoints. In the next module, we will focus on implementing advanced features such as pagination, filtering, and search functionalities.
Module 6: Advanced Pagination, Filtering, and Search
Overview
In this module, we will implement advanced features such as pagination, filtering, and search functionalities within the controllers of our Flight Reservation System. This will enhance the user experience by allowing more efficient data retrieval and navigation.
Step-by-Step Guide
1. Flight Controller with Pagination, Filtering, and Search
app/Http/Controllers/FlightController.php
<?php
namespace App\Http\Controllers;
use App\Models\Flight;
use Illuminate\Http\Request;
class FlightController extends Controller
{
public function index(Request $request)
{
$query = Flight::query();
// Filtering
if ($request->has('origin')) {
$query->where('origin_airport_code', $request->origin);
}
if ($request->has('destination')) {
$query->where('destination_airport_code', $request->destination);
}
if ($request->has('date')) {
$query->whereDate('departure_datetime', $request->date);
}
// Search
if ($request->has('search')) {
$search = $request->search;
$query->where(function ($q) use ($search) {
$q->where('flight_number', 'LIKE', "%{$search}%")
->orWhere('origin_airport_code', 'LIKE', "%{$search}%")
->orWhere('destination_airport_code', 'LIKE', "%{$search}%");
});
}
// Pagination
$flights = $query->paginate(10);
return response()->json($flights);
}
public function show($id)
{
$flight = Flight::find($id);
if (!$flight) {
return response()->json(['message' => 'Flight not found'], 404);
}
return response()->json($flight);
}
public function store(Request $request)
{
$request->validate([
'flight_number' => 'required|string|unique:flights',
'departure_datetime' => 'required|date',
'arrival_datetime' => 'required|date',
'origin_airport_code' => 'required|string|exists:airports,code',
'destination_airport_code' => 'required|string|exists:airports,code',
'available_seats' => 'required|integer',
'airline_id' => 'required|exists:airlines,id',
]);
$flight = Flight::create($request->all());
return response()->json($flight, 201);
}
public function update(Request $request, $id)
{
$flight = Flight::find($id);
if (!$flight) {
return response()->json(['message' => 'Flight not found'], 404);
}
$request->validate([
'flight_number' => 'string|unique:flights,flight_number,' . $id,
'departure_datetime' => 'date',
'arrival_datetime' => 'date',
'origin_airport_code' => 'string|exists:airports,code',
'destination_airport_code' => 'string|exists:airports,code',
'available_seats' => 'integer',
'airline_id' => 'exists:airlines,id',
]);
$flight->update($request->all());
return response()->json($flight);
}
public function destroy($id)
{
$flight = Flight::find($id);
if (!$flight) {
return response()->json(['message' => 'Flight not found'], 404);
}
$flight->delete();
return response()->json(['message' => 'Flight deleted successfully']);
}
}
The FlightController
handles various actions related to the Flight
model, such as listing flights, showing a specific flight, creating a new flight, updating an existing flight, and deleting a flight. Here’s a detailed breakdown of the FlightController
:
Namespaces and Imports
php
namespace App\Http\Controllers;
use App\Models\Flight;
use Illuminate\Http\Request;
- namespace App\Http\Controllers;: Defines the namespace for this controller, placing it in the
App\Http\Controllers
directory. - use App\Models\Flight;: Imports the
Flight
model. - use Illuminate\Http\Request;: Imports the
Request
class to handle HTTP requests.
Class Definition
class FlightController extends Controller
{
// Controller methods will go here
}
- class FlightController extends Controller: Defines the
FlightController
class, which extends Laravel’s baseController
class.
Index Method
public function index(Request $request)
{
$query = Flight::query();
// Filtering
if ($request->has(‘origin’)) {
$query->where(‘origin_airport_code’, $request->origin);
}
if ($request->has(‘destination’)) {
$query->where(‘destination_airport_code’, $request->destination);
}
if ($request->has(‘date’)) {
$query->whereDate(‘departure_datetime’, $request->date);
}
// Search
if ($request->has(‘search’)) {
$search = $request->search;
$query->where(function ($q) use ($search) {
$q->where(‘flight_number‘, ‘LIKE‘, “%{$search}%”)
->orWhere(‘origin_airport_code‘, ‘LIKE‘, “%{$search}%”)
->orWhere(‘destination_airport_code‘, ‘LIKE‘, “%{$search}%”);
});
}
// Pagination
$flights = $query->paginate(10);
return response()->json($flights);
}
- Filtering: Checks if the request has
origin
,destination
, anddate
parameters and applies filters to the query.- Origin: Filters flights by origin airport code.
- Destination: Filters flights by destination airport code.
- Date: Filters flights by departure date.
- Search: Checks if the request has a
search
parameter and applies a search filter to the query.- Search: Filters flights by flight number, origin airport code, or destination airport code using a LIKE query.
- Pagination: Uses the
paginate
method to paginate the results, returning 10 flights per page. - Response: Returns the paginated flights as a JSON response.
Show Method
public function show($id)
{
$flight = Flight::find($id);
if (!$flight) {
return response()->json(['message' => 'Flight not found'], 404);
}
return response()->json($flight);
}
- find($id): Retrieves the flight with the given ID.
- Response: Returns the flight as a JSON response. If the flight is not found, it returns a 404 error.
Store Method
public function store(Request $request)
{
$request->validate([
'flight_number' => 'required|string|unique:flights',
'departure_datetime' => 'required|date',
'arrival_datetime' => 'required|date',
'origin_airport_code' => 'required|string|exists:airports,code',
'destination_airport_code' => 'required|string|exists:airports,code',
'available_seats' => 'required|integer',
'airline_id' => 'required|exists:airlines,id',
]);
$flight = Flight::create($request->all());
return response()->json($flight, 201);
}
- Validation: Validates the incoming request data to ensure all required fields are present and correctly formatted.
- Create Flight: Creates a new flight record using the validated data.
- Response: Returns the newly created flight as a JSON response with a 201 status code.
Update Method
public function update(Request $request, $id)
{
$flight = Flight::find($id);
if (!$flight) {
return response()->json(['message' => 'Flight not found'], 404);
}
$request->validate([
‘flight_number’ => ‘string|unique:flights,flight_number,’ . $id,
‘departure_datetime’ => ‘date’,
‘arrival_datetime’ => ‘date’,
‘origin_airport_code’ => ‘string|exists:airports,code’,
‘destination_airport_code’ => ‘string|exists:airports,code’,
‘available_seats’ => ‘integer’,
‘airline_id’ => ‘exists:airlines,id’,
]);
$flight->update($request->all());
return response()->json($flight);
}
- Find Flight: Retrieves the flight with the given ID.
- Validation: Validates the incoming request data for the fields that can be updated.
- Update Flight: Updates the flight record with the validated data.
- Response: Returns the updated flight as a JSON response.
Destroy Method
public function destroy($id)
{
$flight = Flight::find($id);
if (!$flight) {
return response()->json(['message' => 'Flight not found'], 404);
}
$flight->delete();
return response()->json([‘message’ => ‘Flight deleted successfully’]);
}
- Find Flight: Retrieves the flight with the given ID.
- Delete Flight: Deletes the flight record.
- Response: Returns a success message as a JSON response.
2. Passenger Controller with Pagination, Filtering, and Search
app/Http/Controllers/PassengerController.php
<?php
namespace App\Http\Controllers;
use App\Models\Passenger;
use Illuminate\Http\Request;
class PassengerController extends Controller
{
public function index(Request $request)
{
$query = Passenger::query();
// Filtering and Search
if ($request->has('search')) {
$search = $request->search;
$query->where(function ($q) use ($search) {
$q->where('first_name', 'LIKE', "%{$search}%")
->orWhere('last_name', 'LIKE', "%{$search}%")
->orWhere('email', 'LIKE', "%{$search}%");
});
}
// Pagination
$passengers = $query->paginate(10);
return response()->json($passengers);
}
public function show($id)
{
$passenger = Passenger::find($id);
if (!$passenger) {
return response()->json(['message' => 'Passenger not found'], 404);
}
return response()->json($passenger);
}
public function store(Request $request)
{
$request->validate([
'first_name' => 'required|string',
'last_name' => 'required|string',
'email' => 'required|string|email|unique:passengers',
'passport_number' => 'required|string|unique:passengers',
]);
$passenger = Passenger::create($request->all());
return response()->json($passenger, 201);
}
public function update(Request $request, $id)
{
$passenger = Passenger::find($id);
if (!$passenger) {
return response()->json(['message' => 'Passenger not found'], 404);
}
$request->validate([
'first_name' => 'string',
'last_name' => 'string',
'email' => 'string|email|unique:passengers,email,' . $id,
'passport_number' => 'string|unique:passengers,passport_number,' . $id,
]);
$passenger->update($request->all());
return response()->json($passenger);
}
public function destroy($id)
{
$passenger = Passenger::find($id);
if (!$passenger) {
return response()->json(['message' => 'Passenger not found'], 404);
}
$passenger->delete();
return response()->json(['message' => 'Passenger deleted successfully']);
}
}
The PassengerController
handles various actions related to the Passenger
model, such as listing passengers, showing a specific passenger, creating a new passenger, updating an existing passenger, and deleting a passenger. Here’s a detailed breakdown of the PassengerController
:
Namespaces and Imports
namespace App\Http\Controllers;
use App\Models\Passenger;
use Illuminate\Http\Request;
- namespace App\Http\Controllers;: Defines the namespace for this controller, placing it in the
App\Http\Controllers
directory. - use App\Models\Passenger;: Imports the
Passenger
model. - use Illuminate\Http\Request;: Imports the
Request
class to handle HTTP requests.
Class Definition
class PassengerController extends Controller
{
// Controller methods will go here
}
- class PassengerController extends Controller: Defines the
PassengerController
class, which extends Laravel’s baseController
class.
Index Method
public function index(Request $request)
{
$query = Passenger::query();
// Filtering and Search
if ($request->has('search')) {
$search = $request->search;
$query->where(function ($q) use ($search) {
$q->where('first_name', 'LIKE', "%{$search}%")
->orWhere('last_name', 'LIKE', "%{$search}%")
->orWhere('email', 'LIKE', "%{$search}%");
});
}
// Pagination
$passengers = $query->paginate(10);
return response()->json($passengers);
}
- Filtering and Search: Checks if the request has a
search
parameter and applies the search query to filter passengers byfirst_name
,last_name
, oremail
. - Pagination: Uses the
paginate
method to paginate the results, returning 10 passengers per page. - Response: Returns the paginated passengers as a JSON response.
Show Method
public function show($id)
{
$passenger = Passenger::find($id);
if (!$passenger) {
return response()->json(['message' => 'Passenger not found'], 404);
}
return response()->json($passenger);
}
- find($id): Retrieves the passenger with the given ID.
- Response: Returns the passenger as a JSON response. If the passenger is not found, it returns a 404 error.
Store Method
public function store(Request $request)
{
$request->validate([
'first_name' => 'required|string',
'last_name' => 'required|string',
'email' => 'required|string|email|unique:passengers',
'passport_number' => 'required|string|unique:passengers',
]);
$passenger = Passenger::create($request->all());
return response()->json($passenger, 201);
}
- Validation: Validates the incoming request data to ensure all required fields are present and correctly formatted.
- Create Passenger: Creates a new passenger record using the validated data.
- Response: Returns the newly created passenger as a JSON response with a 201 status code.
Update Method
public function update(Request $request, $id)
{
$passenger = Passenger::find($id);
if (!$passenger) {
return response()->json(['message' => 'Passenger not found'], 404);
}
$request->validate([
'first_name' => 'string',
'last_name' => 'string',
'email' => 'string|email|unique:passengers,email,' . $id,
'passport_number' => 'string|unique:passengers,passport_number,' . $id,
]);
$passenger->update($request->all());
return response()->json($passenger);
}
- Find Passenger: Retrieves the passenger with the given ID.
- Validation: Validates the incoming request data for the fields that can be updated.
- Update Passenger: Updates the passenger record with the validated data.
- Response: Returns the updated passenger as a JSON response.
Destroy Method
public function destroy($id)
{
$passenger = Passenger::find($id);
if (!$passenger) {
return response()->json(['message' => 'Passenger not found'], 404);
}
$passenger->delete();
return response()->json(['message' => 'Passenger deleted successfully']);
}
- Find Passenger: Retrieves the passenger with the given ID.
- Delete Passenger: Deletes the passenger record.
- Response: Returns a success message as a JSON response.
3. Airline Controller with Pagination, Filtering, and Search
app/Http/Controllers/AirlineController.php
<?php
namespace App\Http\Controllers;
use App\Models\Airline;
use Illuminate\Http\Request;
class AirlineController extends Controller
{
public function index(Request $request)
{
$query = Airline::query();
// Filtering and Search
if ($request->has('search')) {
$search = $request->search;
$query->where('name', 'LIKE', "%{$search}%");
}
if ($request->has('region')) {
$query->where('operating_region', $request->region);
}
// Pagination
$airlines = $query->paginate(10);
return response()->json($airlines);
}
public function show($id)
{
$airline = Airline::find($id);
if (!$airline) {
return response()->json(['message' => 'Airline not found'], 404);
}
return response()->json($airline);
}
public function store(Request $request)
{
$request->validate([
'name' => 'required|string|unique:airlines',
'contact_number' => 'required|string',
'operating_region' => 'required|string',
]);
$airline = Airline::create($request->all());
return response()->json($airline, 201);
}
public function update(Request $request, $id)
{
$airline = Airline::find($id);
if (!$airline) {
return response()->json(['message' => 'Airline not found'], 404);
}
$request->validate([
'name' => 'string|unique:airlines,name,' . $id,
'contact_number' => 'string',
'operating_region' => 'string',
]);
$airline->update($request->all());
return response()->json($airline);
}
public function destroy($id)
{
$airline = Airline::find($id);
if (!$airline) {
return response()->json(['message' => 'Airline not found'], 404);
}
$airline->delete();
return response()->json(['message' => 'Airline deleted successfully']);
}
}
The AirlineController
handles various actions related to the Airline
model, such as listing airlines, showing a specific airline, creating a new airline, updating an existing airline, and deleting an airline. Here’s a detailed breakdown of the AirlineController
:
Namespaces and Imports
namespace App\Http\Controllers;
use App\Models\Airline;
use Illuminate\Http\Request;
- namespace App\Http\Controllers;: Defines the namespace for this controller, placing it in the
App\Http\Controllers
directory. - use App\Models\Airline;: Imports the
Airline
model. - use Illuminate\Http\Request;: Imports the
Request
class to handle HTTP requests.
Class Definition
class AirlineController extends Controller
{
// Controller methods will go here
}
- class AirlineController extends Controller: Defines the
AirlineController
class, which extends Laravel’s baseController
class.
Index Method
public function index(Request $request)
{
$query = Airline::query();
// Filtering and Search
if ($request->has('search')) {
$search = $request->search;
$query->where('name', 'LIKE', "%{$search}%");
}
if ($request->has('region')) {
$query->where('operating_region', $request->region);
}
// Pagination
$airlines = $query->paginate(10);
return response()->json($airlines);
}
- Filtering and Search: Checks if the request has
search
andregion
parameters and applies filters to the query.- Search: Filters airlines by name using a LIKE query.
- Region: Filters airlines by operating region.
- Pagination: Uses the
paginate
method to paginate the results, returning 10 airlines per page. - Response: Returns the paginated airlines as a JSON response.
Show Method
public function show($id)
{
$airline = Airline::find($id);
if (!$airline) {
return response()->json(['message' => 'Airline not found'], 404);
}
return response()->json($airline);
}
- find($id): Retrieves the airline with the given ID.
- Response: Returns the airline as a JSON response. If the airline is not found, it returns a 404 error.
Store Method
public function store(Request $request)
{
$request->validate([
'name' => 'required|string|unique:airlines',
'contact_number' => 'required|string',
'operating_region' => 'required|string',
]);
$airline = Airline::create($request->all());
return response()->json($airline, 201);
}
- Validation: Validates the incoming request data to ensure all required fields are present and correctly formatted.
- Create Airline: Creates a new airline record using the validated data.
- Response: Returns the newly created airline as a JSON response with a 201 status code.
Update Method
public function update(Request $request, $id)
{
$airline = Airline::find($id);
if (!$airline) {
return response()->json(['message' => 'Airline not found'], 404);
}
$request->validate([
'name' => 'string|unique:airlines,name,' . $id,
'contact_number' => 'string',
'operating_region' => 'string',
]);
$airline->update($request->all());
return response()->json($airline);
}
- Find Airline: Retrieves the airline with the given ID.
- Validation: Validates the incoming request data for the fields that can be updated.
- Update Airline: Updates the airline record with the validated data.
- Response: Returns the updated airline as a JSON response.
Destroy Method
public function destroy($id)
{
$airline = Airline::find($id);
if (!$airline) {
return response()->json(['message' => 'Airline not found'], 404);
}
$airline->delete();
return response()->json(['message' => 'Airline deleted successfully']);
}
- Find Airline: Retrieves the airline with the given ID.
- Delete Airline: Deletes the airline record.
- Response: Returns a success message as a JSON response.
4. Airport Controller with Pagination, Filtering, and Search
app/Http/Controllers/AirportController.php
<?php
namespace App\Http\Controllers;
use App\Models\Airport;
use Illuminate\Http\Request;
class AirportController extends Controller
{
public function index(Request $request)
{
$query = Airport::query();
// Filtering and Search
if ($request->has('search')) {
$search = $request->search;
$query->where('code', 'LIKE', "%{$search}%")
->orWhere('name', 'LIKE', "%{$search}%")
->orWhere('location', 'LIKE', "%{$search}%");
}
if ($request->has('location')) {
$query->where('location', 'LIKE', "%{$request->location}%");
}
// Pagination
$airports = $query->paginate(10);
return response()->json($airports);
}
public function show($code)
{
$airport = Airport::find($code);
if (!$airport) {
return response()->json(['message' => 'Airport not found'], 404);
}
return response()->json($airport);
}
public function store(Request $request)
{
$request->validate([
'code' =>
The AirportController
handles various actions related to the Airport
model, such as listing airports, showing a specific airport, creating a new airport, updating an existing airport, and deleting an airport. Here’s a detailed breakdown of the AirportController
:
Namespaces and Imports
namespace App\Http\Controllers;
use App\Models\Airport;
use Illuminate\Http\Request;
- namespace App\Http\Controllers;: Defines the namespace for this controller, placing it in the
App\Http\Controllers
directory. - use App\Models\Airport;: Imports the
Airport
model. - use Illuminate\Http\Request;: Imports the
Request
class to handle HTTP requests.
Class Definition
class AirportController extends Controller
{
// Controller methods will go here
}
- class AirportController extends Controller: Defines the
AirportController
class, which extends Laravel’s baseController
class.
Index Method
public function index(Request $request)
{
$query = Airport::query();
// Filtering and Search
if ($request->has(‘search’)) {
$search = $request->search;
$query->where(‘code’, ‘LIKE’, “%{$search}%”)
->orWhere(‘name’, ‘LIKE’, “%{$search}%”)
->orWhere(‘location’, ‘LIKE’, “%{$search}%”);
}
if ($request->has(‘location’)) {
$query->where(‘location’, ‘LIKE’, “%{$request->location}%”);
}
// Pagination
$airports = $query->paginate(10);
return response()->json($airports);
}
- Filtering and Search: Checks if the request has
search
andlocation
parameters and applies filters to the query.- Search: Filters airports by code, name, or location using a LIKE query.
- Location: Filters airports by location using a LIKE query.
- Pagination: Uses the
paginate
method to paginate the results, returning 10 airports per page. - Response: Returns the paginated airports as a JSON response.
Show Method
public function show($code)
{
$airport = Airport::find($code);
if (!$airport) {
return response()->json(['message' => 'Airport not found'], 404);
}
return response()->json($airport);
}
- find($code): Retrieves the airport with the given code.
- Response: Returns the airport as a JSON response. If the airport is not found, it returns a 404 error.
Store Method
public function store(Request $request)
{
$request->validate([
'code' => 'required|string|unique:airports',
'name' => 'required|string',
'location' => 'required|string',
'facilities' => 'nullable|string',
]);
$airport = Airport::create($request->all());
return response()->json($airport, 201);
}
- Validation: Validates the incoming request data to ensure all required fields are present and correctly formatted.
- Create Airport: Creates a new airport record using the validated data.
- Response: Returns the newly created airport as a JSON response with a 201 status code.
Update Method
public function update(Request $request, $code)
{
$airport = Airport::find($code);
if (!$airport) {
return response()->json(['message' => 'Airport not found'], 404);
}
$request->validate([
‘code’ => ‘string|unique:airports,code,’ . $code,
‘name’ => ‘string’,
‘location’ => ‘string’,
‘facilities’ => ‘nullable|string’,
]);
$airport->update($request->all());
return response()->json($airport);
}
- Find Airport: Retrieves the airport with the given code.
- Validation: Validates the incoming request data for the fields that can be updated.
- Update Airport: Updates the airport record with the validated data.
- Response: Returns the updated airport as a JSON response.
Destroy Method
public function destroy($code)
{
$airport = Airport::find($code);
if (!$airport) {
return response()->json(['message' => 'Airport not found'], 404);
}
$airport->delete();
return response()->json([‘message’ => ‘Airport deleted successfully’]);
}
- Find Airport: Retrieves the airport with the given code.
- Delete Airport: Deletes the airport record.
- Response: Returns a success message as a JSON response.
5. Booking Controller with Pagination, Filtering, and Search
app/Http/Controllers/BookingController.php
<?php
namespace App\Http\Controllers;
use App\Models\Booking;
use Illuminate\Http\Request;
class BookingController extends Controller
{
public function index(Request $request)
{
$query = Booking::query();
// Filtering and Search
if ($request->has('passenger')) {
$query->where('passenger_id', $request->passenger);
}
if ($request->has('flight')) {
$query->where('flight_id', $request->flight);
}
if ($request->has('status')) {
$query->where('payment_status', $request->status);
}
// Pagination
$bookings = $query->paginate(10);
return response()->json($bookings);
}
public function show($id)
{
$booking = Booking::find($id);
if (!$booking) {
return response()->json(['message' => 'Booking not found'], 404);
}
return response()->json($booking);
}
public function store(Request $request)
{
$request->validate([
'flight_id' => 'required|exists:flights,id',
'passenger_id' => 'required|exists:passengers,id',
'payment_status' => 'required|string',
]);
$booking = Booking::create($request->all());
return response()->json($booking, 201);
}
public function update(Request $request, $id)
{
$booking = Booking::find($id);
if (!$booking) {
return response()->json(['message' => 'Booking not found'], 404);
}
$request->validate([
'flight_id' => 'exists:flights,id',
'passenger_id' => 'exists:passengers,id',
'payment_status' => 'string',
]);
$booking->update($request->all());
return response()->json($booking);
}
public function destroy($id)
{
$booking = Booking::find($id);
if (!$booking) {
return response()->json(['message' => 'Booking not found'], 404);
}
$booking->delete();
return response()->json(['message' => 'Booking deleted successfully']);
}
}
The BookingController
handles various actions related to the Booking
model, such as listing bookings, showing a specific booking, creating a new booking, updating an existing booking, and deleting a booking. Here’s a detailed breakdown of the BookingController
:
Namespaces and Imports
namespace App\Http\Controllers;
use App\Models\Booking;
use Illuminate\Http\Request;
- namespace App\Http\Controllers;: Defines the namespace for this controller, placing it in the
App\Http\Controllers
directory. - use App\Models\Booking;: Imports the
Booking
model. - use Illuminate\Http\Request;: Imports the
Request
class to handle HTTP requests.
Class Definition
class BookingController extends Controller
{
// Controller methods will go here
}
- class BookingController extends Controller: Defines the
BookingController
class, which extends Laravel’s baseController
class.
Index Method
public function index(Request $request)
{
$query = Booking::query();
// Filtering and Search
if ($request->has('passenger')) {
$query->where('passenger_id', $request->passenger);
}
if ($request->has('flight')) {
$query->where('flight_id', $request->flight);
}
if ($request->has('status')) {
$query->where('payment_status', $request->status);
}
// Pagination
$bookings = $query->paginate(10);
return response()->json($bookings);
}
- Filtering and Search: Checks if the request has
passenger
,flight
, andstatus
parameters and applies filters to the query.- Passenger: Filters bookings by passenger ID.
- Flight: Filters bookings by flight ID.
- Status: Filters bookings by payment status.
- Pagination: Uses the
paginate
method to paginate the results, returning 10 bookings per page. - Response: Returns the paginated bookings as a JSON response.
Show Method
public function show($id)
{
$booking = Booking::find($id);
if (!$booking) {
return response()->json(['message' => 'Booking not found'], 404);
}
return response()->json($booking);
}
- find($id): Retrieves the booking with the given ID.
- Response: Returns the booking as a JSON response. If the booking is not found, it returns a 404 error.
Store Method
public function store(Request $request)
{
$request->validate([
'flight_id' => 'required|exists:flights,id',
'passenger_id' => 'required|exists:passengers,id',
'payment_status' => 'required|string',
]);
$booking = Booking::create($request->all());
return response()->json($booking, 201);
}
- Validation: Validates the incoming request data to ensure all required fields are present and correctly formatted.
- Create Booking: Creates a new booking record using the validated data.
- Response: Returns the newly created booking as a JSON response with a 201 status code.
Update Method
public function update(Request $request, $id)
{
$booking = Booking::find($id);
if (!$booking) {
return response()->json(['message' => 'Booking not found'], 404);
}
$request->validate([
'flight_id' => 'exists:flights,id',
'passenger_id' => 'exists:passengers,id',
'payment_status' => 'string',
]);
$booking->update($request->all());
return response()->json($booking);
}
- Find Booking: Retrieves the booking with the given ID.
- Validation: Validates the incoming request data for the fields that can be updated.
- Update Booking: Updates the booking record with the validated data.
- Response: Returns the updated booking as a JSON response.
Destroy Method
public function destroy($id)
{
$booking = Booking::find($id);
if (!$booking) {
return response()->json(['message' => 'Booking not found'], 404);
}
$booking->delete();
return response()->json(['message' => 'Booking deleted successfully']);
}
- Find Booking: Retrieves the booking with the given ID.
- Delete Booking: Deletes the booking record.
- Response: Returns a success message as a JSON response.
6. Payment Controller with Pagination, Filtering, and Search
app/Http/Controllers/PaymentController.php
<?php
namespace App\Http\Controllers;
use App\Models\Payment;
use Illuminate\Http\Request;
class PaymentController extends Controller
{
public function index(Request $request)
{
$query = Payment::query();
// Filtering and Search
if ($request->has('method')) {
$query->where('payment_method', $request->method);
}
if ($request->has('amountMin')) {
$query->where('amount', '>=', $request->amountMin);
}
if ($request->has('amountMax')) {
$query->where('amount', '<=', $request->amountMax);
}
// Pagination
$payments = $query->paginate(10);
return response()->json($payments);
}
public function show($id)
{
$payment = Payment::find($id);
if (!$payment) {
return response()->json(['message' => 'Payment not found'], 404);
}
return response()->json($payment);
}
public function store(Request $request)
{
$request->validate([
'booking_id' => 'required|exists:bookings,id',
'payment_method' => 'required|string',
'amount' => 'required|numeric',
'transaction_datetime' => 'required|date',
]);
$payment = Payment::create($request->all());
return response()->json($payment, 201);
}
public function update(Request $request, $id)
{
$payment = Payment::find($id);
if (!$payment) {
return response()->json(['message' => 'Payment not found'], 404);
}
$request->validate([
'booking_id' => 'exists:bookings,id',
'payment_method' => 'string',
'amount' => 'numeric',
'transaction_datetime' => 'date',
]);
$payment->update($request->all());
return response()->json($payment);
}
public function destroy($id)
{
$payment = Payment::find($id);
if (!$payment) {
return response()->json(['message' => 'Payment not found'], 404);
}
$payment->delete();
return response()->json(['message' => 'Payment deleted successfully']);
}
}
The PaymentController
handles various actions related to the Payment
model, such as listing payments, showing a specific payment, creating a new payment, updating an existing payment, and deleting a payment. Here’s a detailed breakdown of the PaymentController
:
Namespaces and Imports
namespace App\Http\Controllers;
use App\Models\Payment;
use Illuminate\Http\Request;
- namespace App\Http\Controllers;: Defines the namespace for this controller, placing it in the
App\Http\Controllers
directory. - use App\Models\Payment;: Imports the
Payment
model. - use Illuminate\Http\Request;: Imports the
Request
class to handle HTTP requests.
Class Definition
class PaymentController extends Controller
{
// Controller methods will go here
}
- class PaymentController extends Controller: Defines the
PaymentController
class, which extends Laravel’s baseController
class.
Index Method
public function index(Request $request)
{
$query = Payment::query();
// Filtering and Search
if ($request->has('method')) {
$query->where('payment_method', $request->method);
}
if ($request->has('amountMin')) {
$query->where('amount', '>=', $request->amountMin);
}
if ($request->has('amountMax')) {
$query->where('amount', '<=', $request->amountMax);
}
// Pagination
$payments = $query->paginate(10);
return response()->json($payments);
}
- Filtering and Search: Checks if the request has
method
,amountMin
, andamountMax
parameters and applies filters to the query.- Method: Filters payments by payment method.
- AmountMin: Filters payments with an amount greater than or equal to the specified minimum amount.
- AmountMax: Filters payments with an amount less than or equal to the specified maximum amount.
- Pagination: Uses the
paginate
method to paginate the results, returning 10 payments per page. - Response: Returns the paginated payments as a JSON response.
Show Method
public function show($id)
{
$payment = Payment::find($id);
if (!$payment) {
return response()->json(['message' => 'Payment not found'], 404);
}
return response()->json($payment);
}
- find($id): Retrieves the payment with the given ID.
- Response: Returns the payment as a JSON response. If the payment is not found, it returns a 404 error.
Store Method
public function store(Request $request)
{
$request->validate([
'booking_id' => 'required|exists:bookings,id',
'payment_method' => 'required|string',
'amount' => 'required|numeric',
'transaction_datetime' => 'required|date',
]);
$payment = Payment::create($request->all());
return response()->json($payment, 201);
}
- Validation: Validates the incoming request data to ensure all required fields are present and correctly formatted.
- Create Payment: Creates a new payment record using the validated data.
- Response: Returns the newly created payment as a JSON response with a 201 status code.
Update Method
public function update(Request $request, $id)
{
$payment = Payment::find($id);
if (!$payment) {
return response()->json(['message' => 'Payment not found'], 404);
}
$request->validate([
'booking_id' => 'exists:bookings,id',
'payment_method' => 'string',
'amount' => 'numeric',
'transaction_datetime' => 'date',
]);
$payment->update($request->all());
return response()->json($payment);
}
- Find Payment: Retrieves the payment with the given ID.
- Validation: Validates the incoming request data for the fields that can be updated.
- Update Payment: Updates the payment record with the validated data.
- Response: Returns the updated payment as a JSON response.
Destroy Method
public function destroy($id)
{
$payment = Payment::find($id);
if (!$payment) {
return response()->json(['message' => 'Payment not found'], 404);
}
$payment->delete();
return response()->json(['message' => 'Payment deleted successfully']);
}
- Find Payment: Retrieves the payment with the given ID.
- Delete Payment: Deletes the payment record.
- Response: Returns a success message as a JSON response.
In this module, we implemented advanced pagination, filtering, and search functionalities within the controllers for managing flights, passengers, airlines, airports, bookings, and payments. These features enhance the usability and efficiency of our Flight Reservation System by providing more flexible and efficient data retrieval capabilities. In the next module, we will focus on testing and deploying the entire system online.
Module 7: Testing and Deploying
Overview
In this module, we will focus on testing and deploying the Flight Reservation System. We will write tests to ensure the functionality of our API and then deploy the system to an online platform.
Step-by-Step Guide
1. Testing
We will use the following tools for testing:
- PHPUnit: Laravel’s default testing framework
- Laravel BrowserKit Testing: For HTTP assertions
Ensure PHPUnit is installed and configured by default in Laravel. Create a directory for the tests if it doesn’t already exist:
mkdir tests/Feature
tests/Feature/FlightTest.php
<?php
namespace Tests\Feature;
use App\Models\Flight;
use App\Models\Airline;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class FlightTest extends TestCase
{
use RefreshDatabase;
public function test_can_create_flight()
{
$user = User::factory()->create();
$airline = Airline::factory()->create();
$flightData = [
'flight_number' => '12345',
'departure_datetime' => '2023-10-10T10:00:00Z',
'arrival_datetime' => '2023-10-10T14:00:00Z',
'origin_airport_code' => 'JFK',
'destination_airport_code' => 'LAX',
'available_seats' => 100,
'airline_id' => $airline->id
];
$this->actingAs($user, 'sanctum')
->postJson('/api/flights', $flightData)
->assertStatus(201)
->assertJson($flightData);
}
public function test_can_get_flights()
{
$user = User::factory()->create();
$airline = Airline::factory()->create();
Flight::factory()->count(10)->create(['airline_id' => $airline->id]);
$this->actingAs($user, 'sanctum')
->getJson('/api/flights')
->assertStatus(200)
->assertJsonStructure([
'data' => [
'*' => ['id', 'flight_number', 'departure_datetime', 'arrival_datetime', 'origin_airport_code', 'destination_airport_code', 'available_seats', 'airline_id']
],
'links',
'meta'
]);
}
// Add more tests for updating, showing and deleting flights
}
This FlightTest
class is a feature test class for testing the Flight
API endpoints in a Laravel application. It uses the RefreshDatabase
trait to ensure that the database is refreshed between tests, providing a clean state for each test. Here’s a detailed breakdown of the FlightTest
class:
Namespaces and Imports
namespace Tests\Feature;
use App\Models\Flight;
use App\Models\Airline;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
- namespace Tests\Feature;: Defines the namespace for this test class, placing it in the
Tests\Feature
directory. - use App\Models\Flight;: Imports the
Flight
model. - use App\Models\Airline;: Imports the
Airline
model. - use App\Models\User;: Imports the
User
model. - use Illuminate\Foundation\Testing\RefreshDatabase;: Imports the
RefreshDatabase
trait. - use Tests\TestCase;: Imports the base
TestCase
class.
Class Definition
class FlightTest extends TestCase
{
use RefreshDatabase;
// Test methods will go here
}
- class FlightTest extends TestCase: Defines the
FlightTest
class, which extends Laravel’s baseTestCase
class. - use RefreshDatabase;: Uses the
RefreshDatabase
trait to refresh the database between tests.
Test Method: test_can_create_flight
public function test_can_create_flight()
{
$user = User::factory()->create();
$airline = Airline::factory()->create();
$flightData = [
'flight_number' => '12345',
'departure_datetime' => '2023-10-10T10:00:00Z',
'arrival_datetime' => '2023-10-10T14:00:00Z',
'origin_airport_code' => 'JFK',
'destination_airport_code' => 'LAX',
'available_seats' => 100,
'airline_id' => $airline->id
];
$this->actingAs($user, 'sanctum')
->postJson('/api/flights', $flightData)
->assertStatus(201)
->assertJson($flightData);
}
- Creating a User: Creates a user using the user factory.
- Creating an Airline: Creates an airline using the airline factory.
- Flight Data: Defines the flight data to be sent in the POST request.
- POST Request: Sends a POST request to the
/api/flights
endpoint with the flight data, acting as the created user. - Assertions:
- assertStatus(201): Asserts that the response status is 201 (Created).
- assertJson($flightData): Asserts that the response JSON matches the flight data.
Test Method: test_can_get_flights
public function test_can_get_flights()
{
$user = User::factory()->create();
$airline = Airline::factory()->create();
Flight::factory()->count(10)->create(['airline_id' => $airline->id]);
$this->actingAs($user, 'sanctum')
->getJson('/api/flights')
->assertStatus(200)
->assertJsonStructure([
'data' => [
'*' => ['id', 'flight_number', 'departure_datetime', 'arrival_datetime', 'origin_airport_code', 'destination_airport_code', 'available_seats', 'airline_id']
],
'links',
'meta'
]);
}
- Creating a User: Creates a user using the user factory.
- Creating an Airline: Creates an airline using the airline factory.
- Creating Flights: Creates 10 flights associated with the created airline using the flight factory.
- GET Request: Sends a GET request to the
/api/flights
endpoint, acting as the created user. - Assertions:
- assertStatus(200): Asserts that the response status is 200 (OK).
- assertJsonStructure(…): Asserts that the response JSON structure matches the expected structure.
tests/Feature/UserTest.php
<?php
namespace Tests\Feature;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class UserTest extends TestCase
{
use RefreshDatabase;
public function test_can_register_user()
{
$userData = [
'name' => 'Test User',
'email' => 'testuser@example.com',
'password' => 'password123',
'password_confirmation' => 'password123'
];
$this->postJson('/api/register', $userData)
->assertStatus(201)
->assertJsonStructure([
'access_token',
'token_type'
]);
}
public function test_can_login_user()
{
$user = User::factory()->create(['password' => bcrypt('password123')]);
$loginData = [
'email' => $user->email,
'password' => 'password123'
];
$this->postJson('/api/login', $loginData)
->assertStatus(200)
->assertJsonStructure([
'access_token',
'token_type'
]);
}
// Add more tests for user logout and other functionalities
}
The UserTest
class is a feature test class for testing user registration and login functionalities in a Laravel application. It uses the RefreshDatabase
trait to ensure that the database is refreshed between tests, providing a clean state for each test. Here’s a detailed breakdown of the UserTest
class:
Namespaces and Imports
namespace Tests\Feature;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
- namespace Tests\Feature;: Defines the namespace for this test class, placing it in the
Tests\Feature
directory. - use App\Models\User;: Imports the
User
model. - use Illuminate\Foundation\Testing\RefreshDatabase;: Imports the
RefreshDatabase
trait. - use Tests\TestCase;: Imports the base
TestCase
class.
Class Definition
class UserTest extends TestCase
{
use RefreshDatabase;
// Test methods will go here
}
- class UserTest extends TestCase: Defines the
UserTest
class, which extends Laravel’s baseTestCase
class. - use RefreshDatabase;: Uses the
RefreshDatabase
trait to refresh the database between tests.
Test Method: test_can_register_user
public function test_can_register_user()
{
$userData = [
'name' => 'Test User',
'email' => 'testuser@example.com',
'password' => 'password123',
'password_confirmation' => 'password123'
];
$this->postJson('/api/register', $userData)
->assertStatus(201)
->assertJsonStructure([
'access_token',
'token_type'
]);
}
- User Data: Defines the user data to be sent in the POST request.
- POST Request: Sends a POST request to the
/api/register
endpoint with the user data. - Assertions:
- assertStatus(201): Asserts that the response status is 201 (Created).
- assertJsonStructure([…]): Asserts that the response JSON structure contains the expected keys (
access_token
,token_type
).
Test Method: test_can_login_user
public function test_can_login_user()
{
$user = User::factory()->create(['password' => bcrypt('password123')]);
$loginData = [
'email' => $user->email,
'password' => 'password123'
];
$this->postJson('/api/login', $loginData)
->assertStatus(200)
->assertJsonStructure([
'access_token',
'token_type'
]);
}
- Creating a User: Creates a user using the user factory, setting the password to
password123
. - Login Data: Defines the login data to be sent in the POST request.
- POST Request: Sends a POST request to the
/api/login
endpoint with the login data. - Assertions:
- assertStatus(200): Asserts that the response status is 200 (OK).
- assertJsonStructure([…]): Asserts that the response JSON structure contains the expected keys (
access_token
,token_type
).
Run the tests:
php artisan test
2. Deployment
For deployment, we will use Heroku. Follow these steps to deploy your application.
Install Heroku CLI Download and install the Heroku CLI from Heroku CLI.
Login to Heroku
heroku login
Create a New Heroku Application
heroku create flight-reservation-system
Add ClearDB MySQL Add-on
heroku addons:create cleardb:ignite
Set Environment Variables
heroku config:set APP_ENV=production
heroku config:set APP_KEY=$(php artisan key:generate --show)
heroku config:set JWT_SECRET=your_jwt_secret
Add a Procfile Create a Procfile
in the root directory of your project:
echo "web: vendor/bin/heroku-php-apache2 public/" > Procfile
Prepare Laravel for Deployment Ensure your .env
file contains:
APP_NAME=Laravel
APP_ENV=production
APP_KEY=base64:...
APP_DEBUG=false
APP_URL=https://<your-heroku-app>.herokuapp.com
LOG_CHANNEL=stack
DB_CONNECTION=mysql
DB_HOST=<your-cleardb-host>
DB_PORT=3306
DB_DATABASE=<your-cleardb-database>
DB_USERNAME=<your-cleardb-username>
DB_PASSWORD=<your-cleardb-password>
BROADCAST_DRIVER=log
CACHE_DRIVER=file
QUEUE_CONNECTION=sync
SESSION_DRIVER=file
SESSION_LIFETIME=120
SANCTUM_STATEFUL_DOMAINS=your-domain.com
SESSION_DOMAIN=your-domain.com
Deploy to Heroku Initialize a git repository if you haven’t already and commit your code.
git init
git add .
git commit -m "Initial commit"
Add Heroku remote and push your code.
heroku git:remote -a flight-reservation-system
git push heroku master
Run Migrations on Heroku
heroku run php artisan migrate
Open the Application
heroku open
In this module, we have written tests for our Flight Reservation System to ensure its functionality. We then deployed the application to Heroku, a cloud platform as a service (PaaS). By following these steps, you can ensure that your system is both reliable and accessible online.
Welcome to DevTechTutor.com, your ultimate resource for mastering web development and technology! Whether you're a beginner eager to dive into coding or an experienced developer looking to sharpen your skills, DevTechTutor.com is here to guide you every step of the way. Our mission is to make learning web development accessible, engaging, and effective.