__serialize và __unserialize
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 49 trên 91.
Khi cần chuyển đổi một đối tượng thành chuỗi để lưu trữ hoặc truyền đi, PHP sử dụng tuần tự hóa (serialization). Các phương thức ma thuật __serialize() và __unserialize() cho phép bạn kiểm soát chính xác dữ liệu nào được lưu và cách khôi phục dữ liệu đó.
Phương thức __serialize() trả về một mảng dữ liệu cần được tuần tự hóa, còn __unserialize() nhận mảng đó và dựng lại đối tượng:
<?php
class Session {
public function __construct(
private string $userId,
private array $data,
private int $createdAt
) {}
public function __serialize(): array {
return [
'userId' => $this->userId,
'data' => $this->data
];
}
public function __unserialize(array $data): void {
$this->userId = $data['userId'];
$this->data = $data['data'];
$this->createdAt = time();
}
public function getCreatedAt(): int {
return $this->createdAt;
}
}
$session = new Session("user123", ["theme" => "dark"], time());
$serialized = serialize($session);
$restored = unserialize($serialized);
echo "Created at: " . $restored->getCreatedAt();
Hãy chú ý rằng createdAt bị loại khỏi quá trình tuần tự hóa (serialization) và có dấu thời gian mới khi giải tuần tự hóa. Cách này hữu ích khi cần loại trừ dữ liệu nhạy cảm, giá trị tạm thời hoặc tài nguyên không thể tuần tự hóa như kết nối cơ sở dữ liệu.
Các phương thức này đã thay thế các phương thức cũ hơn __sleep() và __wakeup() trong PHP 7.4, mang đến cách tiếp cận gọn gàng hơn, cho phép bạn làm việc trực tiếp với các mảng dữ liệu thay vì tên thuộc tính.
Thử thách
DễHãy xây dựng một hệ thống lưu vào bộ nhớ đệm hồ sơ người dùng để minh họa cách __serialize() và __unserialize() cho bạn quyền kiểm soát dữ liệu nào được lưu và cách khôi phục dữ liệu đó.
Bạn sẽ sắp xếp code trong hai tệp:
UserProfile.php: Tạo lớpUserProfileđại diện cho hồ sơ người dùng có khả năng lưu vào bộ nhớ đệm. Dùng cách khai báo thuộc tính ngay trong hàm khởi tạo để định nghĩa các thuộc tính riêng tư$userId(chuỗi),$username(chuỗi),$email(chuỗi) và$accessToken(chuỗi). Thêm thuộc tính riêng tư$cachedAtđể lưu thời điểm hồ sơ được lưu vào bộ nhớ đệm (ban đầu đặt thành"not cached"trong hàm khởi tạo). Lớp của bạn cần có:__serialize(): Trả về một mảng chỉ chứauserId,usernamevàemail.accessTokenchứa thông tin nhạy cảm và không bao giờ được tuần tự hóa. Dấu thời giancachedAtsẽ được tạo lại khi khôi phục.__unserialize(): Khôi phụcuserId,usernamevàemailtừ mảng dữ liệu. ĐặtaccessTokenthành"expired"(vì token không nên được lưu lại).getInfo(): Trả về một chuỗi theo định dạng:"[username] ([email]) - Token: [accessToken] - Cached: [cachedAt]"
main.php: Nạp tệp UserProfile. Bạn sẽ nhận bốn đầu vào: ID người dùng, tên người dùng, email và access token. Tạo một instanceUserProfilevới các giá trị này. In ra ba dòng:- Thông tin hồ sơ ban đầu (trước khi tuần tự hóa)
- Tuần tự hóa hồ sơ bằng
serialize(), sau đó giải tuần tự hóa bằngunserialize()để tạo hồ sơ đã khôi phục. In thông tin hồ sơ đã khôi phục. - In ra
"Token preserved: yes"hoặc"Token preserved: no"tùy vào việc token của hồ sơ đã khôi phục có khớp với token ban đầu hay không (gợi ý: chúng không nên khớp vì token hết hạn khi khôi phục)
Mẫu này rất cần thiết để lưu dữ liệu người dùng vào bộ nhớ đệm một cách an toàn. Bạn muốn lưu thông tin hồ sơ nhưng không bao giờ lưu lại thông tin xác thực nhạy cảm như access token. Khi khôi phục hồ sơ từ bộ nhớ đệm, token được đánh dấu là hết hạn, buộc ứng dụng phải lấy token mới.
Tự làm thử
<?php
require_once 'UserProfile.php';
// Đọc dữ liệu đầu vào
$userId = trim(fgets(STDIN));
$username = trim(fgets(STDIN));
$email = trim(fgets(STDIN));
$accessToken = trim(fgets(STDIN));
// TODO: Tạo một instance UserProfile bằng các giá trị đầu vào
// TODO: In ra thông tin của hồ sơ gốc (trước khi tuần tự hóa)
// TODO: Tuần tự hóa hồ sơ, rồi giải tuần tự hóa để tạo hồ sơ được khôi phục
// TODO: In ra thông tin của hồ sơ được khôi phục
// TODO: In ra "Token preserved: yes" hoặc "Token preserved: no"
// tùy vào việc token của hồ sơ được khôi phục có khớp với token gốc hay không
?>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
1Nền tảng về OOP
Tệp bên ngoàiGiới thiệu về OOPLớp và đối tượngTừ khóa $thisPhương thứcThuộc tínhHàm khởi tạo (__construct)Hàm hủy (__destruct)Ôn tập: máy tính đơn giản4Kế thừa
Kế thừa cơ bảnTừ khóa parent::Ghi đè phương thứcTừ khóa finalLớp trừu tượngÔn tập: hệ thống phân cấp nhân viên7Đóng gói
Công khai, được bảo vệ, riêng tưTìm hiểu sâu về bộ điều chỉnh quyền truy cậpGetter và setterẨn thông tinRút gọn hàm khởi tạo (8.0)Ôn tập: hệ thống hồ sơ học sinh2Không gian tên và tự động nạp
Giới thiệu về không gian tênTừ khóa useChuẩn tự động nạp PSR-4Trình tự động nạp của ComposerÔn tập: dự án có tổ chức5Giao diện và hợp đồng
Giới thiệu về giao diệnTriển khai giao diệnTriển khai nhiều giao diệnGiao diện và lớp trừu tượngGợi ý kiểu với giao diệnÔn tập: Máy tính hình học8Phương thức ma thuật
Giới thiệu về phương thức ma thuật__toString và __debugInfo__get, __set, __isset, __unset__call và __callStatic__clone và sao chép đối tượng__serialize và __unserializeÔn tập: Bộ sưu tập tùy chỉnh3Thuộc tính của lớp
Thuộc tính instance và staticHằng số trong lớpPhương thức và thuộc tính staticThuộc tính private và protectedThuộc tính chỉ đọc (PHP 8.1)Ôn tập: Trình quản lý tài khoản ngân hàng6Đa hình
Xem lại việc ghi đè phương thứcĐa hình qua giao diệnGợi ý kiểu và kiểu hợpLiên kết tĩnh muộnÔn tập: bộ xử lý thanh toánTự luyện tập: Trình biên dịch PHP online