Skip to content

Flight booking php 8.2#605

Open
Deloper11 wants to merge 4 commits intogithub:mainfrom
Deloper11:Flight-Booking-PHP-8.2
Open

Flight booking php 8.2#605
Deloper11 wants to merge 4 commits intogithub:mainfrom
Deloper11:Flight-Booking-PHP-8.2

Conversation

@Deloper11
Copy link

Directory Structure
text
etatourtravel/
├── index.php (homepage)
├── config/
│ ├── database.php
│ └── constants.php
├── includes/
│ ├── header.php
│ ├── footer.php
│ └── functions.php
├── templates/ (all the template pages)
├── assets/
│ ├── css/
│ │ └── style.css
│ └── js/
│ └── app.js
├── classes/ (PHP classes)
├── api/ (API endpoints)
├── admin/ (admin panel)
└── data/ (data storage)
Step 1: Main Files

  1. config/database.php
    php
connection = new PDO( "mysql:host=" . DB_HOST . ";dbname=" . DB_NAME . ";charset=utf8mb4", DB_USER, DB_PASS, [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::ATTR_EMULATE_PREPARES => false ] ); } catch (PDOException $e) { die("Connection failed: " . $e->getMessage()); } } public static function getInstance() { if (self::$instance === null) { self::$instance = new self(); } return self::$instance; } public function getConnection() { return $this->connection; } } ?>
  1. includes/header.php
    php
<title>etatourtravel.com | Flight Booking & Admin System</title>
<!-- External Assets -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<link href="https://fonts.googleapis.com/css2?family=Assistant:wght@300;400;600&family=Montserrat:wght@500;700&display=swap" rel="stylesheet">

<!-- Main Styles -->
<link rel="stylesheet" href="/assets/css/style.css">
<!-- Main Navigation -->
<nav class="navbar navbar-expand-lg navbar-dark sticky-top">
    <div class="container">
        <a class="navbar-brand" href="/">
            <img src="https://cdn-icons-png.flaticon.com/512/824/824100.png" alt="Logo">
            <span>ETA Tour & Travel Agency</span>
        </a>
        <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
            <span class="navbar-toggler-icon"></span>
        </button>
        <div class="collapse navbar-collapse" id="navbarNav">
            <ul class="navbar-nav ms-auto">
                <?php if ($isAdmin): ?>
                    <li class="nav-item"><a class="nav-link text-warning" href="/admin/dashboard.php"><i class="fas fa-lock me-1"></i>Admin</a></li>
                    <li class="nav-item"><a class="nav-link" href="/includes/logout.php">Logout</a></li>
                <?php elseif ($isLoggedIn): ?>
                    <li class="nav-item"><a class="nav-link" href="/">Home</a></li>
                    <li class="nav-item"><a class="nav-link" href="/my-flights.php">My Flights</a></li>
                    <li class="nav-item"><a class="nav-link" href="/feedback.php">Feedback</a></li>
                    <li class="nav-item"><a class="nav-link fw-bold text-info" href="/profile.php">
                        <i class="fas fa-user-circle me-1"></i><?php echo htmlspecialchars($user['name']); ?>
                    </a></li>
                    <li class="nav-item"><a class="nav-link" href="/includes/logout.php">Logout</a></li>
                <?php else: ?>
                    <li class="nav-item"><a class="nav-link" href="/">Home</a></li>
                    <li class="nav-item"><a class="nav-link" href="/login.php">Login</a></li>
                    <li class="nav-item"><a class="nav-link" href="/register.php">Register</a></li>
                <?php endif; ?>
            </ul>
        </div>
    </div>
</nav>
  1. includes/footer.php
    php

    ETA Tour & Travel Agency

    Simplifying air travel with cutting-edge booking technology. Trusted by millions of travelers worldwide.

    Support
    • 24/7 Help Center: +8809658001016
    • sales@etatourtravel.com
    Staff Portal

    © 2026 ETA Tour & Travel Agency. Developed by etatourtravel.com.

    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.0/jquery.min.js"></script> <script src="/assets/js/app.js"></script>
4. index.php (Homepage) php // Get flights from database
$db = Database::getInstance()->getConnection();
$stmt = $db->query("SELECT * FROM flights WHERE departure_date >= CURDATE() ORDER BY departure_date ASC");
$flights = $stmt->fetchAll();

// Process search if submitted
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['search'])) {
$from = $_POST['from'];
$to = $_POST['to'];
$depart_date = $_POST['depart_date'];
$trip_type = $_POST['trip_type'];

$sql = "SELECT * FROM flights WHERE departure_airport LIKE ? AND arrival_airport LIKE ? 
        AND DATE(departure_date) = ?";

$stmt = $db->prepare($sql);
$stmt->execute(["%$from%", "%$to%", $depart_date]);
$flights = $stmt->fetchAll();

}
?>

Your Journey Starts Here

Explore new horizons with affordable and reliable flight options.

Departure City Select City Dhaka (DAC) Chittagong (CGP) Sylhet (ZYL) Cox's Bazar (CXB) Jessore (JSR)
Destination Select City Dhaka (DAC) Chittagong (CGP) Sylhet (ZYL) Cox's Bazar (CXB) Jessore (JSR)
Depart Date
Passengers 1 Passenger 2 Passengers 3 Passengers 4 Passengers
Search Flights

Available Flights

flights available
<div class="row">
    <?php if (empty($flights)): ?>
        <div class="col-12 text-center py-5">
            <i class="fas fa-plane-slash fa-3x text-muted mb-3"></i>
            <h4>No flights found</h4>
            <p class="text-muted">Try adjusting your search criteria</p>
        </div>
    <?php else: ?>
        <?php foreach ($flights as $flight): ?>
            <div class="col-md-6 col-lg-4 mb-4">
                <div class="flight-card">
                    <div class="d-flex justify-content-between mb-3">
                        <span class="fw-bold text-primary"><?php echo htmlspecialchars($flight['airline']); ?></span>
                        <span class="status-badge status-<?php echo $flight['status']; ?>">
                            <?php echo ucfirst($flight['status']); ?>
                        </span>
                    </div>
                    <div class="row align-items-center mb-4">
                        <div class="col-5">
                            <div class="h5 mb-0"><?php echo $flight['departure_airport']; ?></div>
                            <small class="text-muted"><?php echo date('H:i', strtotime($flight['departure_date'])); ?></small>
                        </div>
                        <div class="col-2 text-center text-muted">
                            <i class="fas fa-plane"></i>
                        </div>
                        <div class="col-5 text-end">
                            <div class="h5 mb-0"><?php echo $flight['arrival_airport']; ?></div>
                            <small class="text-muted"><?php echo date('H:i', strtotime($flight['arrival_date'])); ?></small>
                        </div>
                    </div>
                    <div class="d-flex justify-content-between align-items-center">
                        <div>
                            <span class="text-muted small">Price</span>
                            <div class="h4 mb-0 text-success">BDT <?php echo number_format($flight['price']); ?></div>
                            <small class="text-muted"><?php echo $flight['class']; ?> • <?php echo $flight['flight_number']; ?></small>
                        </div>
                        <a href="/book-flight.php?id=<?php echo $flight['id']; ?>" 
                           class="btn btn-primary btn-sm px-4 rounded-pill">Book Now</a>
                    </div>
                </div>
            </div>
        <?php endforeach; ?>
    <?php endif; ?>
</div>
  1. assets/css/style.css
    css
    :root {
    --primary: #376b8d;
    --secondary: #4a6491;
    --accent: #4caf50;
    --dark: #1a252f;
    --light: #f8f9fa;
    --admin-bg: #f4f7f6;
    --transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
    }

body {
font-family: 'Assistant', sans-serif;
background-color: #f0f2f5;
overflow-x: hidden;
min-height: 100vh;
}

h1, h2, h3, .navbar-brand {
font-family: 'Montserrat', sans-serif;
}

/* Navbar Styling */
.navbar {
background-color: var(--dark) !important;
box-shadow: 0 2px 10px rgba(0,0,0,0.2);
}
.navbar-brand img {
height: 35px;
margin-right: 10px;
}

/* Hero Section */
.hero-section {
background: linear-gradient(rgba(0, 0, 0, 0.6), rgba(0, 0, 0, 0.6)),
url('https://images.unsplash.com/photo-1436491865332-7a61a109cc05?auto=format&fit=crop&w=1350&q=80');
background-size: cover;
background-position: center;
color: white;
padding: 120px 0 160px;
text-align: center;
}

/* Search Container */
.search-wrapper {
margin-top: -80px;
position: relative;
z-index: 10;
}
.search-card {
background: white;
border-radius: 20px;
padding: 30px;
box-shadow: 0 15px 35px rgba(0,0,0,0.1);
}

/* Component Styles */
.flight-card {
background: white;
border-radius: 12px;
padding: 20px;
margin-bottom: 20px;
border: 1px solid #eee;
transition: var(--transition);
}
.flight-card:hover {
transform: translateY(-5px);
box-shadow: 0 8px 25px rgba(0,0,0,0.08);
}

