SE321 — Software Engineering Web Application

DAFFODIL INTERNATIONAL UNIVERSITY · FINAL EXAM FALL 2024 · COMPLETE SOLUTIONS

Total: 40 Marks
Question 1(a) · Paper 2
Classify the components of MVC design pattern and describe their individual responsibilities.
5 Marks

MVC (Model-View-Controller) is a software architectural pattern that separates an application into three distinct components to improve organization, maintainability, and testability.

ComponentLocation in LaravelResponsibility
Model app/Models/ Represents data and business logic. Interacts directly with the database. In Laravel, each Model maps to a database table via Eloquent ORM. Does not know about the UI.
View resources/views/ Handles presentation and UI. In Laravel, Blade templates (.blade.php) render HTML with dynamic data passed from the Controller. Contains no business logic.
Controller app/Http/Controllers/ Acts as the middleman / bridge. Receives HTTP requests via Routes, instructs the Model to fetch/update data, then passes data to the View for rendering.

Request Flow

flow
Browser Request
      ↓
  ROUTER (routes/web.php)   ← matches URL to Controller method
      ↓
  CONTROLLER                ← processes logic, calls Model
      ↓
  MODEL                     ← queries database, returns data
      ↓
  CONTROLLER                ← receives data, selects View
      ↓
  VIEW (Blade template)     ← renders HTML with data
      ↓
Browser Response (HTML page)
Key benefit: Separation of Concerns — each component has one job, making the code easier to maintain, test, and scale. A designer can work on Views while a developer works on Controllers simultaneously.
Question 2(a) · Paper 2
Find majority element in array in linear time O(n) and O(1) space — Boyer-Moore Voting Algorithm.
5 Marks

The Boyer-Moore Voting Algorithm finds the majority element (appears more than ⌊n/2⌋ times) in O(n) time and O(1) space — no extra arrays needed.

Algorithm Idea

Keep a candidate and a count. When count reaches 0, pick the current element as new candidate. Because the majority element appears more than half the time, it will always survive.

php
<?php
function majorityElement($nums) {
    $candidate = null;
    $count     = 0;

    // Phase 1: Find candidate
    foreach ($nums as $num) {
        if ($count == 0) {
            $candidate = $num;  // pick new candidate
        }
        $count += ($num == $candidate) ? 1 : -1;
    }

    // Phase 2: candidate is guaranteed majority (given by problem)
    return $candidate;
}

// Test Example 1: [3,2,3]
echo majorityElement([3,2,3]);  // Output: 3

// Test Example 2: [2,2,1,1,1,2,2]
echo majorityElement([2,2,1,1,1,2,2]);  // Output: 2
?>

Step-by-step Trace — [3, 2, 3]

Stepnumcount beforeActioncandidatecount after
130count=0 → pick 331
2212 ≠ 3 → count--30
330count=0 → pick 331
OUTPUT
Majority Element = 3 ✓
💡
Why O(1) space? We only use 2 variables (candidate, count) regardless of array size. Why O(n) time? We loop through the array exactly once.
Question 2(b) · Paper 2
Organize the key points that distinguish Sessions from Cookies in PHP.
5 Marks
FeatureSessionsCookies
Storage LocationStored on the serverStored in the browser (client)
SecurityMore secure — data not exposed to userLess secure — user can see/modify data
Data SizeNo practical limitLimited to ~4KB per cookie
LifetimeEnds when browser closes (by default)Can persist for days/years (set expiry)
SpeedSlightly slower (server-side lookup)Faster (browser sends with every request)
Use CaseLogin state, shopping cart, sensitive dataRemember Me, theme preference, analytics

PHP Code Examples

php — sessions
<?php
session_start();            // MUST call at top of every page

// Set session variable
$_SESSION["username"] = "Alice";
$_SESSION["role"]     = "admin";

// Read session
echo $_SESSION["username"];  // Alice

