Home » Bài 3: Magic methods trong PHP – Các phương thức đặc biệt

Bài 3: Magic methods trong PHP – Các phương thức đặc biệt

by Tan Nguyen
16 minutes read

Ở bài trước chúng ta đã tìm hiểu qua về phương thức (method) trong PHP là gì và cách áp dụng vào các ví dụ trong bài, qua bài tiếp theo chúng ta sẽ tìm hiểu về Magic methods là gì, tìm hiểu về ứng dụng cũng như ưu và nhược điểm của Magic methods như thế nào nhé! Các bạn có thể xem lại khái niệm về phương thức (method) ở bài Class, properties, method of Object.
Vấn đề tại sao mình lại giới thiệu về Magic method sớm trong series này như vậy bởi vì ở các bài tiếp theo các bạn sẽ phải đụng đến nó rất nhiều, các bạn cần phải hiểu và áp dụng được nó trong lập trình PHP để thao tác và học đến các bài kế tiếp nhé!

Magic methods là gì?

Magic methods là các phương thức đặc biệt để tùy biến các các sự kiện (event) khi chúng ta thao tác tới đối tượng trong php.
Hiểu đơn giản là nó cung cấp thêm cách để giải quyết một vấn đề. Magic methods được dùng để xử lý các đối tượng trong lập trình hướng đối tượng giúp ta sử dụng các đối tượng dễ dàng hơn.

magic methods php

Bài 3: Magic methods trong PHP

Thông thường mỗi magic method sẽ được kích hoạt (trigger) ở một sự kiện nào đó mà ta tác động vào đối tượng. Ví dụ hàm __get() và __set() sẽ được gọi khi ta tiến hành gán hay lấy giá trị của các thuộc tính trong đối tượng. Và vì nó có tính đặc biệt nên bạn dễ dàng nhận biết nó qua hai dấu gạch dưới (__), nghĩa là tất cả các phương thức Magic methods đều có tên bắt đầu bằng hai dấu gạch dưới.

Danh sách một số magic methods PHP cần quan tâm

  • __construct(), hàm khởi tạo, được gọi khi khởi tạo mới đối tượng
  • __destruct(), hàm hủy, được gọi khi đối tượng bị hủy
  • __get(), hàm getter, được gọi khi lấy giá trị của thuộc tính
  • __set(), hàm setter, được gọi khi gán giá trị cho thuộc tính
  • __call(), hàm call, được gọi khi ta gọi đến một phương thức không tồn tại trong đối tượng
  • __callStatic(), hàm call static, được gọi khi ta gọi đến một phương thức tĩnh không tồn tại trong đối tượng
  • __isset(), được gọi khi gọi hàm isset() hoặc empty() trên một thuộc tính không được phép truy cập.
  • __unset(), được gọi khi hàm unset() được sử dụng trong một thuộc tính không được phép truy cập.
  • __sleep(), được gọi khi serialize() một đối tượng.
  • __wakeup(), được gọi khi unserialize() đối tượng.
  • __toString(), giúp class chỉ định xem sẽ in ra cái gì khi nó được dùng
  • __invoke(), được gọi khi một lệnh cố gắng gọi một đối tượng như một hàm.
  • __set_state()
  • __clone(), được sử dụng khi chúng ta clone một object.
  • __debugInfo(), được gọi khi chúng ta sử dụng hàm vardump().

Các bạn có thể tham khảo chi tiết thêm tại php.net
Về chi tiết của từng loại magic method mình sẽ nêu rõ ở các bài viết sau và cập nhật lại cho các bạn.

Ưu điểm và nhược điểm của magic methods PHP

Ưu điểm

Từ khái niệm trên thì các bạn chắc cũng có thể nhận ra các ưu điểm của nó rồi chứ? nó gồm có các ưu điểm như sau:

  • Giúp cho chúng ta tùy biến được các hành vi.
  • Nó giúp cho chúng ta có thể khởi tạo một đối tượng theo cách mình muốn.

Nhược điểm

Nhược điểm của magic methods là có tốc độ chậm hơn các phương thức bình thường.

Ví dụ một số magic methods PHP

__construct()

Hàm được gọi khi ta khởi tạo một đối tượng.
Trong php thì magic method __construct() rất là phổ biến mà chúng ta hay thường gặp nhất. Hàm __construct() sẽ tự đông được gọi khi ta khởi tạo 1 đối tượng( còn được gọi là hàm khởi tạo).

<?php
class A
{
    public function __construct($text)
    {
        echo "$text";
    }
}
$tweet = new A('Hello World');

Không giống như các ngôn ngữ lập trình hướng đối tượng như java hay C#. Trong PHP, hàm khởi tạo không cho phép chúng ta thực hiện việc overload, nó chỉ cho phép khởi tạo 1 đối tượng duy nhất ứng với method __contructs() được khai báo trong class(không khai báo mặc định là không truyền gì).
Ví dụ :

