OOP là gì? Class và Object

Sau khi hoàn thành Mini Project CRUD, bước tiếp theo là học OOP (Object-Oriented Programming) – Lập trình hướng đối tượng trong PHP. OOP là phương pháp lập trình hiện đại, giúp code dễ bảo trì, tái sử dụng và mở rộng. Từ dự án nhỏ đến framework lớn như Laravel, Symfony đều xây dựng trên nền tảng OOP.

1. OOP là gì?

OOP (Object-Oriented Programming) là phương pháp lập trình tổ chức code thành các đối tượng (Objects) – những thực thể có thuộc tính và hành vi riêng.

1.1. So sánh Procedural vs OOP

<?php
// ❌ PROCEDURAL - Code rời rạc, khó bảo trì
$user_name = "Nguyễn Văn A";
$user_email = "a@email.com";
$user_age = 20;

function getUserInfo($name, $email, $age) {
  return "$name - $email - $age tuổi";
}

echo getUserInfo($user_name, $user_email, $user_age);

// ✅ OOP - Code có tổ chức, dễ quản lý
class User {
  public $name;
  public $email;
  public $age;
  
  public function getInfo() {
    return "$this->name - $this->email - $this->age tuổi";
  }
}

$user = new User();
$user->name = "Nguyễn Văn A";
$user->email = "a@email.com";
$user->age = 20;

