Final Laravel Project: Student Management System

Lesson 50 of 50

100%

Congratulations! You have reached the final lesson.

1. Project Introduction and Requirements

In this final project, you will build a complete Student Management System using Laravel, PHP, MySQL, Blade, and Bootstrap.

The system will allow authorized administrators to manage student records, courses, admissions, and fee information.

Project Modules
  • Admin authentication and dashboard.
  • Student registration and management.
  • Course management.
  • Student search and pagination.
  • Student admission records.
  • Fee payment and pending fee reports.
  • Form validation and error messages.
  • Database migrations and relationships.
  • Authorization and application security.
  • Production deployment.
Technology Stack
Technology Purpose
Laravel Backend framework
PHP Application programming
MySQL Database storage
Blade Dynamic HTML templates
Bootstrap Responsive user interface
2. Create the Project and Database

Create a new Laravel project:

composer create-project laravel/laravel StudentManagement

cd StudentManagement

Create a MySQL database named:

student_management

Configure the database in your .env file:

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=student_management
DB_USERNAME=root
DB_PASSWORD=

Use your actual database username and password. Do not use development credentials in production.

Generate the main project files:

php artisan make:model Student -m
php artisan make:model Course -m
php artisan make:model FeePayment -m

php artisan make:controller StudentController --resource
php artisan make:controller CourseController --resource
php artisan make:controller AdminDashboardController

These commands create models, migration files, and controllers. You will still need to define their fields, relationships, and application logic.

3. Design the Database Tables

Create migrations for the main tables. The following is a simplified database design.

Students Table
Schema::create('students', function (Blueprint $table) {
    $table->id();
    $table->string('student_id')->unique();
    $table->string('name');
    $table->string('email')->unique();
    $table->string('phone', 20)->nullable();
    $table->foreignId('course_id')
          ->constrained()
          ->restrictOnDelete();
    $table->date('admission_date')->nullable();
    $table->timestamps();
});
Courses Table
Schema::create('courses', function (Blueprint $table) {
    $table->id();
    $table->string('course_name');
    $table->decimal('fee', 10, 2)->default(0);
    $table->unsignedInteger('duration_months')->default(0);
    $table->timestamps();
});
Fee Payments Table
Schema::create('fee_payments', function (Blueprint $table) {
    $table->id();
    $table->foreignId('student_id')
          ->constrained()
          ->restrictOnDelete();
    $table->decimal('amount', 10, 2);
    $table->date('payment_date');
    $table->string('payment_method')->nullable();
    $table->string('receipt_number')->unique();
    $table->timestamps();
});

Add the appropriate imports to each migration file. Each table definition belongs inside its own migration's up() method.

Because fee payments reference students and students reference courses, create the courses migration first, then students, then fee payments. Check migration timestamps to ensure this order.

Run the migrations:

php artisan migrate
4. Configure Models and Relationships

Configure the Student model:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;

class Student extends Model
{
    protected $fillable = [
        'student_id',
        'name',
        'email',
        'phone',
        'course_id',
        'admission_date',
    ];

    protected function casts(): array
    {
        return [
            'admission_date' => 'date',
        ];
    }

    public function course(): BelongsTo
    {
        return $this->belongsTo(Course::class);
    }

    public function payments(): HasMany
    {
        return $this->hasMany(FeePayment::class);
    }
}

Configure the Course model:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;

class Course extends Model
{
    protected $fillable = [
        'course_name',
        'fee',
        'duration_months',
    ];

    public function students(): HasMany
    {
        return $this->hasMany(Student::class);
    }
}

Configure the FeePayment model:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

class FeePayment extends Model
{
    protected $fillable = [
        'student_id',
        'amount',
        'payment_date',
        'payment_method',
        'receipt_number',
    ];

    protected function casts(): array
    {
        return [
            'amount' => 'decimal:2',
            'payment_date' => 'date',
        ];
    }

    public function student(): BelongsTo
    {
        return $this->belongsTo(Student::class);
    }
}

These relationships allow you to retrieve a student's course and payment records using Eloquent.

The casts() method is available in modern Laravel versions. In older versions, you can use the $casts property instead.

5. Build Student CRUD Operations

CRUD means Create, Read, Update, and Delete. These operations form the foundation of a student management system.

Create a resource controller:

php artisan make:controller StudentController --resource

Example of listing students with pagination:

use App\Models\Student;

public function index()
{
    $students = Student::with('course')
        ->latest()
        ->paginate(10);

    return view('students.index', compact('students'));
}

Example of creating a student:

use App\Models\Student;
use Illuminate\Http\Request;

public function store(Request $request)
{
    $validated = $request->validate([
        'student_id' => ['required', 'string', 'max:50', 'unique:students,student_id'],
        'name' => ['required', 'string', 'max:255'],
        'email' => ['required', 'email', 'unique:students,email'],
        'phone' => ['nullable', 'string', 'max:20'],
        'course_id' => ['required', 'exists:courses,id'],
        'admission_date' => ['nullable', 'date'],
    ]);

    Student::create($validated);

    return redirect()
        ->route('students.index')
        ->with('success', 'Student added successfully.');
}

Implement the remaining resource methods for viewing, editing, updating, and deleting records. Use validation and authorization for each write operation.

