Trong PHP, self$this là hai từ khóa có vai trò quan trọng trong lập trình hướng đối tượng, nhưng chúng có cách sử dụng và ý nghĩa khác nhau. Dưới đây là sự khác biệt cơ bản giữa hai từ khóa này:

1. self

  • Được sử dụng trong phương thức tĩnh (static method): self được dùng để truy cập các thuộc tính và phương thức tĩnh (static properties và static methods) trong cùng một lớp.
  • Truy cập trực tiếp trong lớp: self dùng để chỉ chính lớp hiện tại tại thời điểm biên dịch, không liên quan đến bất kỳ đối tượng nào. Điều này có nghĩa là self chỉ có thể được sử dụng để gọi các thành viên tĩnh, không thể truy cập các thuộc tính hoặc phương thức không tĩnh.

Ví dụ:

class Example {
    public static $name = "PHP";
    
    public static function getName() {
        return self::$name; // sử dụng self để gọi biến static
    }
}
echo Example::getName(); // Output: PHP
  • Không sử dụng được với đối tượng cụ thể: Vì self chỉ tham chiếu đến lớp hiện tại, nó không thể được dùng để truy cập các thuộc tính hoặc phương thức không tĩnh trong lớp mà cần có một đối tượng để tham chiếu.

2. $this

  • Được sử dụng trong các phương thức không tĩnh (non-static method): $this là một tham chiếu đến đối tượng hiện tại của lớp và chỉ có thể được sử dụng trong các phương thức không tĩnh.
  • Truy cập các thuộc tính và phương thức của đối tượng: $this được dùng để truy cập các thuộc tính và phương thức của đối tượng mà phương thức không tĩnh đang được gọi. Nó giúp bạn truy cập và làm việc với dữ liệu cụ thể của một đối tượng.

Ví dụ:

class Example {
    public $name = "PHP";
    
    public function getName() {
        return $this->name; // sử dụng $this để gọi thuộc tính của đối tượng
    }
}

$obj = new Example();
echo $obj->getName(); // Output: PHP
  • Chỉ khả dụng khi một đối tượng tồn tại: $this chỉ có thể được sử dụng khi phương thức không tĩnh được gọi từ một đối tượng của lớp. Nó không thể được sử dụng trong các phương thức tĩnh vì không có đối tượng cụ thể nào tại thời điểm đó.

Tóm tắt sự khác biệt:

Đặc điểmself$this
Phạm vi sử dụngChỉ trong phương thức tĩnh (static)Chỉ trong phương thức không tĩnh (non-static)
Tham chiếu đếnLớp hiện tạiĐối tượng hiện tại
Truy cậpThuộc tính và phương thức tĩnhThuộc tính và phương thức của đối tượng
Cách gọiself::method() hoặc self::$property$this->method() hoặc $this->property
Thời điểm sử dụngKhi không cần đối tượngKhi cần thao tác trên một đối tượng cụ thể

Như vậy, self thường dùng khi bạn làm việc với các thành viên tĩnh của lớp, còn $this thì dùng để tương tác với đối tượng hiện tại.

3. Hạn Chế Của Việc Gọi self Trong Lớp Cha Khi Kế Thừa Trong PHP

Trong PHP, khi một lớp con kế thừa từ một lớp cha, việc gọi self trong lớp cha không kế thừa được toàn bộ theo cách bạn có thể mong đợi. Dưới đây là chi tiết cách hoạt động và hạn chế của việc sử dụng self trong ngữ cảnh kế thừa:

3.1 Cách hoạt động của self trong lớp cha và kế thừa

  • Khi bạn sử dụng self trong lớp cha, nó sẽ luôn tham chiếu đến lớp mà nó được định nghĩa (tức là lớp cha), không phải lớp con.
  • Do đó, khi lớp con kế thừa một phương thức từ lớp cha mà có sử dụng self, thì self vẫn sẽ tham chiếu đến lớp cha, không phải lớp con.

Ví dụ:

class ParentClass {
    public static function who() {
        echo "Lớp cha: " . __CLASS__;
    }
    
    public static function callWho() {
        self::who(); // self sẽ gọi phương thức của chính lớp ParentClass
    }
}

class ChildClass extends ParentClass {
    public static function who() {
        echo "Lớp con: " . __CLASS__;
    }
}

ChildClass::callWho(); // Kết quả là "Lớp cha: ParentClass"

Phân tích:

  • Khi bạn gọi ChildClass::callWho(), phương thức callWho() được kế thừa từ lớp cha ParentClass, và bên trong phương thức đó, self::who() được gọi.
  • Mặc dù bạn gọi từ lớp con (ChildClass), nhưng self trong lớp cha vẫn luôn tham chiếu đến ParentClass, nên kết quả trả về là "Lớp cha: ParentClass".
  • Không kế thừa hành vi của self theo kiểu “động,” nghĩa là self luôn tham chiếu đến lớp mà nó được định nghĩa.

3.2 Cách khắc phục bằng static (Late Static Binding)

Nếu bạn muốn trong trường hợp này, phương thức who() trong lớp con được gọi thay vì lớp cha, bạn có thể sử dụng từ khóa static thay cho self. Đây là khái niệm “Late Static Binding” trong PHP, và nó cho phép phương thức gọi chính lớp thực tế (tức là lớp con) khi phương thức tĩnh được kế thừa.

Ví dụ sử dụng static:

class ParentClass {
    public static function who() {
        echo "Lớp cha: " . __CLASS__;
    }
    
    public static function callWho() {
        static::who(); // static sẽ gọi phương thức của lớp thực tế, tức là ChildClass
    }
}

class ChildClass extends ParentClass {
    public static function who() {
        echo "Lớp con: " . __CLASS__;
    }
}

ChildClass::callWho(); // Kết quả là "Lớp con: ChildClass"

Phân tích:

  • Khi sử dụng static::who() thay vì self::who(), PHP sử dụng cơ chế “Late Static Binding”, cho phép phương thức who() trong lớp con (ChildClass) được gọi. Kết quả lúc này sẽ là "Lớp con: ChildClass".

Tóm tắt:

Nếu muốn lớp con có thể ghi đè và gọi phương thức của chính nó, bạn nên sử dụng static để tận dụng cơ chế Late Static Binding.

self trong lớp cha sẽ luôn tham chiếu đến lớp mà nó được định nghĩa (lớp cha), kể cả khi được gọi từ lớp con.