// Destroy session (logout)
session_destroy();
?>
php — cookies
<?php
// Set cookie (name, value, expiry time)
setcookie("theme", "dark", time() + (86400 * 30)); // 30 days

// Read cookie
if (isset($_COOKIE["theme"])) {
    echo $_COOKIE["theme"];  // dark
}

// Delete cookie (set expiry to past)
setcookie("theme", "", time() - 3600);
?>
Key rule to remember: Use Sessions for sensitive data like login status. Use Cookies for non-sensitive preferences that should persist across browser sessions.
Question 3(a) · Paper 1
PHP OOP — Interface Input, Trait Logger, Class Addition that implements both.
10 Marks

This question tests Interfaces (contracts a class must follow) and Traits (reusable code blocks). An interface defines method signatures but no body. A trait provides method implementations to reuse across classes.

php — complete solution
<?php

// ─────────────────────────────────────
// i. Interface Input
//    Defines a CONTRACT: any class that implements
//    this MUST have a setNumbers() method.
// ─────────────────────────────────────
interface Input {
    public function setNumbers($a, $b);
}

// ─────────────────────────────────────
// ii. Trait Logger
//     A reusable block of code.
//     Any class that "uses" this trait gets the log() method.
// ─────────────────────────────────────
trait Logger {
    public function log($message) {
        echo "[LOG] " . $message . "<br>";
    }
}

// ─────────────────────────────────────
// iii. Class Addition
//      - implements Input (must define setNumbers)
//      - uses Logger trait (gets log() method for free)
// ─────────────────────────────────────
class Addition implements Input {
    use Logger;  // include the Logger trait

    private $a;
    private $b;

    // Implementing the interface method (required)
    public function setNumbers($a, $b) {
        $this->a = $a;
        $this->b = $b;
        $this->log("Numbers set: a = $a, b = $b");
    }

    // Method to calculate and return the sum
    public function calculate() {
        $sum = $this->a + $this->b;
        $this->log("Calculating: {$this->a} + {$this->b} = $sum");
        return $sum;
    }
}

// ─────────────────────────────────────
// Instantiate and use the class
// ─────────────────────────────────────
$obj = new Addition();
$obj->setNumbers(15, 25);
$result = $obj->calculate();

echo "Result: $result";
?>
OUTPUT
[LOG] Numbers set: a = 15, b = 25
[LOG] Calculating: 15 + 25 = 40
Result: 40

Key Concepts Explained

ConceptExplanation
interfaceA contract — lists methods a class MUST implement. No method bodies. Use keyword implements.
traitA reusable block of methods. Not a class, cannot be instantiated. Include with use TraitName.
implementsUsed when a class fulfills an interface contract.
use (in class)Brings trait methods into the class.
Question 3(b) · Paper 1
Trace the role and responsibilities of each component when a browser requests /product in the given Laravel MVC setup.
8 Marks

Given: Route::get('/product', [ProductController::class, 'index'])->name('product.index') and the controller fetches all products and returns the view.

Complete Request Trace

step-by-step trace
STEP 1 — BROWSER
User types: http://yourapp.com/product
→ HTTP GET request is sent to the Laravel server.

STEP 2 — ROUTER (routes/web.php)
Route::get('/product', [ProductController::class, 'index'])
  →name('product.index');

Laravel matches the URL /product with this route.
It directs the request to ProductController's index() method.
The route is named 'product.index' for easy URL generation.

STEP 3 — CONTROLLER (app/Http/Controllers/ProductController.php)
public function index() {
    $products = Product::all();
    return view('products.index', compact('products'));
}

Responsibility: Acts as the middleman.
  - Receives the request.
  - Calls Product::all() on the Model to get all products.
  - Passes the data to the View using compact().

STEP 4 — MODEL (app/Models/Product.php)
Product::all()
  → Eloquent ORM runs: SELECT * FROM products;
  → Returns a Collection of all product records.
  → Sends the data back to the Controller.

