Conversation
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
Add files via upload
…g-PHP-8.2 Revert "Add files via upload"
Deloper11
left a comment
There was a problem hiding this comment.
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
- config/database.php
php
- includes/header.php
php
<!-- 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>
-
includes/footer.php
php<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>ETA Tour & Travel Agency
Simplifying air travel with cutting-edge booking technology. Trusted by millions of travelers worldwide.
Explore
Support
- 24/7 Help Center: +8809658001016
- sales@etatourtravel.com
Staff Portal© 2026 ETA Tour & Travel Agency. Developed by etatourtravel.com.
$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.
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>
- 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
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>
- register.php
php
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>
- admin/dashboard.php
php
Operational Overview
<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>
- 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
- config/database.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; } } ?>php
- includes/header.php
<title>etatourtravel.com | Flight Booking & Admin System</title>php
-
- Flights
- Feedback
- Destinations
- 24/7 Help Center: +8809658001016
- sales@etatourtravel.com
Staff Portal
<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 databaseincludes/footer.php
php
ETA Tour & Travel Agency
Simplifying air travel with cutting-edge booking technology. Trusted by millions of travelers worldwide.
Explore
Support
© 2026 ETA Tour & Travel Agency. Developed by etatourtravel.com.
$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'];
}
?>
Your Journey Starts Here
Explore new horizons with affordable and reliable flight options.
Available Flights
flights availablecss
: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 {
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"; } } ?>.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
Login
- register.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"; } } } ?>php
Create Account
- admin/dashboard.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(); ?>php
Operational Overview
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