echo $user->getInfo();
?>
OOP - ĐỐI TƯỢNG TRONG THẾ GIỚI THỰC THẾ GIỚI THỰC 🚗 Ô TÔ Thuộc tính: • Hãng: Toyota • Màu sắc: Đỏ • Tốc độ: 0 km/h Hành vi: • Khởi động() • Tăng tốc() • Phanh() Chuyển thành OBJECT TRONG PHP class Car { // Properties public $brand = "Toyota"; public $color = "Đỏ"; public $speed = 0; // Methods function start() {...} function accelerate() {...} function brake() {...} } 💡 OOP = Mô phỏng thế giới thực thành code
Hình 1: Khái niệm OOP - Đối tượng trong thế giới thực

1.2. Tại sao học OOP?

  • Tái sử dụng code: Viết 1 lần, dùng nhiều nơi
  • Dễ bảo trì: Sửa 1 chỗ, ảnh hưởng đúng phạm vi
  • Mở rộng dễ: Thêm tính năng không ảnh hưởng code cũ
  • Bảo mật: Ẩn dữ liệu nhạy cảm (Encapsulation)
  • Teamwork: Nhiều người code cùng lúc
  • Framework: Laravel, Symfony, WordPress… đều dùng OOP

2. Class là gì?

Class (Lớp) là bản thiết kế (blueprint) để tạo ra các đối tượng. Giống như bản vẽ nhà – từ 1 bản vẽ có thể xây nhiều ngôi nhà.

<?php
// Khai báo class
class Car {
  // Properties (thuộc tính)
  public $brand;
  public $color;
  public $speed;
  
  // Methods (phương thức)
  public function start() {
    echo "Xe $this->brand đang khởi động...";
  }
  
  public function accelerate() {
    $this->speed += 10;
    echo "Tăng tốc! Tốc độ: $this->speed km/h";
  }
}
?>

Giải thích:

  • class Car – Tên class (viết hoa chữ cái đầu)
  • public $brand – Thuộc tính (biến trong class)
  • public function start() – Phương thức (hàm trong class)
  • $this – Tham chiếu đến object hiện tại
QUAN HỆ GIỮA CLASS VÀ OBJECT CLASS = BẢN THIẾT KẾ (BLUEPRINT) class Car { public $brand, $color; function start() {...} } ↓ new Car() ↓ Tạo ra nhiều objects OBJECT 1 $car1 = new Car(); brand = "Toyota" color = "Đỏ" 🚗 Ô tô Toyota màu đỏ OBJECT 2 $car2 = new Car(); brand = "Honda" color = "Trắng" 🚗 Ô tô Honda màu trắng OBJECT 3 $car3 = new Car(); brand = "BMW" color = "Đen" 🚗 Ô tô BMW màu đen 💡 1 Class → Vô số Objects (mỗi object độc lập)
Hình 2: Quan hệ giữa Class và Object

3. Object là gì?

Object (Đối tượng) là thực thể cụ thể được tạo từ Class. Từ 1 class có thể tạo nhiều objects.

<?php
class Car {
  public $brand;
  public $color;
  
  public function getInfo() {
    return "Xe $this->brand màu $this->color";
  }
}

// Tạo object từ class (gọi là instance)
$car1 = new Car();
$car1->brand = "Toyota";
$car1->color = "Đỏ";

$car2 = new Car();
$car2->brand = "Honda";
$car2->color = "Trắng";

echo $car1->getInfo();  // Xe Toyota màu Đỏ
echo $car2->getInfo();  // Xe Honda màu Trắng
?>

Điểm quan trọng:

  • ✅ Mỗi object độc lập – thay đổi $car1 không ảnh hưởng $car2
  • ✅ Dùng toán tử -> để truy cập properties và methods
  • ✅ Từ khóa new để tạo object mới

4. Properties (Thuộc tính)

Properties là các biến bên trong class, lưu trữ dữ liệu của object.

4.1. Khai báo Properties

<?php
class Student {
  // Khai báo properties
  public $name;
  public $age;
  public $email;
  public $gpa = 0.0;  // Giá trị mặc định
  
  // Có thể khai báo nhiều cùng lúc
  public $address, $phone;
}

// Sử dụng
$student = new Student();
$student->name = "Nguyễn Văn A";
$student->age = 20;
$student->email = "a@email.com";

echo $student->name;  // Nguyễn Văn A
echo $student->gpa;   // 0.0 (giá trị mặc định)
?>

4.2. Access Modifiers (Phạm vi truy cập)

<?php
class User {
  public $name;       // Truy cập mọi nơi
  protected $email;   // Chỉ trong class và class con
  private $password;  // Chỉ trong class này
  
  public function setPassword($pass) {
    $this->password = password_hash($pass, PASSWORD_DEFAULT);
  }
  
  public function checkPassword($pass) {
    return password_verify($pass, $this->password);
  }
}

$user = new User();
$user->name = "An";              // OK - public
$user->setPassword("secret123"); // OK - dùng method

// $user->password = "123";  // ❌ Lỗi - private không truy cập được
?>
ModifierTrong classClass conBên ngoài
public
protected
private

5. Methods (Phương thức)

Methods là các hàm bên trong class, định nghĩa hành vi của object.

CẤU TRÚC CLASS class User PROPERTIES (Thuộc tính) public $id; public $name; private $password; // Lưu dữ liệu // Biến trong class // Phạm vi truy cập METHODS (Phương thức) public function setPassword($pass) { $this->password = $pass; } public function getInfo() {...} 📦 Properties = Dữ liệu (biến) ⚙️ Methods = Hành vi (hàm)
Hình 3: Cấu trúc Class với Properties và Methods

5.1. Khai báo Methods

<?php
class Calculator {
  public $result = 0;
  
  // Method không tham số
  public function reset() {
    $this->result = 0;
  }
  
  // Method có tham số
  public function add($a, $b) {
    $this->result = $a + $b;
    return $this->result;
  }
  
  // Method trả về giá trị
  public function getResult() {
    return $this->result;
  }
  
  // Method gọi method khác
  public function addAndShow($a, $b) {
    $this->add($a, $b);
    echo "Kết quả: " . $this->getResult();
  }
}

$calc = new Calculator();
echo $calc->add(5, 3);        // 8
$calc->addAndShow(10, 20);    // Kết quả: 30
?>

5.2. $this – Tham chiếu đến object hiện tại

<?php
class BankAccount {
  public $balance = 0;
  
  public function deposit($amount) {
    // $this trỏ đến object đang gọi method
    $this->balance += $amount;
    return $this;  // Trả về chính object (method chaining)
  }
  
  public function withdraw($amount) {
    if ($amount <= $this->balance) {
      $this->balance -= $amount;
    } else {
      echo "Số dư không đủ!";
    }
    return $this;
  }
  
  public function getBalance() {
    return $this->balance;
  }
}

$account = new BankAccount();

// Method chaining - gọi liên tiếp
$account->deposit(1000)
        ->deposit(500)
        ->withdraw(300);

echo $account->getBalance();  // 1200
?>

6. Ví dụ thực tế

6.1. Class User – Quản lý người dùng

<?php
class User {
  // Properties
  public $id;
  public $name;
  public $email;
  private $password;
  public $created_at;
  
  // Setter cho password (mã hóa)
  public function setPassword($password) {
    $this->password = password_hash($password, PASSWORD_DEFAULT);
  }
  
  // Kiểm tra mật khẩu
  public function checkPassword($password) {
    return password_verify($password, $this->password);
  }
  
  // Lấy thông tin user
  public function getInfo() {
    return [
      'id' => $this->id,
      'name' => $this->name,
      'email' => $this->email,
      'created_at' => $this->created_at
    ];
  }
  
  // Hiển thị thông tin
  public function display() {
    echo "<div class='user-card'>";
    echo "<h3>$this->name</h3>";
    echo "<p>Email: $this->email</p>";
    echo "<p>ID: $this->id</p>";
    echo "</div>";
  }
}

// Sử dụng
$user = new User();
$user->id = 1;
$user->name = "Nguyễn Văn A";
$user->email = "a@email.com";
$user->setPassword("password123");
$user->created_at = date("Y-m-d H:i:s");

// Kiểm tra mật khẩu
if ($user->checkPassword("password123")) {
  echo "Đăng nhập thành công!";
}

// Hiển thị thông tin
$user->display();

// Lấy mảng thông tin
$info = $user->getInfo();
print_r($info);
?>

6.2. Class Product – Quản lý sản phẩm

<?php
class Product {
  public $id;
  public $name;
  public $price;
  public $quantity;
  public $category;
  
  // Tính tổng giá trị
  public function getTotalValue() {
    return $this->price * $this->quantity;
  }
  
  // Kiểm tra còn hàng
  public function inStock() {
    return $this->quantity > 0;
  }
  
  // Giảm giá
  public function applyDiscount($percent) {
    $discount = $this->price * ($percent / 100);
    $this->price -= $discount;
    return $this->price;
  }
  
  // Format giá tiền
  public function formatPrice() {
    return number_format($this->price, 0, ',', '.') . ' VNĐ';
  }
  
  // Hiển thị thông tin
  public function display() {
    $status = $this->inStock() ? "Còn hàng" : "Hết hàng";
    
    echo "<div class='product'>";
    echo "<h3>$this->name</h3>";
    echo "<p>Giá: " . $this->formatPrice() . "</p>";
    echo "<p>Số lượng: $this->quantity</p>";
    echo "<p>Trạng thái: $status</p>";
    echo "<p>Tổng giá trị: " . number_format($this->getTotalValue(), 0, ',', '.') . " VNĐ</p>";
    echo "</div>";
  }
}

// Sử dụng
$product = new Product();
$product->id = 1;
$product->name = "Laptop Dell XPS 13";
$product->price = 25000000;
$product->quantity = 5;
$product->category = "Laptop";

echo $product->formatPrice();           // 25,000,000 VNĐ
echo $product->getTotalValue();         // 125000000

// Giảm giá 10%
$product->applyDiscount(10);
echo $product->formatPrice();           // 22,500,000 VNĐ

// Hiển thị
$product->display();
?>

6.3. Class ShoppingCart – Giỏ hàng

<?php
class ShoppingCart {
  private $items = [];
  
  // Thêm sản phẩm
  public function addItem($product, $quantity = 1) {
    $item = [
      'product' => $product,
      'quantity' => $quantity
    ];
    
    $this->items[] = $item;
  }
  
  // Đếm số mặt hàng
  public function getItemCount() {
    return count($this->items);
  }
  
  // Tính tổng tiền
  public function getTotal() {
    $total = 0;
    
    foreach ($this->items as $item) {
      $total += $item['product']->price * $item['quantity'];
    }
    
    return $total;
  }
  
  // Hiển thị giỏ hàng
  public function display() {
    if (empty($this->items)) {
      echo "Giỏ hàng trống";
      return;
    }
    
    echo "<h2>Giỏ hàng của bạn</h2>";
    echo "<table>";
    echo "<tr><th>Sản phẩm</th><th>Giá</th><th>SL</th><th>Thành tiền</th></tr>";
    
    foreach ($this->items as $item) {
      $product = $item['product'];
      $quantity = $item['quantity'];
      $subtotal = $product->price * $quantity;
      
      echo "<tr>";
      echo "<td>{$product->name}</td>";
      echo "<td>" . number_format($product->price) . "</td>";
      echo "<td>{$quantity}</td>";
      echo "<td>" . number_format($subtotal) . " VNĐ</td>";
      echo "</tr>";
    }
    
    echo "<tr><td colspan='3'><strong>Tổng cộng</strong></td>";
    echo "<td><strong>" . number_format($this->getTotal()) . " VNĐ</strong></td></tr>";
    echo "</table>";
  }
}

// Sử dụng
$product1 = new Product();
$product1->name = "Laptop";
$product1->price = 15000000;

$product2 = new Product();
$product2->name = "Chuột";
$product2->price = 200000;

$cart = new ShoppingCart();
$cart->addItem($product1, 1);
$cart->addItem($product2, 2);

echo "Số sản phẩm: " . $cart->getItemCount();  // 2
echo "Tổng tiền: " . number_format($cart->getTotal());  // 15,400,000

$cart->display();
?>

7. Kiểm tra object và class

<?php
class Car {
  public $brand;
}

$car = new Car();
$car->brand = "Toyota";

// Kiểm tra có phải object không
var_dump(is_object($car));  // bool(true)

// Lấy tên class
echo get_class($car);  // Car

// Kiểm tra object thuộc class nào
var_dump($car instanceof Car);  // bool(true)

// Kiểm tra property tồn tại
var_dump(property_exists($car, 'brand'));  // bool(true)
var_dump(property_exists($car, 'color'));  // bool(false)

// Kiểm tra method tồn tại
var_dump(method_exists($car, 'start'));  // bool(false)

// Lấy danh sách properties
$props = get_object_vars($car);
print_r($props);  // Array ( [brand] => Toyota )

// Lấy danh sách methods
$methods = get_class_methods('Car');
print_r($methods);
?>

8. Best Practices

8.1. Quy tắc đặt tên

<?php
// ✅ Tên class: PascalCase (viết hoa chữ cái đầu mỗi từ)
class UserAccount { }
class ShoppingCart { }

// ✅ Tên property/method: camelCase
class Product {
  public $productName;
  public $unitPrice;
  
  public function getDiscountPrice() { }
  public function calculateTotalValue() { }
}

// ❌ Sai
class user_account { }  // Không dùng snake_case cho class
class product {
  public $ProductName;  // Không viết hoa property
  public function Get_Price() { }  // Không viết hoa hoặc dùng underscore
}
?>

8.2. Một class một file

<?php
// File: User.php
class User {
  // ...
}

// File: Product.php
class Product {
  // ...
}

// File: index.php
require_once 'User.php';
require_once 'Product.php';

$user = new User();
$product = new Product();
?>

8.3. Properties nên là private/protected

<?php
class User {
  // ✅ Tốt - Dùng private với getter/setter
  private $email;
  
  public function setEmail($email) {
    if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
      $this->email = $email;
    } else {
      throw new Exception("Email không hợp lệ");
    }
  }
  
  public function getEmail() {
    return $this->email;
  }
  
  // ❌ Tránh - Public cho phép gán bừa
  public $password;  // Ai cũng gán được, không an toàn
}
?>