.status-badge {
font-size: 0.75rem;
padding: 5px 12px;
border-radius: 20px;
font-weight: 700;
text-transform: uppercase;
}
.status-scheduled { background: #e3f2fd; color: #1565c0; }
.status-departed { background: #fff3e0; color: #ef6c00; }
.status-arrived { background: #e8f5e9; color: #2e7d32; }
.status-issue { background: #ffebee; color: #c62828; }
.status-delayed { background: #fff3e0; color: #f57c00; }

/* Admin Dashboard Layout */
.admin-sidebar {
background: var(--dark);
min-height: calc(100vh - 56px);
color: white;
padding-top: 20px;
}
.admin-nav-link {
color: #bdc3c7;
padding: 12px 20px;
display: block;
text-decoration: none;
transition: var(--transition);
border-left: 4px solid transparent;
}
.admin-nav-link:hover, .admin-nav-link.active {
color: white;
background: rgba(255,255,255,0.05);
border-left-color: var(--primary);
}

.stat-card {
background: white;
border-radius: 12px;
padding: 20px;
border-left: 5px solid var(--primary);
box-shadow: 0 4px 6px rgba(0,0,0,0.05);
}

/* Booking Process */
.step-indicator {
display: flex;
justify-content: space-between;
margin: 30px 0 40px;
position: relative;
}
.step-indicator::before {
content: '';
position: absolute;
top: 15px;
left: 0;
right: 0;
height: 2px;
background: #e0e0e0;
z-index: 1;
}
.step {
display: flex;
flex-direction: column;
align-items: center;
position: relative;
z-index: 2;
background: white;
padding: 10px;
}
.step-number {
width: 30px;
height: 30px;
border-radius: 50%;
background: #e0e0e0;
color: #666;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 8px;
font-weight: bold;
}
.step.active .step-number {
background: var(--primary);
color: white;
}
.step.completed .step-number {
background: #4caf50;
color: white;
}

/* E-Ticket Styles */
.ticket-container {
border: 2px solid #424242;
border-radius: 10px;
overflow: hidden;
max-width: 800px;
margin: 0 auto;
}
.ticket-header {
background: var(--primary);
color: white;
padding: 20px;
}
.ticket-body {
padding: 30px;
background: white;
}
.ticket-field {
margin-bottom: 15px;
}
.ticket-label {
font-size: 12px;
color: #666;
text-transform: uppercase;
margin-bottom: 5px;
}
.ticket-value {
font-size: 18px;
font-weight: bold;
color: #333;
}
.ticket-qr {
width: 150px;
height: 150px;
background: #f5f5f5;
display: flex;
align-items: center;
justify-content: center;
margin: 20px auto;
border: 1px dashed #ccc;
}

/* Feedback Form Styles */
.feedback-container {
background: rgba(3, 3, 3, 0.57);
padding: 40px;
border-radius: 10px;
color: white;
}
.rating-stars {
font-size: 30px;
color: #ccc;
cursor: pointer;
}
.rating-stars .active {
color: #ffc107;
}

/* Login/Register Forms */
.auth-form {
background: rgba(255,255,255,0.95);
padding: 40px;
border-radius: 15px;
box-shadow: 0 10px 30px rgba(0,0,0,0.1);
max-width: 500px;
margin: 0 auto;
}
.form-animate-label {
transition: all 0.3s ease;
transform: translateY(-25px);
font-size: 12px;
color: var(--primary);
}

/* Utility */
.cursor-pointer { cursor: pointer; }
.hidden { display: none !important; }
.fade-in { animation: fadeIn 0.4s ease-in; }
@Keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }

@media print {
.navbar, footer, .no-print { display: none !important; }
.ticket-container {
box-shadow: none;
border: 1px solid #000;
margin: 0;
max-width: none;
}
}
6. login.php
php

getConnection(); $stmt = $db->prepare("SELECT * FROM users WHERE email = ? OR username = ?"); $stmt->execute([$email, $email]); $user = $stmt->fetch(); if ($user && password_verify($password, $user['password'])) { $_SESSION['user'] = $user; $_SESSION['is_admin'] = $user['is_admin'] == 1; header("Location: /"); exit(); } else { $error = "Invalid credentials"; } } ?>

Login

            <?php if (isset($error)): ?>
                <div class="alert alert-danger"><?php echo $error; ?></div>
            <?php endif; ?>
            
            <form method="POST" action="">
                <div class="mb-3">
                    <label class="form-label">Email or Username</label>
                    <div class="input-group">
                        <span class="input-group-text"><i class="fas fa-user"></i></span>
                        <input type="text" class="form-control" name="email" required>
                    </div>
                </div>
                <div class="mb-4">
                    <label class="form-label">Password</label>
                    <div class="input-group">
                        <span class="input-group-text"><i class="fas fa-lock"></i></span>
                        <input type="password" class="form-control" name="password" required>
                    </div>
                </div>
                <div class="mb-3">
                    <a href="/reset-password.php" class="text-decoration-none">
                        Forgot Password?
                    </a>
                </div>
                <button type="submit" class="btn btn-primary w-100 py-2 mb-3">
                    <i class="fas fa-sign-in-alt me-2"></i>Login
                </button>
                <div class="text-center">
                    <span class="text-muted">Don't have an account?</span>
                    <a href="/register.php" class="text-decoration-none ms-1">
                        Register here
                    </a>
                </div>
            </form>
        </div>
    </div>
</div>
  1. register.php
    php
getConnection(); // Check if user exists $stmt = $db->prepare("SELECT id FROM users WHERE email = ? OR username = ?"); $stmt->execute([$email, $username]); if ($stmt->fetch()) { $error = "User already exists"; } else { $stmt = $db->prepare("INSERT INTO users (first_name, last_name, email, username, password) VALUES (?, ?, ?, ?, ?)"); if ($stmt->execute([$first_name, $last_name, $email, $username, $password])) { $_SESSION['user'] = [ 'id' => $db->lastInsertId(), 'name' => "$first_name $last_name", 'email' => $email, 'username' => $username ]; header("Location: /"); exit(); } else { $error = "Registration failed"; } } } ?>

Create Account

            <?php if (isset($error)): ?>
                <div class="alert alert-danger"><?php echo $error; ?></div>
            <?php endif; ?>
            
            <form method="POST" action="">
                <div class="row g-3">
                    <div class="col-md-6">
                        <label class="form-label">First Name</label>
                        <input type="text" class="form-control" name="first_name" required>
                    </div>
                    <div class="col-md-6">
                        <label class="form-label">Last Name</label>
                        <input type="text" class="form-control" name="last_name" required>
                    </div>
                </div>
                <div class="mb-3">
                    <label class="form-label">Email</label>
                    <input type="email" class="form-control" name="email" required>
                </div>
                <div class="mb-3">
                    <label class="form-label">Username</label>
                    <input type="text" class="form-control" name="username" required>
                </div>
                <div class="mb-3">
                    <label class="form-label">Password</label>
                    <input type="password" class="form-control" name="password" required>
                </div>
                <div class="mb-4">
                    <label class="form-label">Confirm Password</label>
                    <input type="password" class="form-control" name="confirm_password" required>
                </div>
                <button type="submit" class="btn btn-primary w-100 py-2 mb-3">
                    <i class="fas fa-user-plus me-2"></i>Register
                </button>
                <div class="text-center">
                    <span class="text-muted">Already have an account?</span>
                    <a href="/login.php" class="text-decoration-none ms-1">
                        Login here
                    </a>
                </div>
            </form>
        </div>
    </div>
</div>
  1. admin/dashboard.php
    php
getConnection(); // Get stats $stats = [ 'total_passengers' => $db->query("SELECT SUM(passenger_count) as total FROM bookings")->fetch()['total'] ?? 0, 'total_flights' => $db->query("SELECT COUNT(*) as total FROM flights WHERE status = 'scheduled'")->fetch()['total'], 'total_bookings' => $db->query("SELECT COUNT(*) as total FROM bookings")->fetch()['total'], 'total_revenue' => $db->query("SELECT SUM(total_amount) as total FROM bookings")->fetch()['total'] ?? 0 ]; // Get recent flights $recentFlights = $db->query("SELECT * FROM flights ORDER BY departure_date DESC LIMIT 5")->fetchAll(); ?>

Operational Overview

Total Passengers
Active Flights
Total Bookings
BDT
Total Revenue
        <div class="card shadow-sm border-0">
            <div class="card-header bg-white py-3 d-flex justify-content-between align-items-center">
                <h5 class="mb-0">Recent Flight Operations</h5>
                <a href="/admin/flights.php?action=add" class="btn btn-primary btn-sm">
                    <i class="fas fa-plus me-1"></i> Add Flight
                </a>
            </div>
            <div class="card-body">
                <div class="table-responsive">
                    <table class="table align-middle">
                        <thead class="table-light">
                            <tr>
                                <th>Flight #</th>
                                <th>Airline</th>
                                <th>Route</th>
                                <th>Departure</th>
                                <th>Status</th>
                                <th>Actions</th>
                            </tr>
                        </thead>
                        <tbody>
                            <?php foreach ($recentFlights as $flight): ?>
                            <tr>
                                <td><?php echo $flight['flight_number']; ?></td>
                                <td><?php echo $flight['airline']; ?></td>
                                <td><?php echo $flight['departure_airport']; ?> → <?php echo $flight['arrival_airport']; ?></td>
                                <td><?php echo date('Y-m-d H:i', strtotime($flight['departure_date'])); ?></td>
                                <td>
                                    <span class="status-badge status-<?php echo $flight['status']; ?>">
                                        <?php echo ucfirst($flight['status']); ?>
                                    </span>
                                </td>
                                <td>
                                    <a href="/admin/flights.php?action=edit&id=<?php echo $flight['id']; ?>" 
                                       class="btn btn-sm btn-outline-primary">
                                        <i class="fas fa-edit"></i>
                                    </a>
                                </td>
                            </tr>
                            <?php endforeach; ?>
                        </tbody>
                    </table>
                </div>
            </div>
        </div>
    </div>
</div>
  1. SQL Database Schema
    sql
    -- Create database
    CREATE DATABASE etatourtravel;
    USE etatourtravel;

-- Users table
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT,
first_name VARCHAR(50) NOT NULL,
last_name VARCHAR(50) NOT NULL,
email VARCHAR(100) UNIQUE NOT NULL,
username VARCHAR(50) UNIQUE NOT NULL,
password VARCHAR(255) NOT NULL,
phone VARCHAR(20),
is_admin BOOLEAN DEFAULT FALSE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

-- Flights table
CREATE TABLE flights (
id INT PRIMARY KEY AUTO_INCREMENT,
airline VARCHAR(100) NOT NULL,
flight_number VARCHAR(20) NOT NULL,
departure_airport VARCHAR(10) NOT NULL,
arrival_airport VARCHAR(10) NOT NULL,
departure_date DATETIME NOT NULL,
arrival_date DATETIME NOT NULL,
price DECIMAL(10,2) NOT NULL,
class ENUM('Economy', 'Business', 'First') DEFAULT 'Economy',
seats_available INT DEFAULT 100,
status ENUM('scheduled', 'departed', 'arrived', 'delayed', 'cancelled') DEFAULT 'scheduled',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- Bookings table
CREATE TABLE bookings (
id INT PRIMARY KEY AUTO_INCREMENT,
booking_reference VARCHAR(20) UNIQUE NOT NULL,
user_id INT NOT NULL,
flight_id INT NOT NULL,
passenger_count INT DEFAULT 1,
total_amount DECIMAL(10,2) NOT NULL,
status ENUM('pending', 'confirmed', 'cancelled', 'completed') DEFAULT 'pending',
payment_method VARCHAR(50),
payment_status ENUM('pending', 'paid', 'failed') DEFAULT 'pending',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id),
FOREIGN KEY (flight_id) REFERENCES flights(id)
);

-- Passengers table
CREATE TABLE passengers (
id INT PRIMARY KEY AUTO_INCREMENT,
booking_id INT NOT NULL,
first_name VARCHAR(50) NOT NULL,
middle_name VARCHAR(50),
last_name VARCHAR(50) NOT NULL,
date_of_birth DATE,
contact_number VARCHAR(20),
seat_number VARCHAR(10),
FOREIGN KEY (booking_id) REFERENCES bookings(id) ON DELETE CASCADE
);

-- Feedback table
CREATE TABLE feedback (
id INT PRIMARY KEY AUTO_INCREMENT,
user_id INT,
email VARCHAR(100) NOT NULL,
feedback_text TEXT NOT NULL,
rating INT DEFAULT 5,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id)
);

-- Insert sample admin user (password: admin123)
INSERT INTO users (first_name, last_name, email, username, password, is_admin)
VALUES ('Admin', 'User', 'admin@etatourtravel.com', 'admin', '$2y$10$YourHashedPasswordHere', TRUE);

-- Insert sample flights
INSERT INTO flights (airline, flight_number, departure_airport, arrival_airport, departure_date, arrival_date, price, class, seats_available) VALUES
('Biman Bangladesh Airlines', 'BG 101', 'DAC', 'CGP', '2024-03-15 08:00:00', '2024-03-15 09:00:00', 8500.00, 'Economy', 95),
('US-Bangla Airlines', 'BS 202', 'DAC', 'ZYL', '2024-03-15 10:30:00', '2024-03-15 11:30:00', 9200.00, 'Business', 20),
('Novoair', 'VQ 303', 'CGP', 'CXB', '2024-03-16 07:15:00', '2024-03-16 07:45:00', 6500.00, 'Economy', 100),
('Air Astra', '2A 404', 'DAC', 'JSR', '2024-03-16 14:20:00', '2024-03-16 15:10:00', 7500.00, 'Economy', 85);
10. .htaccess (for URL rewriting)
apache
RewriteEngine On
RewriteBase /

Remove .php extension

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^([^\.]+)$ $1.php [NC,L]

Redirect to index.php for clean URLs

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?path=$1 [QSA,L]
11. includes/logout.php
php

Installation Instructions:
Setup Requirements:

bash

PHP 8.2

sudo apt install php8.2 php8.2-mysql php8.2-curl php8.2-gd php8.2-mbstring
Install Apache & MySQL:

bash
sudo apt install apache2 mysql-server
sudo mysql_secure_installation
Configure Database:

bash
mysql -u root -p

Run the SQL schema provided above

Set Permissions:

bash
chmod -R 755 etatourtravel/
chown -R www-data:www-data etatourtravel/
Configure Apache Virtual Host:

apache
<VirtualHost *:80>
ServerName etatourtravel.local
DocumentRoot /var/www/etatourtravel
<Directory /var/www/etatourtravel>
Options Indexes FollowSymLinks
AllowOverride All
Require all granted


Enable mod_rewrite:

bash
sudo a2enmod rewrite
sudo systemctl restart apache2
Key Features of PHP Version:
Security:

Prepared statements for SQL queries

Password hashing with password_hash()

Input sanitization with htmlspecialchars()

Session-based authentication

Performance:

PDO database connection with persistent connection

Caching mechanisms (can be added)

Optimized queries

Structure:

MVC-like architecture

Separation of concerns

Reusable components

Proper error handling

Admin Features:

Full CRUD for flights

Booking management

User management

Dashboard with statistics

Booking System:

Multi-step booking process

Payment integration ready

E-ticket generation

Email notifications (can be added)

The application is now a fully functional PHP 8.2 application with proper database integration

Directory Structure
text
etatourtravel/
├── index.php (homepage)
├── config/
│   ├── database.php
│   └── constants.php
├── includes/
│   ├── header.php
│   ├── footer.php
│   └── functions.php
├── templates/ (all the template pages)
├── assets/
│   ├── css/
│   │   └── style.css
│   └── js/
│       └── app.js
├── classes/ (PHP classes)
├── api/ (API endpoints)
├── admin/ (admin panel)
└── data/ (data storage)
Step 1: Main Files
1. config/database.php
php
<?php
// database.php
define('DB_HOST', 'localhost');
define('DB_NAME', 'etatourtravel');
define('DB_USER', 'root');
define('DB_PASS', '');

class Database {
    private static $instance = null;
    private $connection;
    
    private function __construct() {
        try {
            $this->connection = new PDO(
                "mysql:host=" . DB_HOST . ";dbname=" . DB_NAME . ";charset=utf8mb4",
                DB_USER,
                DB_PASS,
                [
                    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
                    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
                    PDO::ATTR_EMULATE_PREPARES => false
                ]
            );
        } catch (PDOException $e) {
            die("Connection failed: " . $e->getMessage());
        }
    }
    
    public static function getInstance() {
        if (self::$instance === null) {
            self::$instance = new self();
        }
        return self::$instance;
    }
    
    public function getConnection() {
        return $this->connection;
    }
}
?>
2. includes/header.php
php
<?php
session_start();
require_once __DIR__ . '/../config/database.php';

$isLoggedIn = isset($_SESSION['user']);
$isAdmin = isset($_SESSION['is_admin']) && $_SESSION['is_admin'];
$user = $isLoggedIn ? $_SESSION['user'] : null;
?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>etatourtravel.com | Flight Booking & Admin System</title>
    
    <!-- External Assets -->
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
    <link href="https://fonts.googleapis.com/css2?family=Assistant:wght@300;400;600&family=Montserrat:wght@500;700&display=swap" rel="stylesheet">
    
    <!-- Main Styles -->
    <link rel="stylesheet" href="/assets/css/style.css">
</head>
<body>

    <!-- Main Navigation -->
    <nav class="navbar navbar-expand-lg navbar-dark sticky-top">
        <div class="container">
            <a class="navbar-brand" href="/">
                <img src="https://cdn-icons-png.flaticon.com/512/824/824100.png" alt="Logo">
                <span>ETA Tour & Travel Agency</span>
            </a>
            <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
                <span class="navbar-toggler-icon"></span>
            </button>
            <div class="collapse navbar-collapse" id="navbarNav">
                <ul class="navbar-nav ms-auto">
                    <?php if ($isAdmin): ?>
                        <li class="nav-item"><a class="nav-link text-warning" href="/admin/dashboard.php"><i class="fas fa-lock me-1"></i>Admin</a></li>
                        <li class="nav-item"><a class="nav-link" href="/includes/logout.php">Logout</a></li>
                    <?php elseif ($isLoggedIn): ?>
                        <li class="nav-item"><a class="nav-link" href="/">Home</a></li>
                        <li class="nav-item"><a class="nav-link" href="/my-flights.php">My Flights</a></li>
                        <li class="nav-item"><a class="nav-link" href="/feedback.php">Feedback</a></li>
                        <li class="nav-item"><a class="nav-link fw-bold text-info" href="/profile.php">
                            <i class="fas fa-user-circle me-1"></i><?php echo htmlspecialchars($user['name']); ?>
                        </a></li>
                        <li class="nav-item"><a class="nav-link" href="/includes/logout.php">Logout</a></li>
                    <?php else: ?>
                        <li class="nav-item"><a class="nav-link" href="/">Home</a></li>
                        <li class="nav-item"><a class="nav-link" href="/login.php">Login</a></li>
                        <li class="nav-item"><a class="nav-link" href="/register.php">Register</a></li>
                    <?php endif; ?>
                </ul>
            </div>
        </div>
    </nav>
3. includes/footer.php
php
    <!-- Footer -->
    <footer class="bg-dark text-light py-5 mt-5">
        <div class="container">
            <div class="row g-4">
                <div class="col-md-4">
                    <h5 class="Montserrat font-bold mb-3">ETA Tour & Travel Agency</h5>
                    <p class="text-secondary">Simplifying air travel with cutting-edge booking technology. Trusted by millions of travelers worldwide.</p>
                </div>
                <div class="col-md-2">
                    <h6>Explore</h6>
                    <ul class="list-unstyled text-secondary">
                        <li><a href="/" class="text-decoration-none text-secondary">Flights</a></li>
                        <li><a href="/feedback.php" class="text-decoration-none text-secondary">Feedback</a></li>
                        <li><a href="#" class="text-decoration-none text-secondary">Destinations</a></li>
                    </ul>
                </div>
                <div class="col-md-3">
                    <h6>Support</h6>
                    <ul class="list-unstyled text-secondary">
                        <li><i class="fas fa-headset me-2"></i> 24/7 Help Center: +8809658001016</li>
                        <li><i class="fas fa-envelope me-2"></i> sales@etatourtravel.com</li>
                    </ul>
                </div>
                <div class="col-md-3 text-md-end">
                    <a class="btn btn-outline-light btn-sm mb-3" href="/admin/login.php">
                        <i class="fas fa-user-shield me-2"></i>Staff Portal
                    </a>
                    <p class="small text-secondary">© 2026 ETA Tour & Travel Agency. Developed by etatourtravel.com.</p>
                </div>
            </div>
        </div>
    </footer>

    <!-- Scripts -->
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.0/jquery.min.js"></script>
    <script src="/assets/js/app.js"></script>
</body>
</html>
4. index.php (Homepage)
php
<?php
require_once 'includes/header.php';

// Get flights from database
$db = Database::getInstance()->getConnection();
$stmt = $db->query("SELECT * FROM flights WHERE departure_date >= CURDATE() ORDER BY departure_date ASC");
$flights = $stmt->fetchAll();

// Process search if submitted
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['search'])) {
    $from = $_POST['from'];
    $to = $_POST['to'];
    $depart_date = $_POST['depart_date'];
    $trip_type = $_POST['trip_type'];
    
    $sql = "SELECT * FROM flights WHERE departure_airport LIKE ? AND arrival_airport LIKE ? 
            AND DATE(departure_date) = ?";
    
    $stmt = $db->prepare($sql);
    $stmt->execute(["%$from%", "%$to%", $depart_date]);
    $flights = $stmt->fetchAll();
}
?>