Responsibility: Handles all database interaction.
  Does NOT know how data will be displayed.

STEP 5 — VIEW (resources/views/products/index.blade.php)
Receives: $products (collection of Product objects)
Renders HTML:
  @foreach($products as $product)
      {{ $product->name }} ...
  @endforeach

Responsibility: Presents data to the user.
  Contains ONLY presentation logic (Blade directives).
  No database queries here.

STEP 6 — RESPONSE
Laravel sends the rendered HTML page back to the browser.
User sees the list of products on screen.

Summary Table

ComponentFileRole in /product request
Routerroutes/web.phpMatches GET /product → routes to ProductController@index
ControllerProductController.phpCalls Model, receives data, selects View, passes data
ModelProduct.phpRuns SELECT * FROM products, returns collection to Controller
Viewproducts/index.blade.phpRenders HTML table/list of products for the browser
Question 3(c) · Paper 1
PHP-MySQL app to add new students — name, roll number, department with confirmation.
7 Marks

A complete single-file PHP app that connects to MySQL, shows a form, inserts student data, and displays a confirmation message.

sql — create table first
-- Run this in phpMyAdmin or MySQL console
CREATE DATABASE school_db;
USE school_db;

CREATE TABLE students (
    id         INT AUTO_INCREMENT PRIMARY KEY,
    name       VARCHAR(100) NOT NULL,
    roll_no    VARCHAR(50)  NOT NULL,
    department VARCHAR(100) NOT NULL
);
php — add_student.php (complete file)
<?php
// ── 1. DATABASE CONNECTION ──────────────
$conn = new mysqli("localhost", "root", "", "school_db");

if ($conn->connect_error) {
    die("Connection failed: " . $conn->connect_error);
}

$message = "";

// ── 2. HANDLE FORM SUBMISSION ───────────
if ($_SERVER["REQUEST_METHOD"] == "POST") {
    $name       = htmlspecialchars(trim($_POST["name"]));
    $roll_no    = htmlspecialchars(trim($_POST["roll_no"]));
    $department = htmlspecialchars(trim($_POST["department"]));

    if (empty($name) || empty($roll_no) || empty($department)) {
        $message = "<p style='color:red'>All fields are required!</p>";
    } else {
        // Prepared statement — safe from SQL injection
        $stmt = $conn->prepare(
            "INSERT INTO students (name, roll_no, department) VALUES (?, ?, ?)"
        );
        $stmt->bind_param("sss", $name, $roll_no, $department);

        if ($stmt->execute()) {
            $message = "<p style='color:green'>
                ✅ Student <strong>$name</strong> added successfully!
                (ID: {$conn->insert_id})</p>";
        } else {
            $message = "<p style='color:red'>Error: " . $stmt->error . "</p>";
        }
        $stmt->close();
    }
}
$conn->close();
?>

<!-- ── 3. HTML FORM ──────────────────── -->
<!DOCTYPE html>
<html>
<head><title>Add Student</title></head>
<body>
  <h2>Add New Student</h2>

  <!-- Confirmation message -->
  <?php echo $message; ?>

  <form method="POST" action="">
    <label>Name:</label><br>
    <input type="text" name="name" required><br><br>

    <label>Roll Number:</label><br>
    <input type="text" name="roll_no" required><br><br>

    <label>Department:</label><br>
    <input type="text" name="department" required><br><br>

    <button type="submit">Add Student</button>
  </form>
</body>
</html>
What this covers: Database connection → Form display → POST handling → Input sanitization → Prepared statement INSERT → Confirmation message display. All 4 requirements fulfilled.
Question 3(a) · Paper 2
PHP OOP Notification System — Interface Notifier with EmailNotifier, SMSNotifier, PushNotifier.
10 Marks

Design pattern: one interface (Notifier) enforces the method signature, three concrete classes each implement it differently. This is the Strategy / Polymorphism pattern.

php — complete solution
<?php

