BIT301 Web Technology II

Web Technology IIUnit 619 min read

PHP OOP: Classes, Objects, Inheritance & Database Links

Unit 6 of Web Technology II covers PHP’s object-oriented programming (OOP) features—classes, objects, inheritance, polymorphism, and abstract classes—with real-world applications in user authentication, database-driven apps, and modular code. Learn how to model data (e.g., Student, User) and connect to MySQL, plus solv

Core Concepts of PHP OOP

1. Classes and Objects: The Blueprint and Instance

Definition:

  • A class is a blueprint for creating objects (e.g., Car, User). It defines properties (attributes) and methods (functions).
  • An object is an instance of a class with actual values.

How it works:

class Student {
    // Properties (attributes)
    public $name;
    public $age;

    // Methods (functions)
    public function greet() {
        return "Hello, I'm " . $this->name;
    }
}

// Create an object
$ram = new Student();
$ram->name = "Ram";
$ram->age = 20;
echo $ram->greet(); // Output: Hello, I'm Ram

Visual: Class vs. Object

classDiagram
    class Student {
        +String name
        +int age
        +String greet()
    }
    class Ram {
        -name: "Ram"
        -age: 20
    }
    Student <|-- Ram : "is an instance of"

Real-world analogy:

  • Class = Recipe for a pizza (ingredients + steps).
  • Object = A specific pizza you order (e.g., "Margherita with extra cheese").

2. Constructors and Destructors

Definition:

  • Constructor (__construct()): Runs when an object is created. Initializes properties.
  • Destructor (__destruct()): Runs when an object is destroyed (e.g., page ends).

Example: Login Form User

class User {
    public $username;
    public $password;

    // Constructor
    public function __construct($username, $password) {
        $this->username = $username;
        $this->password = $password;
    }

    // Destructor
    public function __destruct() {
        echo "User $this->username logged out.";
    }
}

$user = new User("admin", "12345");

Output:

User admin logged out.

Exam Tip:

  • Always use constructors to set default values (e.g., $this->isLoggedIn = false;).

3. Inheritance: Reusing and Extending Code

Definition:

  • Inheritance lets a child class (subclass) inherit properties/methods from a parent class (superclass).
  • Uses extends and parent::method() to override or reuse methods.

Example: Admin vs. Regular User

class User {
    public $username;
    protected $role = "user"; // Protected: accessible in child classes

    public function login() {
        return "$this->username logged in as $this->role.";
    }
}

class Admin extends User {
    protected $role = "admin";

    public function deleteUser($user) {
        return "Admin $this->username deleted $user.";
    }
}

$admin = new Admin();
$admin->username = "superadmin";
echo $admin->login(); // Output: superadmin logged in as admin.
echo $admin->deleteUser("Ram"); // Output: Admin superadmin deleted Ram.

Visual: Inheritance Hierarchy

classDiagram
    class User {
        +String username
        +String role
        +login()
    }
    class Admin {
        +deleteUser(user)
    }
    User <|-- Admin : "extends"

Real-world use in Nepal:

  • eSewa: Uses inheritance to separate Customer (regular users) and Admin (eSewa staff) classes. The Admin class extends Customer but adds methods like approvePayment().
  • Khalti: Models User, Merchant, and SupportAgent with inheritance to share common login logic but add unique features.

4. Polymorphism: Same Method, Different Behavior

Definition:

  • Method overriding: Child class redefines a parent method.
  • Method overloading: PHP doesn’t support it natively (use variable arguments ...$args instead).

Example: Payment Processing

class Payment {
    public function process($amount) {
        return "Processing \$$amount via default method.";
    }
}

class CreditCardPayment extends Payment {
    public function process($amount) {
        return "Processing \$$amount via Credit Card (2% fee).";
    }
}

$payment = new CreditCardPayment();
echo $payment->process(100); // Output: Processing $100 via Credit Card (2% fee).

Visual: Polymorphism in Action

sequenceDiagram
    participant Client
    participant Payment
    participant CreditCardPayment
    Client->>Payment: process(100)
    Payment->>CreditCardPayment: (overridden)
    CreditCardPayment-->>Client: "Processing $100 via Credit Card"

Real-world tie-in:

  • Pathao Driver App: Uses polymorphism for different payment methods (CashPayment, KhaltiPayment, CreditCardPayment). The processPayment() method behaves differently for each class.

5. Abstract Classes and Interfaces

Definition:

  • Abstract class: Cannot be instantiated. Forces child classes to implement abstract methods.
  • Interface: Pure contract (methods without implementation). A class can implement multiple interfaces.

Example: Database Connection

abstract class Database {
    abstract public function connect();
}