<section class="hero-section">
    <div class="container">
        <h1 class="display-3 fw-bold mb-3">Your Journey Starts Here</h1>
        <p class="lead mb-0">Explore new horizons with affordable and reliable flight options.</p>
    </div>
</section>

<div class="container search-wrapper">
    <div class="search-card">
        <form method="POST" action="" class="row g-3">
            <div class="col-md-3">
                <label class="form-label small fw-bold">Departure City</label>
                <select class="form-select" name="from" required>
                    <option value="">Select City</option>
                    <option value="DAC">Dhaka (DAC)</option>
                    <option value="CGP">Chittagong (CGP)</option>
                    <option value="ZYL">Sylhet (ZYL)</option>
                    <option value="CXB">Cox's Bazar (CXB)</option>
                    <option value="JSR">Jessore (JSR)</option>
                </select>
            </div>
            <div class="col-md-3">
                <label class="form-label small fw-bold">Destination</label>
                <select class="form-select" name="to" required>
                    <option value="">Select City</option>
                    <option value="DAC">Dhaka (DAC)</option>
                    <option value="CGP">Chittagong (CGP)</option>
                    <option value="ZYL">Sylhet (ZYL)</option>
                    <option value="CXB">Cox's Bazar (CXB)</option>
                    <option value="JSR">Jessore (JSR)</option>
                </select>
            </div>
            <div class="col-md-2">
                <label class="form-label small fw-bold">Depart Date</label>
                <input type="date" class="form-control" name="depart_date" 
                       value="<?php echo date('Y-m-d', strtotime('+1 day')); ?>" required>
            </div>
            <div class="col-md-2">
                <label class="form-label small fw-bold">Passengers</label>
                <select class="form-select" name="passengers">
                    <option value="1">1 Passenger</option>
                    <option value="2">2 Passengers</option>
                    <option value="3">3 Passengers</option>
                    <option value="4">4 Passengers</option>
                </select>
            </div>
            <div class="col-md-2 d-flex align-items-end">
                <button type="submit" name="search" class="btn btn-primary w-100 py-2 fw-bold">
                    <i class="fas fa-search me-2"></i>Search Flights
                </button>
            </div>
        </form>
    </div>