// ─────────────────────────────────────────────────
// Interface: Notifier
// Any class implementing this MUST have sendNotification()
// ─────────────────────────────────────────────────
interface Notifier {
    public function sendNotification($message, $recipient);
}

// ─────────────────────────────────────────────────
// Concrete Class 1: EmailNotifier
// ─────────────────────────────────────────────────
class EmailNotifier implements Notifier {
    public function sendNotification($message, $recipient) {
        echo "📧 EMAIL to {$recipient}: {$message}<br>";
    }
}

// ─────────────────────────────────────────────────
// Concrete Class 2: SMSNotifier
// ─────────────────────────────────────────────────
class SMSNotifier implements Notifier {
    public function sendNotification($message, $recipient) {
        echo "📱 SMS to {$recipient}: {$message}<br>";
    }
}

// ─────────────────────────────────────────────────
// Concrete Class 3: PushNotifier
// ─────────────────────────────────────────────────
class PushNotifier implements Notifier {
    public function sendNotification($message, $recipient) {
        echo "🔔 PUSH to {$recipient}: {$message}<br>";
    }
}

// ─────────────────────────────────────────────────
// Usage — Polymorphism in action
// Each object is treated as a Notifier type
// ─────────────────────────────────────────────────
$notifiers = [
    new EmailNotifier(),
    new SMSNotifier(),
    new PushNotifier(),
];

foreach ($notifiers as $notifier) {
    $notifier->sendNotification("Exam starts tomorrow!", "Alice");
}
?>
OUTPUT
📧 EMAIL to Alice: Exam starts tomorrow!
📱 SMS to Alice: Exam starts tomorrow!
🔔 PUSH to Alice: Exam starts tomorrow!
💡
Why interface? The interface guarantees every notifier class has a sendNotification() method with the same signature. This allows polymorphism — you can loop through different notifiers and call the same method on each without knowing the exact type.
Question 3(b) · Paper 2
Full PHP-MySQL Student Record CRUD — Add, View all, Edit (pre-filled form), Delete.
15 Marks

This is the biggest question — a complete CRUD application with 4 operations. Here is the full, working solution organized by file.

sql — create table
CREATE DATABASE student_db;
USE student_db;

CREATE TABLE students (
    id      INT AUTO_INCREMENT PRIMARY KEY,
    name    VARCHAR(100) NOT NULL,
    age     INT          NOT NULL,
    grade   VARCHAR(10)  NOT NULL,
    email   VARCHAR(150) NOT NULL
);
php — db.php (database connection — shared file)
<?php
// db.php — include this in every file
$conn = new mysqli("localhost", "root", "", "student_db");
if ($conn->connect_error) {
    die("Connection failed: " . $conn->connect_error);
}
?>
php — index.php (VIEW ALL + ADD + DELETE links)
<?php require 'db.php'; ?>
<!DOCTYPE html>
<html>
<head><title>Student Records</title></head>
<body>
<h2>All Students</h2>
<a href="add.php">+ Add New Student</a>
<br><br>

<table border="1">
  <tr>
    <th>ID</th><th>Name</th><th>Age</th><th>Grade</th><th>Email</th><th>Actions</th>
  </tr>
  <?php
    // READ — fetch all students
    $result = $conn->query("SELECT * FROM students");
    while($row = $result->fetch_assoc()): ?>
  <tr>
    <td><?= $row['id'] ?></td>
    <td><?= $row['name'] ?></td>
    <td><?= $row['age'] ?></td>
    <td><?= $row['grade'] ?></td>
    <td><?= $row['email'] ?></td>
    <td>
      <a href="edit.php?id=<?= $row['id'] ?>">Edit</a> |
      <a href="delete.php?id=<?= $row['id'] ?>"
         onclick="return confirm('Delete this student?')">Delete</a>
    </td>
  </tr>
  <?php endwhile; ?>
</table>
</body>
</html>
php — add.php (CREATE)
<?php
require 'db.php';