Tóm tắt

Qua bài này bạn đã nắm được:

  • OOP: Lập trình hướng đối tượng – tổ chức code thành objects
  • Class: Bản thiết kế (blueprint) để tạo objects
  • Object: Thực thể cụ thể được tạo từ class bằng từ khóa new
  • Properties: Biến bên trong class, lưu dữ liệu của object
  • Methods: Hàm bên trong class, định nghĩa hành vi của object
  • $this: Tham chiếu đến object hiện tại
  • Access Modifiers: public (mọi nơi), protected (class + con), private (chỉ trong class)
  • Toán tử ->: Truy cập properties và methods của object
  • Method Chaining: Return $this để gọi method liên tiếp

Bài tiếp theo, bạn sẽ học về Constructor và Destructor – khởi tạo và hủy object.

🎯 Bài tập thực hành

  1. Bài 1: Tạo class Book với properties: title, author, price, pages. Tạo methods: getInfo(), applyDiscount($percent), isExpensive() (giá > 500k).
  2. Bài 2: Tạo class BankAccount với private property balance. Tạo methods: deposit($amount), withdraw($amount), getBalance(). Validate số tiền phải > 0.
  3. Bài 3: Tạo class Student với properties: name, email, scores (mảng điểm). Tạo methods: addScore($score), getAverage(), getGrade() (A/B/C/D/F).