</div>

<div class="container py-5">
    <div class="d-flex justify-content-between align-items-center mb-4">
        <h3 class="mb-0">Available Flights</h3>
        <span class="text-muted"><?php echo count($flights); ?> flights available</span>
    </div>
    
    <div class="row">
        <?php if (empty($flights)): ?>
            <div class="col-12 text-center py-5">
                <i class="fas fa-plane-slash fa-3x text-muted mb-3"></i>
                <h4>No flights found</h4>
                <p class="text-muted">Try adjusting your search criteria</p>
            </div>
        <?php else: ?>
            <?php foreach ($flights as $flight): ?>
                <div class="col-md-6 col-lg-4 mb-4">
                    <div class="flight-card">
                        <div class="d-flex justify-content-between mb-3">
                            <span class="fw-bold text-primary"><?php echo htmlspecialchars($flight['airline']); ?></span>
                            <span class="status-badge status-<?php echo $flight['status']; ?>">
                                <?php echo ucfirst($flight['status']); ?>
                            </span>
                        </div>
                        <div class="row align-items-center mb-4">
                            <div class="col-5">
                                <div class="h5 mb-0"><?php echo $flight['departure_airport']; ?></div>
                                <small class="text-muted"><?php echo date('H:i', strtotime($flight['departure_date'])); ?></small>
                            </div>
                            <div class="col-2 text-center text-muted">
                                <i class="fas fa-plane"></i>
                            </div>
                            <div class="col-5 text-end">
                                <div class="h5 mb-0"><?php echo $flight['arrival_airport']; ?></div>
                                <small class="text-muted"><?php echo date('H:i', strtotime($flight['arrival_date'])); ?></small>
                            </div>
                        </div>
                        <div class="d-flex justify-content-between align-items-center">
                            <div>
                                <span class="text-muted small">Price</span>
                                <div class="h4 mb-0 text-success">BDT <?php echo number_format($flight['price']); ?></div>
                                <small class="text-muted"><?php echo $flight['class']; ?> • <?php echo $flight['flight_number']; ?></small>
                            </div>
                            <a href="/book-flight.php?id=<?php echo $flight['id']; ?>" 
                               class="btn btn-primary btn-sm px-4 rounded-pill">Book Now</a>
                        </div>
                    </div>
                </div>
            <?php endforeach; ?>
        <?php endif; ?>
    </div>
</div>

<?php require_once 'includes/footer.php'; ?>
5. assets/css/style.css
css
:root {
    --primary: #376b8d;
    --secondary: #4a6491;
    --accent: #4caf50;
    --dark: #1a252f;
    --light: #f8f9fa;
    --admin-bg: #f4f7f6;
    --transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}

body {
    font-family: 'Assistant', sans-serif;
    background-color: #f0f2f5;
    overflow-x: hidden;
    min-height: 100vh;
}

h1, h2, h3, .navbar-brand {
    font-family: 'Montserrat', sans-serif;
}

/* Navbar Styling */
.navbar {
    background-color: var(--dark) !important;
    box-shadow: 0 2px 10px rgba(0,0,0,0.2);
}
.navbar-brand img { 
    height: 35px; 
    margin-right: 10px; 
}

/* Hero Section */
.hero-section {
    background: linear-gradient(rgba(0, 0, 0, 0.6), rgba(0, 0, 0, 0.6)), 
                url('https://images.unsplash.com/photo-1436491865332-7a61a109cc05?auto=format&fit=crop&w=1350&q=80');
    background-size: cover;
    background-position: center;
    color: white;
    padding: 120px 0 160px;
    text-align: center;
}

/* Search Container */
.search-wrapper {
    margin-top: -80px;
    position: relative;
    z-index: 10;
}
.search-card {
    background: white;
    border-radius: 20px;
    padding: 30px;
    box-shadow: 0 15px 35px rgba(0,0,0,0.1);
}

/* Component Styles */
.flight-card {
    background: white;
    border-radius: 12px;
    padding: 20px;
    margin-bottom: 20px;
    border: 1px solid #eee;
    transition: var(--transition);
}
.flight-card:hover {
    transform: translateY(-5px);
    box-shadow: 0 8px 25px rgba(0,0,0,0.08);
}