<?php
class A
{
    public function __construct($text)
    {
        echo 'So luong tham so truyen vao: '. count($text);
    }
}
$tweet = new A('Hello World','Hi'); // so luong tham so truyen vao la 2
echo '<br>';
$var = new A(); //sẽ xảy ra lỗi

Chúng ta thấy nó không thể khởi tạo được biến thứ 2 do method __contruct() ta có tham số truyền vào.
Để khắc phục việc không cho overload, trong php có tùy biến như sau :

<?php
class A
{
    public function __construct(...$text)
    {
        echo 'So luong tham so truyen vao: '. count($text);
    }
}
$tweet = new A('Hello World','Hi'); // so luong tham so truyen vao la 2
echo '<br>';
$var = new A();

Chỉ cần thêm ba chấm trước biến  được truyền vào thì sẽ không còn bug nữa.

__destruct()

Được gọi khi một đối tượng bị hủy. Mặc định khi kết thúc chương trình hoặc khi ta khai báo mới đối tượng đó sẽ bị hủy bỏ và gọi đến method __destruct().

<?php
class A
{
    public function __construct(...$text)
    {
        $this->text = $text;
    }
    public function __destruct()
    {
        echo '<br>';
        echo "Huy doi tuong co " . count($this->text) . ' tham so truyen vao.';
    }
}
$tweet = new A('2', '5'); // so luong tham so truyen vao la 2
$var = new A(); // so luong tham so truyen vao la 0
$test = new A('60'); // so luong tham so truyen vao la 1
echo 'End';

Như trên ví dụ ta có thể thấy đối tượng tạo trước sẽ bị hủy sau khi chương trình kết thúc.

__set()

Gọi khi ta truyền dữ liệu vào thuộc tính không tồn tại hoặc thuộc tính private trong đối tượng.

<?php
class A
{
    public function __set($key, $value)
    {
        echo "$key <br> $value";
    }
}
$tweet = new A(); 
$tweet->name = 'Dao Cong Van';
/* output:
name
Dao Cong Van
*/

Nó truyền dưới dạng key => value. Như ở ví dụ trên, ta set giá trị cho thuộc tính name mà không tồn tại trong class. Nó sẽ gọi đến hàm __set() với $key là thuộc tính đã gọi, $value là giá trị đã gán.

__get()

Gọi khi ta truy cập vào thuộc tính không tồn tại hoặc thuộc tính private trong đối tượng. Tương tự như set, get là việc xử lý khi truy cập đối tượng.

<?php
class A
{
    public function __get($key)
    {
        echo "Xin chao $key";
    }
}
$tweet = new A(); 
$tweet->people;
/* output:
Xin chao people
*/

__isset()

Phương thức __isset() sẽ được gọi khi chúng ta thực hiện kiểm tra một thuộc tính không được phép truy cập của một đối tượng, hay kiểm tra một thuộc tính không tồn tại trong đối tượng đó. Cụ thể là hàm isset() và hàm empty().
Chú ý: phương thức __isset() không sử dụng được với thuộc tính tĩnh.

<?php
class A
{
    public function __isset($key)
    {
        echo "Thuoc tinh kiem tra khong ton tai: $key";
    }
}
$tweet = new A(); 
isset($tweet->people);
/* output:
Thuoc tinh kiem tra khong ton tai: people
*/

__unset()

Được gọi khi hàm unset() được sử dụng trong một thuộc tính không được phép truy cập. Tương tự như hàm isset. Khi ta Unset 1 thuộc tính không tồn tại thì method __unset() sẽ được gọi.

<?php
class A
{
    public function __unset($key)
    {
        echo "Thuoc tinh kiem tra khong ton tai: $key";
    }
}
$tweet = new A(); 
unset($tweet->people);
/* output:
Thuoc tinh kiem tra khong ton tai: people
*/

__call()

Được gọi khi ta gọi một phương thức không được phép truy cập trong phạm vi của một đối tượng. Như vậy thì có thể thấy __get() và __call() cũng gần giống nhau. Có điều __get() gọi khi không có thuộc tính còn __call() khi phương thức không có. Ta cũng có thể dùng hàm __call() để thực hiện overload trong php.
Khai báo : __call($method_name, $parameter)
Trong đó:

  • $method_name: là phương thức được gọi mà không tồn tại.
  • $parameter: là tham số truyền vào( là mảng).