if ($_SERVER["REQUEST_METHOD"] == "POST") {
    $name  = htmlspecialchars($_POST['name']);
    $age   = (int)$_POST['age'];
    $grade = htmlspecialchars($_POST['grade']);
    $email = htmlspecialchars($_POST['email']);

    $stmt = $conn->prepare(
        "INSERT INTO students (name, age, grade, email) VALUES (?, ?, ?, ?)"
    );
    $stmt->bind_param("siss", $name, $age, $grade, $email);
    $stmt->execute();

    header("Location: index.php"); // redirect back
    exit();
}
?>
<!DOCTYPE html>
<html>
<head><title>Add Student</title></head>
<body>
<h2>Add New Student</h2>
<form method="POST">
  Name:  <input type="text"   name="name"  required><br><br>
  Age:   <input type="number" name="age"   required><br><br>
  Grade: <input type="text"   name="grade" required><br><br>
  Email: <input type="email"  name="email" required><br><br>
  <button type="submit">Add Student</button>
  <a href="index.php">Cancel</a>
</form>
</body>
</html>
php — edit.php (UPDATE — pre-filled form)
<?php
require 'db.php';
$id = (int)$_GET['id'];

// Handle UPDATE on form submit
if ($_SERVER["REQUEST_METHOD"] == "POST") {
    $name  = htmlspecialchars($_POST['name']);
    $age   = (int)$_POST['age'];
    $grade = htmlspecialchars($_POST['grade']);
    $email = htmlspecialchars($_POST['email']);
    $id    = (int)$_POST['id'];

    $stmt = $conn->prepare(
        "UPDATE students SET name=?, age=?, grade=?, email=? WHERE id=?"
    );
    $stmt->bind_param("sissi", $name, $age, $grade, $email, $id);
    $stmt->execute();
    header("Location: index.php");
    exit();
}

// Fetch current values to PRE-FILL the form
$stmt = $conn->prepare("SELECT * FROM students WHERE id = ?");
$stmt->bind_param("i", $id);
$stmt->execute();
$student = $stmt->get_result()->fetch_assoc();
?>
<!DOCTYPE html>
<html>
<head><title>Edit Student</title></head>
<body>
<h2>Edit Student</h2>
<form method="POST">
  <!-- Hidden field to pass the ID -->
  <input type="hidden" name="id" value="<?= $student['id'] ?>">

  <!-- value="" pre-fills the form with current data -->
  Name:  <input type="text"   name="name"  value="<?= $student['name']  ?>"><br><br>
  Age:   <input type="number" name="age"   value="<?= $student['age']   ?>"><br><br>
  Grade: <input type="text"   name="grade" value="<?= $student['grade'] ?>"><br><br>
  Email: <input type="email"  name="email" value="<?= $student['email'] ?>"><br><br>
  <button type="submit">Update Student</button>
  <a href="index.php">Cancel</a>
</form>
</body>
</html>
php — delete.php (DELETE)
<?php
require 'db.php';
$id = (int)$_GET['id']; // cast to int for safety

$stmt = $conn->prepare("DELETE FROM students WHERE id = ?");
$stmt->bind_param("i", $id);
$stmt->execute();

header("Location: index.php"); // redirect back to list
exit();
?>

File Structure Summary

FileCRUD OperationKey Code
index.phpREAD (View All)SELECT * FROM students + table display
add.phpCREATE (Add)Form + INSERT INTO students
edit.phpUPDATE (Edit)Pre-filled form + UPDATE students SET
delete.phpDELETE (Remove)DELETE FROM students WHERE id=?
db.phpConnectionnew mysqli(...) — shared across files
Examiner key points: (1) All queries use prepared statements for security. (2) Edit form uses value="<?= $student['field'] ?>" to pre-fill. (3) Delete uses confirmation dialog before deleting. (4) After each operation, header("Location: index.php") redirects back to the list.
Abdullah Al Shovon