.status-badge {
    font-size: 0.75rem;
    padding: 5px 12px;
    border-radius: 20px;
    font-weight: 700;
    text-transform: uppercase;
}
.status-scheduled { background: #e3f2fd; color: #1565c0; }
.status-departed { background: #fff3e0; color: #ef6c00; }
.status-arrived { background: #e8f5e9; color: #2e7d32; }
.status-issue { background: #ffebee; color: #c62828; }
.status-delayed { background: #fff3e0; color: #f57c00; }

/* Admin Dashboard Layout */
.admin-sidebar {
    background: var(--dark);
    min-height: calc(100vh - 56px);
    color: white;
    padding-top: 20px;
}
.admin-nav-link {
    color: #bdc3c7;
    padding: 12px 20px;
    display: block;
    text-decoration: none;
    transition: var(--transition);
    border-left: 4px solid transparent;
}
.admin-nav-link:hover, .admin-nav-link.active {
    color: white;
    background: rgba(255,255,255,0.05);
    border-left-color: var(--primary);
}

.stat-card {
    background: white;
    border-radius: 12px;
    padding: 20px;
    border-left: 5px solid var(--primary);
    box-shadow: 0 4px 6px rgba(0,0,0,0.05);
}

/* Booking Process */
.step-indicator {
    display: flex;
    justify-content: space-between;
    margin: 30px 0 40px;
    position: relative;
}
.step-indicator::before {
    content: '';
    position: absolute;
    top: 15px;
    left: 0;
    right: 0;
    height: 2px;
    background: #e0e0e0;
    z-index: 1;
}
.step {
    display: flex;
    flex-direction: column;
    align-items: center;
    position: relative;
    z-index: 2;
    background: white;
    padding: 10px;
}
.step-number {
    width: 30px;
    height: 30px;
    border-radius: 50%;
    background: #e0e0e0;
    color: #666;
    display: flex;
    align-items: center;
    justify-content: center;
    margin-bottom: 8px;
    font-weight: bold;
}
.step.active .step-number {
    background: var(--primary);
    color: white;
}
.step.completed .step-number {
    background: #4caf50;
    color: white;
}

/* E-Ticket Styles */
.ticket-container {
    border: 2px solid #424242;
    border-radius: 10px;
    overflow: hidden;
    max-width: 800px;
    margin: 0 auto;
}
.ticket-header {
    background: var(--primary);
    color: white;
    padding: 20px;
}
.ticket-body {
    padding: 30px;
    background: white;
}
.ticket-field {
    margin-bottom: 15px;
}
.ticket-label {
    font-size: 12px;
    color: #666;
    text-transform: uppercase;
    margin-bottom: 5px;
}
.ticket-value {
    font-size: 18px;
    font-weight: bold;
    color: github#333;
}
.ticket-qr {
    width: 150px;
    height: 150px;
    background: #f5f5f5;
    display: flex;
    align-items: center;
    justify-content: center;
    margin: 20px auto;
    border: 1px dashed #ccc;
}

/* Feedback Form Styles */
.feedback-container {
    background: rgba(3, 3, 3, 0.57);
    padding: 40px;
    border-radius: 10px;
    color: white;
}
.rating-stars {
    font-size: 30px;
    color: #ccc;
    cursor: pointer;
}
.rating-stars .active {
    color: #ffc107;
}

/* Login/Register Forms */
.auth-form {
    background: rgba(255,255,255,0.95);
    padding: 40px;
    border-radius: 15px;
    box-shadow: 0 10px 30px rgba(0,0,0,0.1);
    max-width: 500px;
    margin: 0 auto;
}
.form-animate-label {
    transition: all 0.3s ease;
    transform: translateY(-25px);
    font-size: 12px;
    color: var(--primary);
}

/* Utility */
.cursor-pointer { cursor: pointer; }
.hidden { display: none !important; }
.fade-in { animation: fadeIn 0.4s ease-in; }
@Keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }

@media print {
    .navbar, footer, .no-print { display: none !important; }
    .ticket-container { 
        box-shadow: none; 
        border: 1px solid #000;
        margin: 0;
        max-width: none;
    }
}
6. login.php
php
<?php
require_once 'includes/header.php';

// Handle login
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $email = $_POST['email'] ?? '';
    $password = $_POST['password'] ?? '';
    
    $db = Database::getInstance()->getConnection();
    $stmt = $db->prepare("SELECT * FROM users WHERE email = ? OR username = ?");
    $stmt->execute([$email, $email]);
    $user = $stmt->fetch();
    
    if ($user && password_verify($password, $user['password'])) {
        $_SESSION['user'] = $user;
        $_SESSION['is_admin'] = $user['is_admin'] == 1;
        
        header("Location: /");
        exit();
    } else {
        $error = "Invalid credentials";
    }
}
?>

<div class="container py-5">
    <div class="row justify-content-center">
        <div class="col-md-5">
            <div class="auth-form">
                <h2 class="text-center mb-4">Login</h2>
                
                <?php if (isset($error)): ?>
                    <div class="alert alert-danger"><?php echo $error; ?></div>
                <?php endif; ?>
                
                <form method="POST" action="">
                    <div class="mb-3">
                        <label class="form-label">Email or Username</label>
                        <div class="input-group">
                            <span class="input-group-text"><i class="fas fa-user"></i></span>
                            <input type="text" class="form-control" name="email" required>
                        </div>
                    </div>
                    <div class="mb-4">
                        <label class="form-label">Password</label>
                        <div class="input-group">
                            <span class="input-group-text"><i class="fas fa-lock"></i></span>
                            <input type="password" class="form-control" name="password" required>
                        </div>
                    </div>
                    <div class="mb-3">
                        <a href="/reset-password.php" class="text-decoration-none">
                            Forgot Password?
                        </a>
                    </div>
                    <button type="submit" class="btn btn-primary w-100 py-2 mb-3">
                        <i class="fas fa-sign-in-alt me-2"></i>Login
                    </button>
                    <div class="text-center">
                        <span class="text-muted">Don't have an account?</span>
                        <a href="/register.php" class="text-decoration-none ms-1">
                            Register here
                        </a>
                    </div>
                </form>
            </div>
        </div>
    </div>
</div>

<?php require_once 'includes/footer.php'; ?>
7. register.php
php
<?php
require_once 'includes/header.php';

// Handle registration
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $first_name = $_POST['first_name'];
    $last_name = $_POST['last_name'];
    $email = $_POST['email'];
    $username = $_POST['username'];
    $password = password_hash($_POST['password'], PASSWORD_DEFAULT);
    
    $db = Database::getInstance()->getConnection();
    
    // Check if user exists
    $stmt = $db->prepare("SELECT id FROM users WHERE email = ? OR username = ?");
    $stmt->execute([$email, $username]);
    
    if ($stmt->fetch()) {
        $error = "User already exists";
    } else {
        $stmt = $db->prepare("INSERT INTO users (first_name, last_name, email, username, password) 
                             VALUES (?, ?, ?, ?, ?)");
        if ($stmt->execute([$first_name, $last_name, $email, $username, $password])) {
            $_SESSION['user'] = [
                'id' => $db->lastInsertId(),
                'name' => "$first_name $last_name",
                'email' => $email,
                'username' => $username
            ];
            
            header("Location: /");
            exit();
        } else {
            $error = "Registration failed";
        }
    }
}
?>

<div class="container py-5">
    <div class="row justify-content-center">
        <div class="col-md-6">
            <div class="auth-form">
                <h2 class="text-center mb-4">Create Account</h2>
                
                <?php if (isset($error)): ?>
                    <div class="alert alert-danger"><?php echo $error; ?></div>
                <?php endif; ?>
                
                <form method="POST" action="">
                    <div class="row g-3">
                        <div class="col-md-6">
                            <label class="form-label">First Name</label>
                            <input type="text" class="form-control" name="first_name" required>
                        </div>
                        <div class="col-md-6">
                            <label class="form-label">Last Name</label>
                            <input type="text" class="form-control" name="last_name" required>
                        </div>
                    </div>
                    <div class="mb-3">
                        <label class="form-label">Email</label>
                        <input type="email" class="form-control" name="email" required>
                    </div>
                    <div class="mb-3">
                        <label class="form-label">Username</label>
                        <input type="text" class="form-control" name="username" required>
                    </div>
                    <div class="mb-3">
                        <label class="form-label">Password</label>
                        <input type="password" class="form-control" name="password" required>
                    </div>
                    <div class="mb-4">
                        <label class="form-label">Confirm Password</label>
                        <input type="password" class="form-control" name="confirm_password" required>
                    </div>
                    <button type="submit" class="btn btn-primary w-100 py-2 mb-3">
                        <i class="fas fa-user-plus me-2"></i>Register
                    </button>
                    <div class="text-center">
                        <span class="text-muted">Already have an account?</span>
                        <a href="/login.php" class="text-decoration-none ms-1">
                            Login here
                        </a>
                    </div>
                </form>
            </div>
        </div>
    </div>
</div>

<?php require_once 'includes/footer.php'; ?>
8. admin/dashboard.php
php
<?php
require_once '../includes/header.php';

// Check admin access
if (!isset($_SESSION['is_admin']) || !$_SESSION['is_admin']) {
    header("Location: /admin/login.php");
    exit();
}

$db = Database::getInstance()->getConnection();

// Get stats
$stats = [
    'total_passengers' => $db->query("SELECT SUM(passenger_count) as total FROM bookings")->fetch()['total'] ?? 0,
    'total_flights' => $db->query("SELECT COUNT(*) as total FROM flights WHERE status = 'scheduled'")->fetch()['total'],
    'total_bookings' => $db->query("SELECT COUNT(*) as total FROM bookings")->fetch()['total'],
    'total_revenue' => $db->query("SELECT SUM(total_amount) as total FROM bookings")->fetch()['total'] ?? 0
];

// Get recent flights
$recentFlights = $db->query("SELECT * FROM flights ORDER BY departure_date DESC LIMIT 5")->fetchAll();
?>

<div class="container-fluid">
    <div class="row">
        <div class="col-lg-2 p-0 admin-sidebar">
            <div class="px-4 mb-4">
                <span class="badge bg-primary w-100 py-2">System Admin</span>
            </div>
            <a href="/admin/dashboard.php" class="admin-nav-link active">
                <i class="fas fa-chart-line"></i> Dashboard
            </a>
            <a href="/admin/flights.php" class="admin-nav-link">
                <i class="fas fa-plane"></i> Manage Flights
            </a>
            <a href="/admin/bookings.php" class="admin-nav-link">
                <i class="fas fa-book"></i> Passenger List
            </a>
            <a href="/admin/feedback.php" class="admin-nav-link">
                <i class="fas fa-comments"></i> Feedback
            </a>
        </div>
        <div class="col-lg-10 p-4">
            <h2 class="mb-4">Operational Overview</h2>
            <div class="row g-4 mb-5">
                <div class="col-md-3">
                    <div class="stat-card">
                        <i class="fas fa-users text-primary fa-2x mb-2"></i>
                        <div class="h3 mb-0"><?php echo $stats['total_passengers']; ?></div>
                        <small class="text-muted">Total Passengers</small>
                    </div>
                </div>
                <div class="col-md-3">
                    <div class="stat-card" style="border-left-color: #2ecc71">
                        <i class="fas fa-plane-departure text-success fa-2x mb-2"></i>
                        <div class="h3 mb-0"><?php echo $stats['total_flights']; ?></div>
                        <small class="text-muted">Active Flights</small>
                    </div>
                </div>
                <div class="col-md-3">
                    <div class="stat-card" style="border-left-color: #f1c40f">
                        <i class="fas fa-ticket-alt text-warning fa-2x mb-2"></i>
                        <div class="h3 mb-0"><?php echo $stats['total_bookings']; ?></div>
                        <small class="text-muted">Total Bookings</small>
                    </div>
                </div>
                <div class="col-md-3">
                    <div class="stat-card" style="border-left-color: #e74c3c">
                        <i class="fas fa-money-bill-wave text-danger fa-2x mb-2"></i>
                        <div class="h3 mb-0">BDT <?php echo number_format($stats['total_revenue']); ?></div>
                        <small class="text-muted">Total Revenue</small>
                    </div>
                </div>
            </div>
            
            <div class="card shadow-sm border-0">
                <div class="card-header bg-white py-3 d-flex justify-content-between align-items-center">
                    <h5 class="mb-0">Recent Flight Operations</h5>
                    <a href="/admin/flights.php?action=add" class="btn btn-primary btn-sm">
                        <i class="fas fa-plus me-1"></i> Add Flight
                    </a>
                </div>
                <div class="card-body">
                    <div class="table-responsive">
                        <table class="table align-middle">
                            <thead class="table-light">
                                <tr>
                                    <th>Flight #</th>
                                    <th>Airline</th>
                                    <th>Route</th>
                                    <th>Departure</th>
                                    <th>Status</th>
                                    <th>Actions</th>
                                </tr>
                            </thead>
                            <tbody>
                                <?php foreach ($recentFlights as $flight): ?>
                                <tr>
                                    <td><?php echo $flight['flight_number']; ?></td>
                                    <td><?php echo $flight['airline']; ?></td>
                                    <td><?php echo $flight['departure_airport']; ?> → <?php echo $flight['arrival_airport']; ?></td>
                                    <td><?php echo date('Y-m-d H:i', strtotime($flight['departure_date'])); ?></td>
                                    <td>
                                        <span class="status-badge status-<?php echo $flight['status']; ?>">
                                            <?php echo ucfirst($flight['status']); ?>
                                        </span>
                                    </td>
                                    <td>
                                        <a href="/admin/flights.php?action=edit&id=<?php echo $flight['id']; ?>" 
                                           class="btn btn-sm btn-outline-primary">
                                            <i class="fas fa-edit"></i>
                                        </a>
                                    </td>
                                </tr>
                                <?php endforeach; ?>
                            </tbody>
                        </table>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

<?php require_once '../includes/footer.php'; ?>
9. SQL Database Schema
sql
-- Create database
CREATE DATABASE etatourtravel;
USE etatourtravel;

-- Users table
CREATE TABLE users (
    id INT PRIMARY KEY AUTO_INCREMENT,
    first_name VARCHAR(50) NOT NULL,
    last_name VARCHAR(50) NOT NULL,
    email VARCHAR(100) UNIQUE NOT NULL,
    username VARCHAR(50) UNIQUE NOT NULL,
    password VARCHAR(255) NOT NULL,
    phone VARCHAR(20),
    is_admin BOOLEAN DEFAULT FALSE,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

-- Flights table
CREATE TABLE flights (
    id INT PRIMARY KEY AUTO_INCREMENT,
    airline VARCHAR(100) NOT NULL,
    flight_number VARCHAR(20) NOT NULL,
    departure_airport VARCHAR(10) NOT NULL,
    arrival_airport VARCHAR(10) NOT NULL,
    departure_date DATETIME NOT NULL,
    arrival_date DATETIME NOT NULL,
    price DECIMAL(10,2) NOT NULL,
    class ENUM('Economy', 'Business', 'First') DEFAULT 'Economy',
    seats_available INT DEFAULT 100,
    status ENUM('scheduled', 'departed', 'arrived', 'delayed', 'cancelled') DEFAULT 'scheduled',
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- Bookings table
CREATE TABLE bookings (
    id INT PRIMARY KEY AUTO_INCREMENT,
    booking_reference VARCHAR(20) UNIQUE NOT NULL,
    user_id INT NOT NULL,
    flight_id INT NOT NULL,
    passenger_count INT DEFAULT 1,
    total_amount DECIMAL(10,2) NOT NULL,
    status ENUM('pending', 'confirmed', 'cancelled', 'completed') DEFAULT 'pending',
    payment_method VARCHAR(50),
    payment_status ENUM('pending', 'paid', 'failed') DEFAULT 'pending',
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (user_id) REFERENCES users(id),
    FOREIGN KEY (flight_id) REFERENCES flights(id)
);

-- Passengers table
CREATE TABLE passengers (
    id INT PRIMARY KEY AUTO_INCREMENT,
    booking_id INT NOT NULL,
    first_name VARCHAR(50) NOT NULL,
    middle_name VARCHAR(50),
    last_name VARCHAR(50) NOT NULL,
    date_of_birth DATE,
    contact_number VARCHAR(20),
    seat_number VARCHAR(10),
    FOREIGN KEY (booking_id) REFERENCES bookings(id) ON DELETE CASCADE
);

-- Feedback table
CREATE TABLE feedback (
    id INT PRIMARY KEY AUTO_INCREMENT,
    user_id INT,
    email VARCHAR(100) NOT NULL,
    feedback_text TEXT NOT NULL,
    rating INT DEFAULT 5,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (user_id) REFERENCES users(id)
);

-- Insert sample admin user (password: admin123)
INSERT INTO users (first_name, last_name, email, username, password, is_admin) 
VALUES ('Admin', 'User', 'admin@etatourtravel.com', 'admin', '$2y$10$YourHashedPasswordHere', TRUE);

-- Insert sample flights
INSERT INTO flights (airline, flight_number, departure_airport, arrival_airport, departure_date, arrival_date, price, class, seats_available) VALUES
('Biman Bangladesh Airlines', 'BG 101', 'DAC', 'CGP', '2024-03-15 08:00:00', '2024-03-15 09:00:00', 8500.00, 'Economy', 95),
('US-Bangla Airlines', 'BS 202', 'DAC', 'ZYL', '2024-03-15 10:30:00', '2024-03-15 11:30:00', 9200.00, 'Business', 20),
('Novoair', 'VQ 303', 'CGP', 'CXB', '2024-03-16 07:15:00', '2024-03-16 07:45:00', 6500.00, 'Economy', 100),
('Air Astra', '2A 404', 'DAC', 'JSR', '2024-03-16 14:20:00', '2024-03-16 15:10:00', 7500.00, 'Economy', 85);
10. .htaccess (for URL rewriting)
apache
RewriteEngine On
RewriteBase /

# Remove .php extension
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^([^\.]+)$ $1.php [NC,L]

# Redirect to index.php for clean URLs
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?path=$1 [QSA,L]
11. includes/logout.php
php
<?php
session_start();
session_destroy();
header("Location: /login.php");
exit();
?>
Installation Instructions:
Setup Requirements:

bash
# PHP 8.2
sudo apt install php8.2 php8.2-mysql php8.2-curl php8.2-gd php8.2-mbstring
Install Apache & MySQL:

bash
sudo apt install apache2 mysql-server
sudo mysql_secure_installation
Configure Database:

bash
mysql -u root -p
# Run the SQL schema provided above
Set Permissions:

bash
chmod -R 755 etatourtravel/
chown -R www-data:www-data etatourtravel/
Configure Apache Virtual Host:

apache
<VirtualHost *:80>
    ServerName etatourtravel.local
    DocumentRoot /var/www/etatourtravel
    <Directory /var/www/etatourtravel>
        Options Indexes FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>
</VirtualHost>
Enable mod_rewrite:

bash
sudo a2enmod rewrite
sudo systemctl restart apache2
Key Features of PHP Version:
Security:

Prepared statements for SQL queries

Password hashing with password_hash()

Input sanitization with htmlspecialchars()

Session-based authentication

Performance:

PDO database connection with persistent connection

Caching mechanisms (can be added)

Optimized queries

Structure:

MVC-like architecture

Separation of concerns

Reusable components

Proper error handling

Admin Features:

Full CRUD for flights

Booking management

User management

Dashboard with statistics

Booking System:

Multi-step booking process

Payment integration ready

E-ticket generation

Email notifications (can be added)

The application is now a fully functional PHP 8.2 application with proper database integration
Copy link
Author

@Deloper11 Deloper11 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Directory Structure
text
etatourtravel/
├── index.php (homepage)
├── config/
│ ├── database.php
│ └── constants.php
├── includes/
│ ├── header.php
│ ├── footer.php
│ └── functions.php
├── templates/ (all the template pages)
├── assets/
│ ├── css/
│ │ └── style.css
│ └── js/
│ └── app.js
├── classes/ (PHP classes)
├── api/ (API endpoints)
├── admin/ (admin panel)
└── data/ (data storage)
Step 1: Main Files

  1. config/database.php
    php
connection = new PDO( "mysql:host=" . DB_HOST . ";dbname=" . DB_NAME . ";charset=utf8mb4", DB_USER, DB_PASS, [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::ATTR_EMULATE_PREPARES => false ] ); } catch (PDOException $e) { die("Connection failed: " . $e->getMessage()); } } public static function getInstance() { if (self::$instance === null) { self::$instance = new self(); } return self::$instance; } public function getConnection() { return $this->connection; } } ?>
  1. includes/header.php
    php
<title>etatourtravel.com | Flight Booking & Admin System</title>
<!-- External Assets -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<link href="https://fonts.googleapis.com/css2?family=Assistant:wght@300;400;600&family=Montserrat:wght@500;700&display=swap" rel="stylesheet">

<!-- Main Styles -->
<link rel="stylesheet" href="/assets/css/style.css">
<!-- Main Navigation -->
<nav class="navbar navbar-expand-lg navbar-dark sticky-top">
    <div class="container">
        <a class="navbar-brand" href="/">
            <img src="https://cdn-icons-png.flaticon.com/512/824/824100.png" alt="Logo">
            <span>ETA Tour & Travel Agency</span>
        </a>
        <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
            <span class="navbar-toggler-icon"></span>
        </button>
        <div class="collapse navbar-collapse" id="navbarNav">
            <ul class="navbar-nav ms-auto">
                <?php if ($isAdmin): ?>
                    <li class="nav-item"><a class="nav-link text-warning" href="/admin/dashboard.php"><i class="fas fa-lock me-1"></i>Admin</a></li>
                    <li class="nav-item"><a class="nav-link" href="/includes/logout.php">Logout</a></li>
                <?php elseif ($isLoggedIn): ?>
                    <li class="nav-item"><a class="nav-link" href="/">Home</a></li>
                    <li class="nav-item"><a class="nav-link" href="/my-flights.php">My Flights</a></li>
                    <li class="nav-item"><a class="nav-link" href="/feedback.php">Feedback</a></li>
                    <li class="nav-item"><a class="nav-link fw-bold text-info" href="/profile.php">
                        <i class="fas fa-user-circle me-1"></i><?php echo htmlspecialchars($user['name']); ?>
                    </a></li>
                    <li class="nav-item"><a class="nav-link" href="/includes/logout.php">Logout</a></li>
                <?php else: ?>
                    <li class="nav-item"><a class="nav-link" href="/">Home</a></li>
                    <li class="nav-item"><a class="nav-link" href="/login.php">Login</a></li>
                    <li class="nav-item"><a class="nav-link" href="/register.php">Register</a></li>
                <?php endif; ?>
            </ul>
        </div>
    </div>
</nav>
  1. includes/footer.php
    php

    ETA Tour & Travel Agency

    Simplifying air travel with cutting-edge booking technology. Trusted by millions of travelers worldwide.

    Support
    • 24/7 Help Center: +8809658001016
    • sales@etatourtravel.com
    Staff Portal

    © 2026 ETA Tour & Travel Agency. Developed by etatourtravel.com.

    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.0/jquery.min.js"></script> <script src="/assets/js/app.js"></script>
4. index.php (Homepage) php // Get flights from database
$db = Database::getInstance()->getConnection();
$stmt = $db->query("SELECT * FROM flights WHERE departure_date >= CURDATE() ORDER BY departure_date ASC");
$flights = $stmt->fetchAll();

// Process search if submitted
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['search'])) {
$from = $_POST['from'];
$to = $_POST['to'];
$depart_date = $_POST['depart_date'];
$trip_type = $_POST['trip_type'];

$sql = "SELECT * FROM flights WHERE departure_airport LIKE ? AND arrival_airport LIKE ? 
        AND DATE(departure_date) = ?";

$stmt = $db->prepare($sql);
$stmt->execute(["%$from%", "%$to%", $depart_date]);
$flights = $stmt->fetchAll();

}
?>