class MySQL extends Database {
    public function connect() {
        return "Connected to MySQL using PDO.";
    }
}

$mysql = new MySQL();
echo $mysql->connect();

Interface Example: Payment Gateway

interface PaymentGateway {
    public function pay($amount);
}

class PayPal implements PaymentGateway {
    public function pay($amount) {
        return "Paid \$$amount via PayPal.";
    }
}

$paypal = new PayPal();
echo $paypal->pay(50); // Output: Paid $50 via PayPal.

Visual: Abstract Class vs. Interface

classDiagram
    abstract class Database {
        <<abstract>>
        +connect()
    }
    class MySQL {
        +connect()
    }
    Database <|-- MySQL : "implements abstract"
    interface PaymentGateway {
        +pay(amount)
    }
    class PayPal {
        +pay(amount)
    }
    PaymentGateway <|.. PayPal : "implements"

Real-world use:

  • Nepal Stock Exchange (NEPSE): Uses interfaces to standardize trading methods across Broker, Investor, and Admin classes. All must implement executeTrade() but can do so differently.

6. Access Modifiers: Public, Private, Protected

Modifier Accessible In Example Use Case
public Anywhere $username (visible to all)
private Only within the class $apiKey (hidden from subclasses)
protected Class + subclasses $role (shared with child classes)

Example: Secure User Data

class User {
    public $username;
    private $password;
    protected $lastLogin;

    public function setPassword($pass) {
        $this->password = md5($pass); // Never store plaintext!
    }
}

Exam Tip:

  • Use private for sensitive data (e.g., passwords, API keys).
  • Use protected for data meant for inheritance (e.g., $role in Admin class).

7. Static Properties and Methods

Definition:

  • Static: Belongs to the class, not objects. Called using ClassName::method().
  • Use case: Counters, utility functions.

Example: User Counter

class User {
    public static $totalUsers = 0;

    public function __construct() {
        self::$totalUsers++;
    }
}

$user1 = new User();
$user2 = new User();
echo User::$totalUsers; // Output: 2

Real-world use in Nepal:

  • NTC Website: Uses static methods to count total internet subscribers without creating objects for each user.

8. Magic Methods: __get, __set, __toString

Definition:

  • Special methods for dynamic behavior (e.g., lazy loading, type conversion).

Example: Lazy-Loaded User Profile

class User {
    private $data = [];

    public function __get($key) {
        return $this->data[$key] ?? null;
    }

    public function __set($key, $value) {
        $this->data[$key] = $value;
    }

    public function __toString() {
        return "User: " . $this->name;
    }
}

$user = new User();
$user->name = "Hari"; // Uses __set
echo $user->name;     // Uses __get
echo $user;           // Uses __toString

Output:

Hari
User: Hari

9. PHP OOP with Databases (PDO Example)

Step-by-Step: Login System with MySQL

<?php
// 1. Define User class
class User {
    private $db;

    public function __construct(PDO $db) {
        $this->db = $db;
    }

    public function login($username, $password) {
        $stmt = $this->db->prepare("SELECT * FROM users WHERE username = ? AND password = ?");
        $stmt->execute([$username, md5($password)]);
        return $stmt->fetch();
    }
}

// 2. Database connection
$db = new PDO("mysql:host=localhost;dbname=webtech", "root", "");
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

// 3. Create User object and test login
$user = new User($db);
$loginResult = $user->login("admin", "12345");

if ($loginResult) {
    header("Location: home.php");
} else {
    echo "Login failed!";
}
?>

Visual: Database Connection Flow

sequenceDiagram
    participant Client
    participant UserClass
    participant PDO
    participant MySQL
    Client->>UserClass: login("admin", "12345")
    UserClass->>PDO: prepare("SELECT...")
    PDO->>MySQL: execute()
    MySQL-->>PDO: fetch()
    PDO-->>UserClass: User object
    UserClass-->>Client: Redirect to home.php

Real-world tie-in:

  • Khalti’s Login System: Uses PDO to securely fetch user data from MySQL and validate credentials before redirecting to the dashboard.

10. Error Handling in OOP

Best Practices:

  1. Use try-catch for database operations.
  2. Throw custom exceptions for business logic errors.

Example: Invalid User Exception

class InvalidUserException extends Exception {}

class User {
    public function login($username, $password) {
        if (empty($username)) {
            throw new InvalidUserException("Username cannot be empty!");
        }
        // ... rest of the login logic
    }
}

try {
    $user = new User();
    $user->login("", "12345");
} catch (InvalidUserException $e) {
    echo "Error: " . $e->getMessage();
}

Output:

Error: Username cannot be empty!