Gợi ý Bài 1:

<?php
class Book {
  public $title;
  public $author;
  public $price;
  public $pages;
  
  public function getInfo() {
    return "$this->title - Tác giả: $this->author - Giá: " . number_format($this->price) . " VNĐ";
  }
  
  public function applyDiscount($percent) {
    $this->price -= $this->price * ($percent / 100);
    return $this->price;
  }
  
  public function isExpensive() {
    return $this->price > 500000;
  }
}

$book = new Book();
$book->title = "Lập trình PHP";
$book->author = "Nguyễn Văn A";
$book->price = 600000;
$book->pages = 500;

echo $book->getInfo();
echo $book->isExpensive() ? "Sách đắt" : "Sách rẻ";
$book->applyDiscount(10);  // Giảm 10%
?>

Gợi ý Bài 2:

<?php
class BankAccount {
  private $balance = 0;
  
  public function deposit($amount) {
    if ($amount <= 0) {
      echo "Số tiền phải > 0";
      return false;
    }
    
    $this->balance += $amount;
    return true;
  }
  
  public function withdraw($amount) {
    if ($amount <= 0) {
      echo "Số tiền phải > 0";
      return false;
    }
    
    if ($amount > $this->balance) {
      echo "Số dư không đủ";
      return false;
    }
    
    $this->balance -= $amount;
    return true;
  }
  
  public function getBalance() {
    return $this->balance;
  }
}

$account = new BankAccount();
$account->deposit(1000000);
$account->withdraw(300000);
echo $account->getBalance();  // 700000
?>

Để lại bình luận

Email của bạn sẽ không được hiển thị.