Your Journey Starts Here

Explore new horizons with affordable and reliable flight options.

Departure City Select City Dhaka (DAC) Chittagong (CGP) Sylhet (ZYL) Cox's Bazar (CXB) Jessore (JSR)
Destination Select City Dhaka (DAC) Chittagong (CGP) Sylhet (ZYL) Cox's Bazar (CXB) Jessore (JSR)
Depart Date
Passengers 1 Passenger 2 Passengers 3 Passengers 4 Passengers
Search Flights

Available Flights

flights available
<div class="row">
    <?php if (empty($flights)): ?>
        <div class="col-12 text-center py-5">
            <i class="fas fa-plane-slash fa-3x text-muted mb-3"></i>
            <h4>No flights found</h4>
            <p class="text-muted">Try adjusting your search criteria</p>
        </div>
    <?php else: ?>
        <?php foreach ($flights as $flight): ?>
            <div class="col-md-6 col-lg-4 mb-4">
                <div class="flight-card">
                    <div class="d-flex justify-content-between mb-3">
                        <span class="fw-bold text-primary"><?php echo htmlspecialchars($flight['airline']); ?></span>
                        <span class="status-badge status-<?php echo $flight['status']; ?>">
                            <?php echo ucfirst($flight['status']); ?>
                        </span>
                    </div>
                    <div class="row align-items-center mb-4">
                        <div class="col-5">
                            <div class="h5 mb-0"><?php echo $flight['departure_airport']; ?></div>
                            <small class="text-muted"><?php echo date('H:i', strtotime($flight['departure_date'])); ?></small>
                        </div>
                        <div class="col-2 text-center text-muted">
                            <i class="fas fa-plane"></i>
                        </div>
                        <div class="col-5 text-end">
                            <div class="h5 mb-0"><?php echo $flight['arrival_airport']; ?></div>
                            <small class="text-muted"><?php echo date('H:i', strtotime($flight['arrival_date'])); ?></small>
                        </div>
                    </div>
                    <div class="d-flex justify-content-between align-items-center">
                        <div>
                            <span class="text-muted small">Price</span>
                            <div class="h4 mb-0 text-success">BDT <?php echo number_format($flight['price']); ?></div>
                            <small class="text-muted"><?php echo $flight['class']; ?> • <?php echo $flight['flight_number']; ?></small>
                        </div>
                        <a href="/book-flight.php?id=<?php echo $flight['id']; ?>" 
                           class="btn btn-primary btn-sm px-4 rounded-pill">Book Now</a>
                    </div>
                </div>
            </div>
        <?php endforeach; ?>
    <?php endif; ?>