In the Real World

  1. eSewa’s User Authentication

    • Idea Used: OOP classes (User, Admin, Customer) with inheritance.
    • How: The Admin class extends User and adds methods like approvePayment(). The login() method (overridden in Admin) checks permissions before granting access to the dashboard.
    • Database Link: PDO connects to eSewa’s MySQL database to verify user credentials.
  2. Pathao Driver App’s Payment System

    • Idea Used: Polymorphism via interfaces (PaymentGateway) and abstract classes (Payment).
    • How: The app implements KhaltiPayment, CashPayment, and CreditCardPayment classes, all inheriting from Payment. The processPayment() method behaves differently for each class (e.g., Khalti deducts a 2% fee, while cash payments are instant).
    • Real Example: When a user selects "Pay with Khalti," the app calls $khaltiPayment->process(500), which internally uses Khalti’s API.
  3. NEPSE Trading Platform

    • Idea Used: Abstract classes and interfaces for standardized trading.
    • How: The Trader abstract class defines executeTrade() and checkBalance(). Concrete classes like Broker and Investor implement these methods differently. The Trade interface ensures all trading classes support buy() and sell().
    • Database Link: PDO connects to NEPSE’s PostgreSQL database to fetch stock prices and update portfolios.

Worked Example: Daraz Order Queue System

Problem: Daraz wants to model an order queue where:

  • Orders have orderId, customer, status (e.g., "pending," "shipped").
  • Admins can cancel orders, and customers can track status.

Solution:

<?php
class Order {
    public $orderId;
    public $customer;
    protected $status;

    public function __construct($orderId, $customer) {
        $this->orderId = $orderId;
        $this->customer = $customer;
        $this->status = "pending";
    }

    public function updateStatus($newStatus) {
        $this->status = $newStatus;
    }
}

class AdminOrder extends Order {
    public function cancelOrder() {
        $this->status = "cancelled";
        return "Order #$this->orderId cancelled by admin.";
    }
}

class CustomerOrder extends Order {
    public function trackStatus() {
        return "Order #$this->orderId: $this->status";
    }
}

// Simulate Daraz's order flow
$order = new CustomerOrder(1001, "Ram");
echo $order->trackStatus() . "\n"; // Order #1001: pending

$adminOrder = new AdminOrder(1001, "Ram");
echo $adminOrder->cancelOrder() . "\n"; // Order #1001 cancelled by admin.
echo $order->trackStatus(); // Order #1001: cancelled (inherited)
?>

Output:

Order #1001: pending
Order #1001 cancelled by admin.
Order #1001: cancelled

Visual: Daraz Order Flow

stateDiagram-v2
    [*] --> Pending: Order created
    Pending --> Shipped: Admin updates status
    Pending --> Cancelled: Admin cancels
    Shipped --> Delivered: Courier updates
    Cancelled --> [*]
    Delivered --> [*]

Comparison Table: OOP vs. Procedural PHP

Feature OOP Procedural PHP
Code Organization Classes/objects Functions + global variables
Reusability High (inheritance) Low (copy-paste code)
Maintainability Easy (modular) Hard (spaghetti code)
Security Better (encapsulation) Risky (global variables exposed)
Example class User { ... } function login($user, $pass) { ... }

Common Pitfalls and How to Avoid Them

  1. Overusing public properties

    • Problem: Exposes data to unintended modifications.
    • Fix: Use private properties with getter/setter methods.
      class User {
          private $email;
          public function setEmail($email) {
              $this->email = filter_var($email, FILTER_VALIDATE_EMAIL);
          }
      }
      
  2. Tight Coupling

    • Problem: Classes depend on each other directly (hard to reuse).
    • Fix: Use dependency injection (pass dependencies as parameters).
      class Order {
          private $paymentGateway;
          public function __construct(PaymentGateway $gateway) {
              $this->paymentGateway = $gateway;
          }
      }
      
  3. Ignoring __destruct

    • Problem: Resources (e.g., database connections) may leak.
    • Fix: Close connections in __destruct.
      class Database {
          public function __destruct() {
              $this->connection = null;
          }
      }
      