Student resource routes:

use App\Http\Controllers\StudentController;
use Illuminate\Support\Facades\Route;

Route::resource('students', StudentController::class);

The resource route generates standard CRUD routes. In a real application, protect these routes with authentication and suitable authorization rules.

6. Build the Admin Dashboard

The admin dashboard should summarize the current state of the application.

Example controller statistics:

use App\Models\Student;
use App\Models\Course;
use App\Models\FeePayment;

public function index()
{
    $totalStudents = Student::count();

    $totalCourses = Course::count();

    $totalPayments = FeePayment::sum('amount');

    $recentStudents = Student::with('course')
        ->latest()
        ->take(5)
        ->get();

    return view('admin.dashboard', compact(
        'totalStudents',
        'totalCourses',
        'totalPayments',
        'recentStudents'
    ));
}

Add the route in routes/web.php:

use App\Http\Controllers\AdminDashboardController;

Route::get(
    '/admin/dashboard',
    [AdminDashboardController::class, 'index']
)->middleware('auth')->name('admin.dashboard');

Example dashboard card in Blade:

<div class="card border-primary shadow-sm">
    <div class="card-body">
        <h6 class="text-muted">Total Students</h6>
        <h2 class="text-primary">
            {{ number_format($totalStudents) }}
        </h2>
    </div>
</div>

Add similar cards for courses and payments. The payment total above represents recorded payments; it is not necessarily the total amount due or the outstanding balance.

The auth middleware requires authentication but does not automatically grant or deny administrator privileges. Add an admin role check, gate, or policy.

7. Implement Fee Payment Recording

The system can record fee payments made by students. Always validate the student, payment amount, and date.

Example controller method:

use App\Models\FeePayment;
use Illuminate\Http\Request;
use Illuminate\Validation\Rule;

public function storePayment(Request $request)
{
    $validated = $request->validate([
        'student_id' => ['required', 'exists:students,id'],
        'amount' => ['required', 'numeric', 'gt:0', 'max:99999999.99'],
        'payment_date' => ['required', 'date'],
        'payment_method' => [
            'nullable',
            Rule::in(['cash', 'bank_transfer', 'upi']),
        ],
    ]);

    $validated['receipt_number'] =
        'RCP-' . strtoupper((string) str()->uuid());

    FeePayment::create($validated);

    return back()->with(
        'success',
        'Payment recorded successfully.'
    );
}

This method assumes it is placed inside an appropriate controller and that the model and database migration match the example.

Important payment rules:

  • Do not trust payment amounts submitted by a browser without checking them against your fee rules.
  • Restrict payment recording to authorized staff.
  • Validate the payment method and date.
  • Use a database transaction when recording a payment and updating related fee balances.
  • For online payments, verify the payment gateway's server-side confirmation before marking a payment as paid.
  • Keep a reliable audit trail for corrections and refunds.

For a production system, calculate outstanding fees using the actual course fee and all valid payments, taking discounts, adjustments, and refunds into account.

8. Authentication, Validation, and Security

A management system stores personal and financial information. Protect it before using real student data.

Security checklist
  • Require authentication for administrative pages.
  • Use policies, gates, or role middleware to authorize actions.
  • Validate all incoming form data.
  • Use Blade's escaped output syntax for user-provided values.
  • Include @csrf in state-changing forms.
  • Use Eloquent or parameterized queries rather than unsafe SQL concatenation.
  • Store passwords using Laravel's supported hashing tools.
  • Keep production debugging disabled.
  • Use HTTPS and protect database credentials.
  • Back up the database and test recovery procedures.

Example protected route group:

Route::middleware('auth')->prefix('admin')->name('admin.')->group(function () {
    Route::get('/dashboard', [
        AdminDashboardController::class,
        'index',
    ])->name('dashboard');

    Route::resource('students', StudentController::class);
});

This protects the routes from unauthenticated visitors. Add administrator-specific authorization as well, and ensure the controller methods enforce the same permissions for every sensitive action.

9. Final Project Checklist and Deployment

Complete the following tasks before submitting your project:

  1. Create the Laravel project and configure MySQL.
  2. Create and run migrations for students, courses, and fee payments.
  3. Configure Eloquent models and relationships.
  4. Implement student CRUD operations.
  5. Add search and pagination.
  6. Create the admin dashboard and statistics cards.
  7. Record fee payments and display payment history.
  8. Implement authentication and admin authorization.
  9. Validate forms and show useful error messages.
  10. Test the main workflows and failure cases.
  11. Configure production environment variables and HTTPS.
  12. Deploy the project and verify that it works correctly.
Useful Commands
php artisan migrate
php artisan route:list
php artisan test
php artisan optimize:clear
php artisan serve

Use php artisan serve for local development. Production deployment requires a properly configured web server or hosting platform.

Final deliverable:

Submit a working Student Management System with a database, CRUD operations, dashboard, fee records, authentication, authorization, validation, tests, and deployment documentation.

Congratulations! You have reached the end of the Laravel tutorial roadmap.

Final Quiz

1. Which Laravel feature defines database schema changes?




2. Which method is commonly used to validate incoming form data in a controller?




3. Is the auth middleware alone enough to guarantee that only administrators can access an admin dashboard?