</div>
  1. assets/css/style.css
    css
    :root {
    --primary: #376b8d;
    --secondary: #4a6491;
    --accent: #4caf50;
    --dark: #1a252f;
    --light: #f8f9fa;
    --admin-bg: #f4f7f6;
    --transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
    }

body {
font-family: 'Assistant', sans-serif;
background-color: #f0f2f5;
overflow-x: hidden;
min-height: 100vh;
}

h1, h2, h3, .navbar-brand {
font-family: 'Montserrat', sans-serif;
}

/* Navbar Styling */
.navbar {
background-color: var(--dark) !important;
box-shadow: 0 2px 10px rgba(0,0,0,0.2);
}
.navbar-brand img {
height: 35px;
margin-right: 10px;
}

/* Hero Section */
.hero-section {
background: linear-gradient(rgba(0, 0, 0, 0.6), rgba(0, 0, 0, 0.6)),
url('https://images.unsplash.com/photo-1436491865332-7a61a109cc05?auto=format&fit=crop&w=1350&q=80');
background-size: cover;
background-position: center;
color: white;
padding: 120px 0 160px;
text-align: center;
}

/* Search Container */
.search-wrapper {
margin-top: -80px;
position: relative;
z-index: 10;
}
.search-card {
background: white;
border-radius: 20px;
padding: 30px;
box-shadow: 0 15px 35px rgba(0,0,0,0.1);
}

/* Component Styles */
.flight-card {
background: white;
border-radius: 12px;
padding: 20px;
margin-bottom: 20px;
border: 1px solid #eee;
transition: var(--transition);
}
.flight-card:hover {
transform: translateY(-5px);
box-shadow: 0 8px 25px rgba(0,0,0,0.08);
}

