Menu
CoddyTech

__get, __set, __isset, __unset

Thuộc phần Lập trình hướng đối tượng trong hành trình PHP của Coddy. Bài học 46 trên 91.

PHP cung cấp bốn phương thức ma thuật để chặn thao tác truy cập thuộc tính: __get(), __set(), __isset() và __unset(). Chúng được kích hoạt khi bạn cố truy cập các thuộc tính không tồn tại hoặc không thể truy cập.

Phương thức __get() được gọi khi đọc một thuộc tính không thể truy cập, còn __set() xử lý việc ghi vào thuộc tính đó. Nhờ vậy, bạn có thể tạo thuộc tính động hoặc thêm logic khi truy cập thuộc tính:

<?php
class DynamicObject {
    private array $data = [];
    
    public function __get(string $name): mixed {
        return $this->data[$name] ?? null;
    }
    
    public function __set(string $name, mixed $value): void {
        $this->data[$name] = $value;
    }
}

$obj = new DynamicObject();
$obj->title = "Hello";
$obj->count = 42;
echo $obj->title . " - " . $obj->count;

Đầu ra:

Hello - 42

Phương thức __isset() được gọi khi dùng isset() hoặc empty(), còn __unset() xử lý khi gọi hàm unset():

<?php
class DynamicObject {
    private array $data = [];
    
    public function __set(string $name, mixed $value): void {
        $this->data[$name] = $value;
    }
    
    public function __isset(string $name): bool {
        return isset($this->data[$name]);
    }
    
    public function __unset(string $name): void {
        unset($this->data[$name]);
    }
}

$obj = new DynamicObject();
$obj->name = "Test";
echo isset($obj->name) ? "exists" : "missing";

Đầu ra:

exists

Các phương thức này thường được dùng để tạo vùng chứa dữ liệu linh hoạt, triển khai tải dữ liệu lười hoặc xây dựng các đối tượng hoạt động như mảng mà vẫn giữ cấu trúc hướng đối tượng.

challenge icon

Thử thách

Dễ

Hãy xây dựng một trình quản lý cấu hình linh hoạt, lưu trữ các thiết lập một cách linh động bằng các phương thức ma thuật. Lớp của bạn sẽ chặn thao tác truy cập thuộc tính để quản lý các giá trị cấu hình, kiểm tra thiết lập có tồn tại hay không và xóa chúng khi cần, tất cả mà không cần định nghĩa rõ từng thuộc tính.

Bạn sẽ sắp xếp code trong hai tệp:

  • Config.php: Tạo lớp Config dùng một mảng riêng tư để lưu trữ nội bộ các giá trị cấu hình. Cài đặt cả bốn phương thức ma thuật cho thuộc tính:
    • __get($name): Trả về giá trị của khóa đã cho, hoặc "undefined" nếu khóa không tồn tại
    • __set($name, $value): Lưu giá trị dưới khóa đã cho
    • __isset($name): Trả về kết quả cho biết khóa có tồn tại trong cấu hình hay không
    • __unset($name): Xóa khóa khỏi cấu hình
    Đồng thời thêm phương thức count() để trả về số lượng thiết lập đã lưu.
  • main.php: Nạp tệp Config. Bạn sẽ nhận ba đầu vào: tên một thiết lập, giá trị của thiết lập đó và tên một thiết lập thứ hai. Tạo một instance Config và thực hiện các thao tác sau:
    • Đặt giá trị đã cho cho thiết lập thứ nhất
    • In ra thiết lập thứ nhất có tồn tại hay không bằng isset(): xuất "exists" hoặc "missing"
    • In ra giá trị của thiết lập thứ nhất
    • In ra số lượng thiết lập hiện tại
    • Dùng unset() để xóa thiết lập thứ nhất
    • In ra thiết lập thứ nhất hiện có tồn tại hay không: xuất "exists" hoặc "missing"
    • In ra giá trị của thiết lập thứ hai (thiết lập này chưa từng được đặt)

Mỗi kết quả đầu ra phải nằm trên một dòng riêng. Các phương thức ma thuật cho phép bạn tương tác với đối tượng Config bằng cú pháp thuộc tính tự nhiên như $config->theme = "dark" và isset($config->theme), dù không có thuộc tính thực nào được định nghĩa.

Tự làm thử

<?php

require_once 'Config.php';

// Đọc dữ liệu đầu vào
$settingName1 = trim(fgets(STDIN));
$settingValue = trim(fgets(STDIN));
$settingName2 = trim(fgets(STDIN));

// TODO: Tạo một instance của Config

// TODO: Gán giá trị đã cho cho thiết lập đầu tiên

// TODO: In ra thiết lập đầu tiên có tồn tại hay không ("exists" hoặc "missing")

// TODO: In ra giá trị của thiết lập đầu tiên

// TODO: In ra số lượng thiết lập hiện tại

// TODO: Dùng unset() để xóa thiết lập đầu tiên

// TODO: In ra thiết lập đầu tiên hiện có tồn tại hay không ("exists" hoặc "missing")

// TODO: In ra giá trị của thiết lập thứ hai (thiết lập này chưa từng được gán giá trị)

?>
quiz iconTự kiểm tra

Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.

Tất cả bài học trong Lập trình hướng đối tượng

Tự luyện tập: Trình biên dịch PHP online