<?php
class A
{
    public function __call($method_name, $parameter)
    {
        if ($method_name == "overloadFunction") {
            $count = count($parameter);
            switch ($count) {
                case "1":
                    echo 'code cho moi doi so';
                    break;
                case '2':
                    echo 'Code cho 2 doi so';
                    break;
                default:
                    throw new Exception('Bad argument');
            }
        } else {
            throw new Exception('Function $method_name does not exists');
        }
    }
}
$var = new A();
$var->overloadFunction('1');
echo '<br>';
$var->overloadFunction('2');
echo '<br>';
$var->overloadFunction('2', '3');
/*output:
code cho moi doi so
code cho moi doi so
Code cho 2 doi so
*/

 
Chúng ta có thể thấy trong class test không hề có hàm overloadFunction. Khi ta gọi tới phương thức overloadFunction thì nó sẽ chạy hàm __call().

__callstatic()

Được kích hoạt khi ta gọi một phương thức không được phép truy cập trong phạm vi của một phương thức tĩnh.

<?php
class A
{
    public static function __callStatic($name, $arguments)
    {
        echo "Ban vua goi phuong thuc " . $name . " va co cac tham so: " . implode(' - ', $arguments);
    }
}
A::getInfo('name', 'age', 'address');
/* output:
Ban vua goi phuong thuc getInfova co cac tham so: name - age - address
*/

__toString()

Phương thức này được gọi khi chúng ta in echo đối tượng. Method __toString() sẽ bắt buộc phải trả về 1 dãy String.

<?php
class A
{
    public function __toString()
    {
        echo "Xin chao";
        return ' moi nguoi';
    }
}
$var = new A();
echo $var;
/* output:
Xin chao moi nguoi
*/

__invoke()

Phương thức này được gọi khi ta cố gắng gọi một đối tượng như một hàm.

<?php
class A
{
    public function __invoke($name)
    {
        echo $name;
    }
}
$var = new A();
$var('Bui Chi Cong');
/* output:
Bui Chi Cong
*/

__Sleep()

Được gọi khi serialize() một đối tượng. Thông thường khi chúng ta serialize() một đối tượng thì nó sẽ trả về tất cả các thuộc tính trong đối tượng đó. Nhưng nếu sử dụng __sleep() thì chúng ta có thể quy định được các thuộc tính có thể trả về.

<?php
class A
{
    private $name = 'Nguyen Minh';
    private $age = 20;
    public function __sleep()
    {
        return array('name');
    }
}
echo serialize(new A());
/*output:
O:1:"A":1:{s:7:"Aname";s:11:"Nguyen Minh";}
*/

__wakeup

Được gọi khi unserialize() đối tượng.

<?php
class A
{
    public function __wakeup()
    {
        echo 'Hello';
    }
}
unserialize(serialize(new A()));
/* output:
Hello
*/

__set_state()

Được sử dụng khi chúng ta var_export một object.

<?php
class A
{
    public function __set_state()
    {
        echo 'Hello';
    }
}
$var = new A();
var_export($var);
/* output:
A::__set_state(array( ))
*/

__clone()

Được sử dụng khi chúng ta clone(sao chép 1 đối tượng thành 1 đối tượng hoàn toàn mới không liên quan đến đối tượng cũ) một object.

<?php
class A
{
    public function __clone()
    {
        echo 'Doi tuong vua duoc sinh ra';
    }
}
$var = new A();
$var2 = clone $var;
/* output:
Doi tuong vua duoc sinh ra
*/

__debugInfo()

Được gọi khi chúng ta sử dụng hàm vardump().

<?php
class A
{
    public function __debugInfo()
    {
        echo 'Debug.';
    }
}
$var = new A();
var_dump($var);

Kết thúc

Bài viết đã tổng quan về magic methods và cách sử dụng chúng. Việc sử dụng magic methods khá là hữu ích nhưng chúng ta cũng không nên lạm dụng vì nó chậm hơn methods thường.
Về một số magic method quan trọng trong PHP mình sẽ có những bài viết riêng về chúng ở những bài sau cho các bạn tham khảo nhé!
Xem thêm:

Nếu các bạn cảm thấy Website TanHongIT.Com thật sự hữu ích mình mong các bạn có thể chia sẻ những bài viết đến cho cộng đồng cùng thao khảo nhé. Cảm ơn các bạn !!!

Các bạn có bất kì thắc mắc cần được hỗ trợ hay yêu cầu các phần mềm, thủ thuật, khoá học,… thì cứ để lại comment bên dưới bài viết hoặc liên hệ qua fanpage của TanHongIT để được hỗ trợ nhé! Mình sẽ cố gắng chia sẻ cho các bạn mọi thứ cần thiết nhất!

refer viblo
CHÚC CÁC BẠN THÀNH CÔNG VÀ VUI VẺ
5/5 - (6 votes)

Related Posts

5 1 vote
Article Rating
Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments

This website uses cookies to improve your experience. We'll assume you're ok with this, but you can opt-out if you wish. Accept Read More

0
Would love your thoughts, please comment.x
()
x