.status-badge {
font-size: 0.75rem;
padding: 5px 12px;
border-radius: 20px;
font-weight: 700;
text-transform: uppercase;
}
.status-scheduled { background: #e3f2fd; color: #1565c0; }
.status-departed { background: #fff3e0; color: #ef6c00; }
.status-arrived { background: #e8f5e9; color: #2e7d32; }
.status-issue { background: #ffebee; color: #c62828; }
.status-delayed { background: #fff3e0; color: #f57c00; }

/* Admin Dashboard Layout */
.admin-sidebar {
background: var(--dark);
min-height: calc(100vh - 56px);
color: white;
padding-top: 20px;
}
.admin-nav-link {
color: #bdc3c7;
padding: 12px 20px;
display: block;
text-decoration: none;
transition: var(--transition);
border-left: 4px solid transparent;
}
.admin-nav-link:hover, .admin-nav-link.active {
color: white;
background: rgba(255,255,255,0.05);
border-left-color: var(--primary);
}

.stat-card {
background: white;
border-radius: 12px;
padding: 20px;
border-left: 5px solid var(--primary);
box-shadow: 0 4px 6px rgba(0,0,0,0.05);
}

/* Booking Process */
.step-indicator {
display: flex;
justify-content: space-between;
margin: 30px 0 40px;
position: relative;
}
.step-indicator::before {
content: '';
position: absolute;
top: 15px;
left: 0;
right: 0;
height: 2px;
background: #e0e0e0;
z-index: 1;
}
.step {
display: flex;
flex-direction: column;
align-items: center;
position: relative;
z-index: 2;
background: white;
padding: 10px;
}
.step-number {
width: 30px;
height: 30px;
border-radius: 50%;
background: #e0e0e0;
color: #666;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 8px;
font-weight: bold;
}
.step.active .step-number {
background: var(--primary);
color: white;
}
.step.completed .step-number {
background: #4caf50;
color: white;
}

/* E-Ticket Styles */
.ticket-container {
border: 2px solid #424242;
border-radius: 10px;
overflow: hidden;
max-width: 800px;
margin: 0 auto;
}
.ticket-header {
background: var(--primary);
color: white;
padding: 20px;
}
.ticket-body {
padding: 30px;
background: white;
}
.ticket-field {
margin-bottom: 15px;
}
.ticket-label {
font-size: 12px;
color: #666;
text-transform: uppercase;
margin-bottom: 5px;
}
.ticket-value {
font-size: 18px;
font-weight: bold;
color: #333;
}
.ticket-qr {
width: 150px;
height: 150px;
background: #f5f5f5;
display: flex;
align-items: center;
justify-content: center;
margin: 20px auto;
border: 1px dashed #ccc;
}

/* Feedback Form Styles */
.feedback-container {
background: rgba(3, 3, 3, 0.57);
padding: 40px;
border-radius: 10px;
color: white;
}
.rating-stars {
font-size: 30px;
color: #ccc;
cursor: pointer;
}
.rating-stars .active {
color: #ffc107;
}

/* Login/Register Forms */
.auth-form {
background: rgba(255,255,255,0.95);
padding: 40px;
border-radius: 15px;
box-shadow: 0 10px 30px rgba(0,0,0,0.1);
max-width: 500px;
margin: 0 auto;
}
.form-animate-label {
transition: all 0.3s ease;
transform: translateY(-25px);
font-size: 12px;
color: var(--primary);
}

/* Utility */
.cursor-pointer { cursor: pointer; }
.hidden { display: none !important; }
.fade-in { animation: fadeIn 0.4s ease-in; }
@Keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }

@media print {
.navbar, footer, .no-print { display: none !important; }
.ticket-container {
box-shadow: none;
border: 1px solid #000;
margin: 0;
max-width: none;
}
}
6. login.php
php

getConnection(); $stmt = $db->prepare("SELECT * FROM users WHERE email = ? OR username = ?"); $stmt->execute([$email, $email]); $user = $stmt->fetch(); if ($user && password_verify($password, $user['password'])) { $_SESSION['user'] = $user; $_SESSION['is_admin'] = $user['is_admin'] == 1; header("Location: /"); exit(); } else { $error = "Invalid credentials"; } } ?>

Login

            <?php if (isset($error)): ?>
                <div class="alert alert-danger"><?php echo $error; ?></div>
            <?php endif; ?>
            
            <form method="POST" action="">
                <div class="mb-3">
                    <label class="form-label">Email or Username</label>
                    <div class="input-group">
                        <span class="input-group-text"><i class="fas fa-user"></i></span>
                        <input type="text" class="form-control" name="email" required>
                    </div>
                </div>
                <div class="mb-4">
                    <label class="form-label">Password</label>
                    <div class="input-group">
                        <span class="input-group-text"><i class="fas fa-lock"></i></span>
                        <input type="password" class="form-control" name="password" required>
                    </div>
                </div>
                <div class="mb-3">
                    <a href="/reset-password.php" class="text-decoration-none">
                        Forgot Password?
                    </a>
                </div>
                <button type="submit" class="btn btn-primary w-100 py-2 mb-3">
                    <i class="fas fa-sign-in-alt me-2"></i>Login
                </button>
                <div class="text-center">
                    <span class="text-muted">Don't have an account?</span>
                    <a href="/register.php" class="text-decoration-none ms-1">
                        Register here
                    </a>
                </div>
            </form>
        </div>
    </div>
</div>
  1. register.php
    php
getConnection(); // Check if user exists $stmt = $db->prepare("SELECT id FROM users WHERE email = ? OR username = ?"); $stmt->execute([$email, $username]); if ($stmt->fetch()) { $error = "User already exists"; } else { $stmt = $db->prepare("INSERT INTO users (first_name, last_name, email, username, password) VALUES (?, ?, ?, ?, ?)"); if ($stmt->execute([$first_name, $last_name, $email, $username, $password])) { $_SESSION['user'] = [ 'id' => $db->lastInsertId(), 'name' => "$first_name $last_name", 'email' => $email, 'username' => $username ]; header("Location: /"); exit(); } else { $error = "Registration failed"; } } } ?>

Create Account

            <?php if (isset($error)): ?>
                <div class="alert alert-danger"><?php echo $error; ?></div>
            <?php endif; ?>
            
            <form method="POST" action="">
                <div class="row g-3">
                    <div class="col-md-6">
                        <label class="form-label">First Name</label>
                        <input type="text" class="form-control" name="first_name" required>
                    </div>
                    <div class="col-md-6">
                        <label class="form-label">Last Name</label>
                        <input type="text" class="form-control" name="last_name" required>
                    </div>
                </div>
                <div class="mb-3">
                    <label class="form-label">Email</label>
                    <input type="email" class="form-control" name="email" required>
                </div>
                <div class="mb-3">
                    <label class="form-label">Username</label>
                    <input type="text" class="form-control" name="username" required>
                </div>
                <div class="mb-3">
                    <label class="form-label">Password</label>
                    <input type="password" class="form-control" name="password" required>
                </div>
                <div class="mb-4">
                    <label class="form-label">Confirm Password</label>
                    <input type="password" class="form-control" name="confirm_password" required>
                </div>
                <button type="submit" class="btn btn-primary w-100 py-2 mb-3">
                    <i class="fas fa-user-plus me-2"></i>Register
                </button>
                <div class="text-center">
                    <span class="text-muted">Already have an account?</span>
                    <a href="/login.php" class="text-decoration-none ms-1">
                        Login here
                    </a>
                </div>
            </form>
        </div>
    </div>
</div>
  1. admin/dashboard.php
    php
getConnection(); // Get stats $stats = [ 'total_passengers' => $db->query("SELECT SUM(passenger_count) as total FROM bookings")->fetch()['total'] ?? 0, 'total_flights' => $db->query("SELECT COUNT(*) as total FROM flights WHERE status = 'scheduled'")->fetch()['total'], 'total_bookings' => $db->query("SELECT COUNT(*) as total FROM bookings")->fetch()['total'], 'total_revenue' => $db->query("SELECT SUM(total_amount) as total FROM bookings")->fetch()['total'] ?? 0 ]; // Get recent flights $recentFlights = $db->query("SELECT * FROM flights ORDER BY departure_date DESC LIMIT 5")->fetchAll(); ?>

Operational Overview

Total Passengers
Active Flights
Total Bookings
BDT
Total Revenue
        <div class="card shadow-sm border-0">
            <div class="card-header bg-white py-3 d-flex justify-content-between align-items-center">
                <h5 class="mb-0">Recent Flight Operations</h5>
                <a href="/admin/flights.php?action=add" class="btn btn-primary btn-sm">
                    <i class="fas fa-plus me-1"></i> Add Flight
                </a>
            </div>
            <div class="card-body">
                <div class="table-responsive">
                    <table class="table align-middle">
                        <thead class="table-light">
                            <tr>
                                <th>Flight #</th>
                                <th>Airline</th>
                                <th>Route</th>
                                <th>Departure</th>
                                <th>Status</th>
                                <th>Actions</th>
                            </tr>
                        </thead>
                        <tbody>
                            <?php foreach ($recentFlights as $flight): ?>
                            <tr>
                                <td><?php echo $flight['flight_number']; ?></td>
                                <td><?php echo $flight['airline']; ?></td>
                                <td><?php echo $flight['departure_airport']; ?> → <?php echo $flight['arrival_airport']; ?></td>
                                <td><?php echo date('Y-m-d H:i', strtotime($flight['departure_date'])); ?></td>
                                <td>
                                    <span class="status-badge status-<?php echo $flight['status']; ?>">
                                        <?php echo ucfirst($flight['status']); ?>
                                    </span>
                                </td>
                                <td>
                                    <a href="/admin/flights.php?action=edit&id=<?php echo $flight['id']; ?>" 
                                       class="btn btn-sm btn-outline-primary">
                                        <i class="fas fa-edit"></i>
                                    </a>
                                </td>
                            </tr>
                            <?php endforeach; ?>
                        </tbody>
                    </table>
                </div>
            </div>
        </div>
    </div>
</div>
  1. SQL Database Schema
    sql
    -- Create database
    CREATE DATABASE etatourtravel;
    USE etatourtravel;

-- Users table
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT,
first_name VARCHAR(50) NOT NULL,
last_name VARCHAR(50) NOT NULL,
email VARCHAR(100) UNIQUE NOT NULL,
username VARCHAR(50) UNIQUE NOT NULL,
password VARCHAR(255) NOT NULL,
phone VARCHAR(20),
is_admin BOOLEAN DEFAULT FALSE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

-- Flights table
CREATE TABLE flights (
id INT PRIMARY KEY AUTO_INCREMENT,
airline VARCHAR(100) NOT NULL,
flight_number VARCHAR(20) NOT NULL,
departure_airport VARCHAR(10) NOT NULL,
arrival_airport VARCHAR(10) NOT NULL,
departure_date DATETIME NOT NULL,
arrival_date DATETIME NOT NULL,
price DECIMAL(10,2) NOT NULL,
class ENUM('Economy', 'Business', 'First') DEFAULT 'Economy',
seats_available INT DEFAULT 100,
status ENUM('scheduled', 'departed', 'arrived', 'delayed', 'cancelled') DEFAULT 'scheduled',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- Bookings table
CREATE TABLE bookings (
id INT PRIMARY KEY AUTO_INCREMENT,
booking_reference VARCHAR(20) UNIQUE NOT NULL,
user_id INT NOT NULL,
flight_id INT NOT NULL,
passenger_count INT DEFAULT 1,
total_amount DECIMAL(10,2) NOT NULL,
status ENUM('pending', 'confirmed', 'cancelled', 'completed') DEFAULT 'pending',
payment_method VARCHAR(50),
payment_status ENUM('pending', 'paid', 'failed') DEFAULT 'pending',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id),
FOREIGN KEY (flight_id) REFERENCES flights(id)
);

-- Passengers table
CREATE TABLE passengers (
id INT PRIMARY KEY AUTO_INCREMENT,
booking_id INT NOT NULL,
first_name VARCHAR(50) NOT NULL,
middle_name VARCHAR(50),
last_name VARCHAR(50) NOT NULL,
date_of_birth DATE,
contact_number VARCHAR(20),
seat_number VARCHAR(10),
FOREIGN KEY (booking_id) REFERENCES bookings(id) ON DELETE CASCADE
);

-- Feedback table
CREATE TABLE feedback (
id INT PRIMARY KEY AUTO_INCREMENT,
user_id INT,
email VARCHAR(100) NOT NULL,
feedback_text TEXT NOT NULL,
rating INT DEFAULT 5,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id)
);

-- Insert sample admin user (password: admin123)
INSERT INTO users (first_name, last_name, email, username, password, is_admin)
VALUES ('Admin', 'User', 'admin@etatourtravel.com', 'admin', '$2y$10$YourHashedPasswordHere', TRUE);

-- Insert sample flights
INSERT INTO flights (airline, flight_number, departure_airport, arrival_airport, departure_date, arrival_date, price, class, seats_available) VALUES
('Biman Bangladesh Airlines', 'BG 101', 'DAC', 'CGP', '2024-03-15 08:00:00', '2024-03-15 09:00:00', 8500.00, 'Economy', 95),
('US-Bangla Airlines', 'BS 202', 'DAC', 'ZYL', '2024-03-15 10:30:00', '2024-03-15 11:30:00', 9200.00, 'Business', 20),
('Novoair', 'VQ 303', 'CGP', 'CXB', '2024-03-16 07:15:00', '2024-03-16 07:45:00', 6500.00, 'Economy', 100),
('Air Astra', '2A 404', 'DAC', 'JSR', '2024-03-16 14:20:00', '2024-03-16 15:10:00', 7500.00, 'Economy', 85);
10. .htaccess (for URL rewriting)
apache
RewriteEngine On
RewriteBase /

Remove .php extension

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^([^\.]+)$ $1.php [NC,L]

Redirect to index.php for clean URLs

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?path=$1 [QSA,L]
11. includes/logout.php
php

Installation Instructions:
Setup Requirements:

bash

PHP 8.2

sudo apt install php8.2 php8.2-mysql php8.2-curl php8.2-gd php8.2-mbstring
Install Apache & MySQL:

bash
sudo apt install apache2 mysql-server
sudo mysql_secure_installation
Configure Database:

bash
mysql -u root -p

Run the SQL schema provided above

Set Permissions:

bash
chmod -R 755 etatourtravel/
chown -R www-data:www-data etatourtravel/
Configure Apache Virtual Host:

apache
<VirtualHost *:80>
ServerName etatourtravel.local
DocumentRoot /var/www/etatourtravel
<Directory /var/www/etatourtravel>
Options Indexes FollowSymLinks
AllowOverride All
Require all granted


Enable mod_rewrite:

bash
sudo a2enmod rewrite
sudo systemctl restart apache2
Key Features of PHP Version:
Security:

Prepared statements for SQL queries

Password hashing with password_hash()

Input sanitization with htmlspecialchars()

Session-based authentication

Performance:

PDO database connection with persistent connection

Caching mechanisms (can be added)

Optimized queries

Structure:

MVC-like architecture

Separation of concerns

Reusable components

Proper error handling

Admin Features:

Full CRUD for flights

Booking management

User management

Dashboard with statistics

Booking System:

Multi-step booking process

Payment integration ready

E-ticket generation

Email notifications (can be added)

The application is now a fully functional PHP 8.2 application with proper database integration

@Deloper11 Deloper11 marked this pull request as draft February 8, 2026 15:45
@Deloper11 Deloper11 marked this pull request as ready for review February 8, 2026 15:45
@Deloper11 Deloper11 marked this pull request as draft February 8, 2026 15:45
@Deloper11 Deloper11 marked this pull request as ready for review February 8, 2026 15:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant