PHP Cơ bản
PHP Nâng cao
PHP & Cơ sở dữ liệu MySQL
Ví dụ PHP
Tài liệu tham khảo PHP
Quảng cáo

Lớp và Đối tượng PHP

Trong hướng dẫn này, bạn sẽ học cách viết mã theo kiểu hướng đối tượng trong PHP.

Lập trình hướng đối tượng là gì

Lập trình hướng đối tượng (Object-Oriented Programming: OOP) là một mô hình lập trình dựa trên khái niệm lớp và đối tượng (classes và objects). Trái ngược với lập trình thủ tục trong đó trọng tâm là viết các thủ tục hoặc hàm thực hiện các thao tác trên dữ liệu, trong lập trình hướng đối tượng, trọng tâm là sự sáng tạo của các đối tượng chứa cả dữ liệu và chức năng cùng nhau.

Lập trình hướng đối tượng có một số ưu điểm so với kiểu lập trình thông thường hoặc kiểu thủ tục. Những điều quan trọng nhất được liệt kê dưới đây:

  • Nó cung cấp một cấu trúc mô-đun rõ ràng cho các chương trình.
  • Nó giúp bạn tuân thủ nguyên tắc "không lặp lại chính mình" (don't repeat yourself: DRY) và do đó làm cho mã của bạn dễ bảo trì, sửa đổi và gỡ lỗi hơn nhiều.
  • Nó làm cho nó có thể tạo ra các hành vi phức tạp hơn với ít mã hơn và thời gian phát triển ngắn hơn và mức độ tái sử dụng cao.

Các phần sau sẽ mô tả cách hoạt động của các lớp và đối tượng trong PHP.

 

Mẹo: Ý nghĩa đằng sau nguyên tắc Không lặp lại chính mình (DRY) là giảm việc lặp lại mã bằng cách trừu tượng hóa mã phổ biến cho ứng dụng và đặt chúng ở một nơi duy nhất và sử dụng lại thay vì lặp lại.

Lớp và đối tượng (Classes và Objects) trong PHP

Lớp và đối tượng là hai khía cạnh chính của lập trình hướng đối tượng. Một lớp là một tập hợp các biến và hàm độc lập, độc lập, chúng hoạt động cùng nhau để thực hiện một hoặc nhiều tác vụ cụ thể, trong khi các đối tượng là các thể hiện riêng lẻ của một lớp.

Một lớp hoạt động như một khuôn mẫu hoặc bản thiết kế mà từ đó có thể tạo ra nhiều đối tượng riêng lẻ. Khi các đối tượng riêng lẻ được tạo ra, chúng kế thừa các thuộc tính và hành vi chung giống nhau, mặc dù mỗi đối tượng có thể có các giá trị khác nhau cho các thuộc tính nhất định.

Ví dụ, hãy nghĩ về một lớp học như một bản thiết kế cho một ngôi nhà. Bản thân bản thiết kế không phải là một ngôi nhà, mà là một kế hoạch chi tiết của ngôi nhà. Trong khi, một vật thể giống như một ngôi nhà thực tế được xây dựng theo bản thiết kế đó. Chúng ta có thể xây dựng một số ngôi nhà giống hệt nhau từ cùng một bản thiết kế, nhưng mỗi ngôi nhà có thể có các loại sơn, nội thất và gia đình bên trong khác nhau.

Một lớp có thể được khai báo bằng từ khóa class, theo sau là tên của lớp và một cặp dấu ngoặc nhọn ({}), như trong ví dụ sau.

Hãy tạo một tệp PHP có tên Rectangle.php và đặt đoạn mã ví dụ sau vào bên trong nó để mã lớp của chúng ta sẽ được tách biệt khỏi phần còn lại của chương trình. Sau đó, chúng tôi có thể sử dụng nó ở bất cứ nơi nào cần thiết bằng cách chỉ cần đưa vào tệp Rectangle.php.

Ví dụ

<?php
class Rectangle
{
    // Declare  properties
    public $length = 0;
    public $width = 0;
    
    // Method to get the perimeter
    public function getPerimeter(){
        return (2 * ($this->length + $this->width));
    }
    
    // Method to get the area
    public function getArea(){
        return ($this->length * $this->width);
    }
}
?>

Từ khóa public trước các thuộc tính và phương thức trong ví dụ trên, là một cách thức truy cập , mà chỉ ra rằng thuộc tính này hoặc phương thức có thể truy cập từ bất cứ nơi nào. Chúng ta sẽ tìm hiểu thêm về điều này ở phần sau của chương này.

 

Ghi chú: Về mặt cú pháp, các biến trong một lớp được gọi là thuộc tính , trong khi các hàm được gọi là phương thức . Ngoài ra, tên lớp theo quy ước được viết bằng PascalCase tức là mỗi từ nối bắt đầu bằng một ký tự hoa (ví dụ MyClass).

Khi một lớp đã được định nghĩa, các đối tượng có thể được tạo từ lớp bằng từ khóa new. Các phương thức và thuộc tính của lớp có thể được truy cập trực tiếp thông qua cá thể đối tượng này.

Tạo một tên tệp PHP khác test.php và đặt đoạn mã sau vào bên trong nó.

Ví dụ

<?php
// Include class definition
require "Rectangle.php";
 
// Create a new object from Rectangle class
$obj = new Rectangle;
 
// Get the object properties values
echo $obj->length; // 0utput: 0
echo $obj->width; // 0utput: 0
 
// Set object properties values
$obj->length = 30;
$obj->width = 20;
 
// Read the object properties values again to show the change
echo $obj->length; // 0utput: 30
echo $obj->width; // 0utput: 20
 
 
// Call the object methods
echo $obj->getPerimeter(); // 0utput: 100
echo $obj->getArea(); // Output: 600
?>

Biểu tượng mũi tên (->) là một cấu trúc OOP được sử dụng để truy cập các thuộc tính và phương thức chứa của một đối tượng nhất định. Trong khi đó, biến giả $this cung cấp một tham chiếu đến đối tượng đang gọi, tức là đối tượng mà phương thức thuộc về.

Sức mạnh thực sự của lập trình hướng đối tượng trở nên rõ ràng khi sử dụng nhiều phiên bản của cùng một lớp, như thể hiện trong ví dụ sau:

Ví dụ

<?php
// Include class definition
require "Rectangle.php";
 
// Create multiple objects from the Rectangle class
$obj1 = new Rectangle;
$obj2 = new Rectangle;
 
// Call the methods of both the objects
echo $obj1->getArea(); // Output: 0
echo $obj2->getArea(); // Output: 0
 
// Set $obj1 properties values
$obj1->length = 30;
$obj1->width = 20;
 
// Set $obj2 properties values
$obj2->length = 35;
$obj2->width = 50;
 
// Call the methods of both the objects again
echo $obj1->getArea(); // Output: 600
echo $obj2->getArea(); // Output: 1750
?>

Như bạn có thể thấy trong ví dụ trên, việc gọi phương thức getArea() trên các đối tượng khác nhau khiến phương thức đó hoạt động trên một tập dữ liệu khác nhau. Mỗi cá thể đối tượng là hoàn toàn độc lập, với các thuộc tính và phương thức riêng, do đó có thể được thao tác độc lập, ngay cả khi chúng thuộc cùng một lớp.

Sử dụng Hàm khởi tạo và Hàm hủy (Constructors và Destructors)

Để làm cho việc lập trình hướng đối tượng dễ dàng hơn, PHP cung cấp một số phương thức ma thuật được thực thi tự động khi một số hành động nhất định xảy ra trong một đối tượng.

Ví dụ, phương thức __construct() (được gọi là phương thức khởi tạo ) được thực thi tự động bất cứ khi nào một đối tượng mới được tạo. Tương tự, phương thức __destruct() (được gọi là hàm hủy ) được thực thi tự động khi đối tượng bị phá hủy. Một hàm hủy dọn dẹp mọi tài nguyên được phân bổ cho một đối tượng sau khi đối tượng bị hủy.

Ví dụ

<?php
class MyClass
{
    // Constructor
    public function __construct(){
        echo 'The class "' . __CLASS__ . '" was initiated!<br>';
    }
    
    // Destructor
    public function __destruct(){
        echo 'The class "' . __CLASS__ . '" was destroyed.<br>';
    }
}
 
// Create a new object
$obj = new MyClass;
 
// Output a message at the end of the file
echo "The end of the file is reached.";
?>

Mã PHP trong ví dụ trên sẽ tạo ra kết quả sau:

The class "MyClass" was initiated!
The end of the file is reached.
The class "MyClass" was destroyed.

Một trình hủy được gọi tự động khi một tập lệnh kết thúc. Tuy nhiên, để kích hoạt trình hủy một cách rõ ràng, bạn có thể hủy đối tượng bằng cách sử dụng hàm PHP unset(), như sau:

Ví dụ

<?php
class MyClass
{
    // Constructor
    public function __construct(){
        echo 'The class "' . __CLASS__ . '" was initiated!<br>';
    }
    
    // Destructor
    public function __destruct(){
    echo 'The class "' . __CLASS__ . '" was destroyed.<br>';
    }
}
 
// Create a new object
$obj = new MyClass;
 
// Destroy the object
unset($obj);
 
// Output a message at the end of the file
echo "The end of the file is reached.";
?>

Bây giờ, mã PHP trong ví dụ trên sẽ tạo ra kết quả sau:

The class "MyClass" was initiated!
The class "MyClass" was destroyed.
The end of the file is reached.
 

Mẹo: PHP tự động dọn dẹp tất cả các tài nguyên được cấp phát trong quá trình thực thi khi tập lệnh kết thúc, ví dụ: đóng các kết nối cơ sở dữ liệu, hủy các đối tượng, v.v.

 

Ghi chú: __CLASS__ là một hằng số ma thuật chứa tên của lớp mà nó xuất hiện. Nó trống, nếu nó xảy ra bên ngoài lớp.

Mở rộng lớp thông qua kế thừa

Các lớp có thể kế thừa các thuộc tính và phương thức của một lớp khác bằng cách sử dụng từ khóa extends. Quá trình mở rộng này được gọi là kế thừa. Đó có lẽ là lý do mạnh mẽ nhất đằng sau việc sử dụng mô hình lập trình hướng đối tượng.

Ví dụ

<?php
// Include class definition
require "Rectangle.php";
 
// Define a new class based on an existing class
class Square extends Rectangle
{   
    // Method to test if the rectangle is also a square
    public function isSquare(){
        if($this->length == $this->width){
            return true; // Square
        } else{
            return false; // Not a square
        }
    }
}
 
// Create a new object from Square class
$obj = new Square;
 
// Set object properties values
$obj->length = 20;
$obj->width = 20;
 
// Call the object methods
if($obj->isSquare()){
    echo "The area of the square is ";
} else{
    echo "The area of the rectangle is ";
};
echo $obj->getArea();
?>

Mã PHP trong ví dụ trên sẽ tạo ra kết quả sau:

The area of the square is 400

Như bạn có thể thấy trong ví dụ trên, mặc dù định nghĩa lớp của Square không chứa phương thức getArea() cũng như thuộc tính $length và thuộc tính $width một cách rõ ràng , các phương thức của lớp Square có thể sử dụng chúng, vì chúng được kế thừa từ lớp cha Rectangle.

 

Mẹo: Vì một lớp con được dẫn xuất từ lớp cha, nó cũng được gọi là lớp dẫn xuất và lớp cha của nó được gọi là lớp cơ sở.

Kiểm soát khả năng hiển thị của các thuộc tính và phương thức

Khi làm việc với các lớp, bạn thậm chí có thể hạn chế quyền truy cập vào các thuộc tính và phương thức của nó bằng cách sử dụng các từ khóa khả năng hiển thị để kiểm soát tốt hơn. Có ba từ khóa khả năng hiển thị (từ hiển thị nhiều nhất đến ít hiển thị nhất): public, protected, private, mà quyết định như thế nào và từ đâu tài sản và phương pháp có thể được truy cập và sửa đổi.

  • public- Một thuộc tính hoặc phương thức công cộng có thể được truy cập ở bất kỳ đâu, từ bên trong lớp và bên ngoài. Đây là khả năng hiển thị mặc định cho tất cả các thành viên lớp trong PHP.
  • protected - Một thuộc tính hoặc phương thức được bảo vệ chỉ có thể được truy cập từ bên trong chính lớp đó hoặc trong các lớp con hoặc lớp kế thừa tức là các lớp mở rộng lớp đó.
  • private - Một thuộc tính hoặc phương thức private chỉ có thể truy cập được từ bên trong lớp định nghĩa nó. Ngay cả các lớp con hoặc lớp kế thừa cũng không thể truy cập các thuộc tính hoặc phương thức private.

Ví dụ sau sẽ cho bạn thấy cách hiển thị này hoạt động trong thực tế:

Ví dụ

<?php
// Class definition
class Automobile
{
    // Declare  properties
    public $fuel;
    protected $engine;
    private $transmission;
}
class Car extends Automobile
{
    // Constructor
    public function __construct(){
        echo 'The class "' . __CLASS__ . '" was initiated!<br>';
    }
}
 
// Create an object from Automobile class
$automobile = new Automobile;
 
// Attempt to set $automobile object properties
$automobile->fuel = 'Petrol'; // ok
$automobile->engine = '1500 cc'; // fatal error
$automobile->transmission = 'Manual'; // fatal error
 
// Create an object from Car class
$car = new Car;
 
// Attempt to set $car object properties
$car->fuel = 'Diesel'; // ok
$car->engine = '2200 cc'; // fatal error
$car->transmission = 'Automatic'; // undefined
?>

Thuộc tính và phương thức tĩnh

Ngoài khả năng hiển thị, các thuộc tính và phương thức cũng có thể được khai báo static, điều này làm cho chúng có thể truy cập được mà không cần khởi tạo lớp. Các thuộc tính và phương thức tĩnh có thể được truy cập bằng toán tử phân giải phạm vi (::), như sau: ClassName::$propertyClassName::method().

Một thuộc tính được khai báo là static không thể được truy cập thông qua đối tượng của lớp đó mặc dù có thể sử dụng phương thức static, như được minh họa trong ví dụ sau:

Ví dụ

<?php
// Class definition
class HelloClass
{
    // Declare a static property
    public static $greeting = "Hello World!";
    
    // Declare a static method
    public static function sayHello(){
        echo self::$greeting;
    }
}
// Attempt to access static property and method directly
echo HelloClass::$greeting; // Output: Hello World!
HelloClass::sayHello(); // Output: Hello World!
 
// Attempt to access static property and method via object
$hello = new HelloClass;
echo $hello->greeting; // Strict Warning
$hello->sayHello(); // Output: Hello World!
?>

Từ khóa self trong ví dụ trên có nghĩa là "lớp hiện tại". Nó không bao giờ có dấu ($) đứng trước và luôn theo sau bởi toán tử :: (ví dụ self::$name).

Từ khóa self khác với từ khóa this có nghĩa là "đối tượng hiện tại" hay "dụ hiện tại của một lớp". Từ khóa this được luôn luôn đi trước bởi một dấu đô la ($) và tiếp theo là mũi tên điều hướng -> (ví dụ $this->name).

 

Ghi chú: Vì các phương thức tĩnh có thể được gọi mà không có thể hiện của một lớp (tức là đối tượng), biến giả $this không có sẵn bên trong phương thức được khai báo là tĩnh.

Chúng tôi hy vọng đến giờ bạn đã hiểu các khái niệm cơ bản về lập trình hướng đối tượng. Bạn sẽ tìm thấy nhiều ví dụ hơn về OOP trong phần cơ sở dữ liệu PHP và MySQL.

Bài viết này đã giúp ích cho bạn?

Advertisements