Exam Tip: How to Score Full Marks

  1. For coding questions:

    • Always include:
      • Class definition with public/private modifiers.
      • Constructor to initialize properties.
      • Methods with proper logic (e.g., login() checks credentials).
      • Error handling (try-catch or if checks).
    • Example Starter:
      <?php
      class User {
          private $username;
          private $password;
      
          public function __construct($username, $password) {
              $this->username = $username;
              $this->password = md5($password); // Hash password
          }
      
          public function login($inputPassword) {
              return $this->password === md5($inputPassword);
          }
      }
      
      $user = new User("admin", "12345");
      if ($user->login("12345")) {
          echo "Login successful!";
      } else {
          echo "Invalid credentials.";
      }
      ?>
      
  2. For theory questions:

    • Define terms clearly (e.g., "Inheritance allows a child class to inherit properties and methods from a parent class.").
    • Use diagrams (class diagrams, sequence diagrams) to explain relationships.
    • Relate to real-world examples (e.g., "Like how eSewa uses inheritance for Admin and Customer classes...").
  3. Database questions:

    • Show the PDO connection code.
    • Use prepared statements to prevent SQL injection.
    • Example:
      $stmt = $pdo->prepare("SELECT * FROM users WHERE username = ?");
      $stmt->execute([$username]);
      
  4. JSON/XML parsing:

    • Use json_decode() or simplexml_load_file().
    • Example:
      $json = '{"Name": "Gunadi", "Email": "[email protected]"}';
      $data = json_decode($json);
      echo $data->Name; // Output: Gunadi
      
  5. Array manipulation:

    • For array_splice(), show both insertion and removal:
      $fruits = ["apple", "banana", "orange"];
      array_splice($fruits, 1, 0, "kiwi"); // Insert "kiwi" at index 1
      array_splice($fruits, 1, 1);         // Remove 1 element at index 1
      

Past Exam Questions Solved

Q1: Login Form Redirection

<?php
class Login {
    private $username;
    private $password;

    public function __construct($username, $password) {
        $this->username = $username;
        $this->password = md5($password);
    }

    public function validate($inputPassword) {
        return $this->password === md5($inputPassword);
    }
}

// Simulate form submission
if ($_SERVER["REQUEST_METHOD"] == "POST") {
    $user = new Login("admin", "12345"); // Hardcoded for demo; use DB in real apps
    if ($user->validate($_POST["password"])) {
        header("Location: home.php");
        exit();
    } else {
        echo "Invalid credentials!";
    }
}
?>

<!-- HTML Form -->
<form method="post">
    Username: <input type="text" name="username"><br>
    Password: <input type="password" name="password"><br>
    <input type="submit" value="Login">
    <input type="reset" value="Cancel">
</form>

Q2: Student Object in JavaScript (PHP Equivalent)

<?php
class Student {
    public $name = "Ram";
    public $age = 20;
    public $dob = "2003-02-03";

    public function display() {
        echo "Name: " . $this->name . "<br>";
        echo "Age: " . $this->age . "<br>";
        echo "DOB: " . $this->dob;
    }
}

$student = new Student();
$student->display();
?>

Q3: PHP.ini Settings

Setting Purpose
display_errors Controls whether PHP errors are shown to users (On/Off).
variables_order Defines the order of $_GET, $_POST, etc. (e.g., "GPCS" for all).
request_order Legacy setting (use variables_order instead).

Example php.ini snippet:

display_errors = Off
variables_order = "GPCS"

Q4: JSON File Parsing

<?php
$json = file_get_contents("BIT.JSON");
$data = json_decode($json);

echo "Name: " . $data->Name . "<br>";
echo "Email: " . $data->Email . "<br>";
echo "Age: " . $data->Age;
?>

Q5: Database Connection and Form Insert

<?php
class Database {
    private $conn;

    public function __construct() {
        $this->conn = new PDO("mysql:host=localhost;dbname=test", "root", "");
        $this->conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    }

    public function insertUser($name, $password) {
        $stmt = $this->conn->prepare("INSERT INTO users (name, password) VALUES (?, ?)");
        $stmt->execute([$name, md5($password)]);
        return $stmt->rowCount();
    }
}

// Handle form submission
if ($_SERVER["REQUEST_METHOD"] == "POST") {
    $db = new Database();
    $rowsAffected = $db->insertUser($_POST["name"], $_POST["password"]);
    echo $rowsAffected ? "User added!" : "Error!";
}
?>

<!-- HTML Form -->
<form method="post">
    Name: <input type="text" name="name"><br>
    Password: <input type="password" name="password"><br>
    <input type="radio" name="role" value="user"> User<br>
    <input type="radio" name="role" value="admin"> Admin<br>
    <input type="submit" value="Submit">
</form>

Summary Checklist for Exams

Before submitting your answer, verify:

  1. Classes: Defined with proper access modifiers (public, private).
  2. Objects: Instantiated with new and properties set.
  3. Methods: Include logic (e.g., login() checks credentials).
  4. Database: PDO connection + prepared statements.
  5. Error Handling: try-catch or input validation.
  6. Real-world Tie-in: Mention at least one Nepalese app (eSewa, Khalti, etc.).
  7. Diagrams: Draw class/inheritance diagrams for theory questions.

Based on the TU BIT syllabus for Web Technology II (BIT301), unit 6.

Discussion

Loading…