Hướng dẫn dùng mapclass trong PHP
Khi mới làm quen với lập trình chúng ta thường bắt đầu với các ngôn ngữ như C, Pascal là những ngôn ngữ lập trình cấu trúc với việc thực hiện mã lệnh tuần tự kèm theo các câu lệnh điều kiện và các vòng lặp. Kiểu lập trình này giúp chúng ta có thể nhanh chóng tiếp cận và thực hành, nhưng với các dự án dần dà nó có những yếu điểm trong phát triển phần mềm. Show
1. Lập trình hướng đối tượng là gì?OOP viết tắt của Object-Oriented Programming - Lập trình hướng đối tượng ra đời giải quyết các vấn đề mà lập trình truyền thống gặp phải. Lập trình hướng đối tượng không chỉ đơn giản là các cú pháp, câu lệnh mới mà còn là một cách tư duy mới khi giải quyết một vấn đề. Thực tế khi làm một việc gì đó, chúng ta sẽ quan tâm đến hai điều: vật bị tác động và hành động. Với lập trình cũng vậy, nếu chúng ta tập trung vào hành động thì đó là lập trình hướng thủ tục còn nếu tập trung vào các vật thể thì đó là lập trình hướng đối tượng. Với cả hai cách giải quyết vấn đề, đều cho chúng ta một kết quả như nhau, chỉ có một điều khác nhau là cách chúng ta tập trung vào cái gì? Trong lập trình hướng đối tượng OOP, có hai thuật ngữ rất quan trọng là lớp (class) và đối tượng (object). Class là định nghĩa chung cho một vật, để dễ tưởng tượng bạn có thể nghĩ đến class là một bản thiết kế trong khi đó đối tượng là một thực hiện cụ thể của bản thiết kế. Ví dụ, object là một ngôi nhà cụ thể thì class là bản thiết kế ngôi nhà đó. Lập trình hướng đối tượng là cách bạn thiết kế các class và sau đó thực hiện chúng thành các đối tượng trong chương trình khi cần. Lập trình hướng đối tượng có 4 tính chất chính:
Với OOP, ứng dụng ra thành các phần nhỏ, ví dụ website có thể làm nhiều thứ như tương tác với database, quản lý form, gửi email, tạo mã HTML… mỗi thứ đó có thể là một module hay một class. Bằng cách tách biệt các thành phần không liên quan, các class sẽ độc lập, dễ bảo trì và cập nhật, debug lỗi cũng vì thế đơn giản hơn. Một vấn đề cũng hay gặp với những người mới làm quen với OOP là khi chia nhỏ các thành phần, các lớp được định nghĩa quá rộng, ví dụ thay vì định nghĩa một class để tương tác với một cơ sở dữ liệu MySQL, bạn tạo ra một class tương tác với cơ sở dữ liệu không xác định, class này hoạt động như một lớp database chung chung, nhưng tính năng của nó lại hướng về một thứ cố định. Trong OOP, các class là các thành phần riêng biệt được đóng kín và ẩn đi cách thức hoạt động bên trong nó, một thuộc tính của lớp có thể làm việc gì đó nếu bạn cần làm mà bạn không biết cách nó hoàn thành như thế nào. Bên cạnh những ưu điểm, OOP cũng có những vấn đề của nó, OOP không phải là cách tốt hơn trong lập trình, nó đơn giản chỉ là một hướng đi khác trong giải quyết vấn đề. Trong một số trường hợp nó tốt hơn, nhưng cũng có những trường hợp OOP là tồi hơn. Có nhiều lập trình viên thấy rằng lập trình hướng đối tượng sử dụng các đối tượng có thể kém hiệu quả hơn phương pháp lập trình hướng thủ tục. Hiệu năng giữa hai phương pháp là không đáng kể trong nhiều trường hợp, nhưng có những nguy cơ tiềm ẩn từ những việc khác. Những thông tin trên đây có thể làm cho bạn hơi mung lung, khó hiểu về lập trình hướng đối tượng, nhưng bạn hãy bình tĩnh và chỉ cần một câu ngắn gọn để nhớ về OOP:
2. Các khái niệm cơ bản trong lập trình hướng đối tượng2.1 Class - Bản thiết kếTrong lập trình hướng đối tượng, chúng ta sẽ tập trung vào các vật (danh từ) ví dụ như ngôi nhà, xe ô tô... và với một vật thì bản thiết kế hay mô hình trìu tượng là cái đầu tiên nghĩ đến và class chính là cái chúng ta đang nói đến. Một class User có thể lưu trữ các thông tin như tên, id, địa chỉ email… Các chức năng của User có thể là đăng nhập, đăng xuất, thay đổi mật khẩu… Class được định nghĩa với từ khóa class và theo sau là tên của class, tên class không được đặt trùng với các từ khóa được sử dụng bởi hệ thống, thông thường tên class tuân thủ theo kiểu Pascal Case (chữ cái đầu viết hoa). Sau tên lớp, các định nghĩa về lớp được đặt trong hai dấu ngoặc nhọn:
Các lớp có thể chứa các biến (variable) và hàm (function), trong lập trình hướng đối tượng, biến trong class được gọi là thuộc tính (property) và hàm được gọi là phương thức (method). Các thuộc tính và phương thức là thành phần của class.
Phương thức được định nghĩa trong một class giống như một hàm ở ngoài lớp, chúng có thể có các tham số, giá trị mặc định và trả về giá trị khi kết thúc… Thuộc tính trong các lớp khác biệt một chút so với các biến ở ngoài lớp. Đầu tiên, các thuộc tính phải được khai báo với các từ khóa để biết phạm vi truy nhập như public, private, protected. Các giá trị này chỉ có ý nghĩa khi thực hiện thừa kế các class, chúng ta sẽ nói đến chi tiết trong các phần tiếp theo:
Trong khai báo một class, các thuộc tính được khai báo đầu tiên, sau đó đến các phương thức trong class. Một sự khác biệt nữa giữa thuộc tính (property) và biến thông thường (variable) là thuộc tính được khởi tạo với một tập giá trị thuần túy chứ không được khởi tạo với giá trị là kết quả của một biểu thức.
Một số chú ý là thuộc tính không nhất thiết phải có giá trị khởi tạo, chú ý nữa các đoạn code khác ngoài việc khai báo thuộc tính phải được thực hiện ở trong phương thức, không thể thực hiện các câu lệnh bên ngoài một phương thức.
Trên đây chúng ta đã có được các kiến thức về class, một khái niệm cơ sở quan trọng của OOP. Các đoạn code trong lý thuyết chỉ để minh họa, chúng ta cần có các ví dụ cụ thể hơn giúp hiểu rõ lý thuyết đưa ra. Một cách học lập trình tốt là học đến đâu thực hành đến đấy. Trong loạt bài về "Lập trình hướng đối tượng trong PHP", chúng ta cũng sẽ làm như vậy, mỗi phần lý thuyết sẽ được tiếp theo bởi các ví dụ. Phần tiếp theo đây, chúng ta cùng tạo ra một môi trường thực hành. 2.2 Các bước cài đặt môi trường thực hành lập trình hướng đối tượng trong PHPBước 1: Tải và cài đặt XAMPP, đây là một phần mềm tổng hợp bên trong đã có sẵn PHP, Apache (máy chủ web). Bước 2: Tạo thư mục C:/xampp/htdocs/OOP để chứa các code thực hành. Bước 3 (tùy chọn): Ở bước 2 là chúng ta đã có thể truy cập các file php từ trình duyệt với đường dẫn http://localhost/OOP, tuy nhiên nếu bạn muốn truy nhập theo kiểu domain ảo dạng http://oop.dev chúng ta thực hiện mở file hosts nằm trong C:\Windows\System32\drivers\etc và thêm vào:
Sau đó, mở file httpd-vhosts.conf trong thư mục C:\xampp\apache\conf\extra để map domain ảo này với thư mục mã nguồn:
Khởi động lại Apache trong XAMPP Control Panel là bạn đã có thể sử dụng được tên miền ảo http://oop.dev cho các ví dụ thực hành. Ok, chúng ta đã cài đặt xong môi trường và bắt tay tạo ra một ví dụ về class. Ví dụ HelloWorld để khởi đầu, nhiệm vụ chỉ đơn giản là in ra màn một câu chào bằng các thứ tiếng khác nhau. Trong lập trình hướng đối tượng, mỗi class có thể được lưu trên một file khác nhau hoặc đưa toàn bộ các code vào một file giống lập trình thủ tục cũng được, chúng ta sẽ tạo ra một file HelloWorld.php nằm trong thư mục C:/xampp/htdocs/OOP với nội dung sau:
Như vậy, bạn đã định nghĩa được một class HelloWorld không có thuộc tính mà chỉ có duy nhất một phương thức sayHello(). Phương thức này sử dụng để in ra các câu chào bằng các thứ tiếng khác nhau, nó có một tham số đầu vào là $language và được mặc định là ngôn ngữ tiếng Anh. Bạn có thể thực thi file HelloWorld.php bằng cách mở trình duyệt và vào đường dẫn http://oop.dev/HelloWorld.php, bạn nào không tạo domain ảo thì vào bằng đường dẫn http://localhost/OOP/HelloWorld.php. Ặc, trắng tinh lỗi gì sao. Không phải đâu, do chúng ta mới tạo ra một Class mà chưa sử dụng Class này lên trống trơn là đúng thôi. Trong phần tiếp theo chúng ta sẽ tìm hiểu cách sử dụng Class. 2.3 Đối tượng - thực thi cụ thể của bản vẽTrong phần 2.1 chúng ta đã tạo ra một bản vẽ là một class, tiếp theo chúng ta sẽ sử dụng bản vẽ để tạo ra các đối tượng là những thực hiện cụ thể của bản vẽ. Trở lại với ví dụ về class User, một thực thể của class này là một người dùng xác định, ví dụ thông tin người dùng này như sau username là kiendang, ID người dùng là 1234 và địa chỉ email là . Một class có thể có nhiều các thực thể khác nhau, cũng như một bản vẽ nhà có thể thực hiện xây dựng ra nhiều các ngôi nhà cụ thể khác nhau. Các đối tượng (ngôi nhà) này là giống nhau về khung (ba tầng, một tum) nhưng khác nhau về nét đặc trưng (khác về màu sơn, chất liệu cửa khác nhau...). Trong PHP việc tạo một đối tượng từ class là rất đơn giản, chúng ta sử dụng từ khóa new:
Bây giờ biến $object đã tồn tại và có dạng là ClassName (thay vì dạng string, integer, array…), chúng ta nói $object là một thực thể của ClassName. Chúng ta cũng có thể thực thi các phương thức trong class bằng cú pháp:
Trong đó, -> được gọi là toán tử đối tượng, được sử dụng để truy xuất các thuộc tính hoặc phương thức của đối tượng. Nếu một phương thức có tham số, bạn có thể truyền các tham số cho chúng, các tham số được phân cách bởi dấu phẩy.
Truy xuất giá trị thuộc tính của đối tượng cũng thông qua toán tử đối tượng ->
Chú ý, đằng sau toán tử đối tượng là tên thuộc tính, không sử dụng dấu $ khi truy nhập vào thuộc tính của lớp, đây là lỗi thường gặp với người mới làm quen lập trình hướng đối tượng.
Khi kết thúc việc sử dụng đối tượng, bạn có thể xóa chúng đi như với các biến thông thường. Trong các ứng dụng PHP, nếu bạn không xóa các đối tượng khi sử dụng thì ứng dụng cũng tự động xóa sau khi thực hiện xong các đoạn mã.
Phần lý thuyết chỉ có như vậy, chúng ta cùng thực hành tiếp với class HelloWorld đã tạo ra ở trên. Bạn hãy cùng tôi thực hành sử dụng class này tạo ra các thực thể (instance). Mở thư mục OOP tạo file mới là hello.php với nội dung:
Để sử dụng được class HelloWorld được khai báo trong file OOP/HelloWorld.php chúng ta cần câu lệnh require trước khi tạo ra một đối tượng từ class này. Tiếp theo, với đối tượng $obj được tạo ra từ class HelloWorld, chúng ta gọi phương thức sayHello() để in câu chào ra màn hình, nếu không truyền tham số nó sẽ lấy giá trị mặc định là tiếng Anh để in ra lời chào, các lời chào tiếp theo được in ra bằng tiếng Việt, tiếng Trung Quốc và tiếng Pháp. Kết thúc, khi không sử dụng đến đối tượng này nữa chúng ta thực xóa chúng đi. Kết quả là bạn truy nhập vào http://oop.dev/hello.php sẽ được như sau: 2.4 Biến $thisClass HelloWorld đã làm được một số việc và là một ví dụ dễ hiểu để khởi đầu, class này có duy nhất một phương thức và không có bất kỳ thuộc tính nào. Như đã trình bày trong phần trước, khái niệm về thuộc tính:
Trên đây là các nguyên tắc khi định nghĩa một thuộc tính, khi sử dụng thuộc tính cần thêm một chút thông tin. Khi truy nhập vào thuộc tính của class chúng ta cần thông qua toán tử đối tượng ->
Có một vấn đề là chúng ta muốn truy cập thuộc tính trong chính class đó. Bạn không thể sử dụng:
Phương thức do() không thể truy xuất thuộc tính $var, giải pháp là sử dụng một biến đặc biệt là $this. Biến $this trong một class tham chiếu đến thực thể hiện tại của class. Trong một phương thức, bạn có thể tham chiếu đến thực thể của class và các thuộc tính bằng cách sử dụng cú pháp $this->attributeName. Trong phần thực hành với biến $this, chúng ta đến với một ví dụ tạo ra một class hình chữ nhật với các thuộc tính chiều rộng, chiều cao và các phương thức như tính chu vi, diện tích... Tạo file Rectangle.php trong thư mục OOP.
Trong class Rectangle chúng ta có sử dụng đến biến $this và nó trỏ đến đối tượng hiện tại của class Rectangle, tuy nhiên khi chúng ta chưa tạo ra đối tượng thì biến $this cũng chỉ để định nghĩa. Cũng giống như các thực hành ở trên. Chúng ta đã tạo ra class và tiếp theo sẽ sử dụng class này, tạo file rectangle_calculate.php với nội dung:
Khi tạo ra đối tượng từ class Rectangle, chúng ta có thể thiết lập giá trị chiều rộng và chiều cao cho đối tượng, khi đó biến $this tham chiếu đến đối tượng này. Kiểm tra xem ví dụ hoạt động như thế nào trong đường dẫn http://oop.dev/rectangle\_calculate.php 3. Các phương thức được xây dựng sẵn trong ClassTrong class có sẵn một số phương thức (còn gọi là magic method) giúp cho việc sử dụng class thuận tiện hơn, có một số phương thức liên quan đến việc khởi tạo và hủy bỏ một đối tượng, cũng có một số phương thức giúp làm việc với các đối tượng như tạo một bản sao đối tượng, nhân bản đối tượng... Các phương thức này có một số khác biệt với phương thức chuẩn:
3.1 Phương thức khởi tạo __construct()Phương thức khởi tạo (contructor) là một phương thức đặc biệt, tên phương thức luôn là __construct(). Phương thức này được gọi mỗi khi một đối tượng được tạo ra từ class. Phương thức này không trả về giá trị, do đó không sử dụng câu lệnh return trong __construct(). Khai báo phương thức khởi tạo như sau:
Phương thức khởi tạo thực hiện các công việc cần thiết để khởi tạo đối tượng như kết nối với cơ sở dữ liệu, thiết lập cookie hoặc khởi tạo các giá trị ban đầu. Phương thức khởi tạo cũng có thể có tham số và giá trị các tham số này được truyền vào khi tạo đối tượng.
Trong ví dụ Rectangle.php ở phần 1.3, chúng ta sẽ tạo ra một hàm khởi tạo và trong đó thiết lập luôn giá trị chiều rộng, chiều cao của đối tượng hình chữ nhật.
Như vậy khi tạo ra đối tượng chúng ta có thể khởi tạo các kích thước của đối tượng luôn, thực hiện trong rectangle_calculate.php:
Chạy lại đường dẫn http://oop.dev/rectangle\_calculate.php chúng ta thấy hàm khởi tạo __contruct đã được sử dụng để thiết lập kích thước hình chữ nhật khi tạo đối tượng. 3.2 Phương thức hủy __destruct()Phương thức hủy __destruct() ngược với phương thức khởi tạo __contruct(), nó được gọi đến khi đối tượng bị hủy bỏ.
Hoặc nó được gọi khi đoạn mã được thực thi xong (tại thời điểm này PHP giải phóng các biến khỏi bộ nhớ). Khai báo phương thức hủy như sau:
Hàm hủy __destruct cũng là các công việc kết thúc vòng đời của một đối tượng, ví dụ tiếp theo này chúng ta sẽ cùng tìm hiểu vòng đời của một đối tượng. Tạo ra file object_lifecycle.php với nội dung như sau:
Bạn thấy đấy, trong các sự kiện xảy ra trong vòng đời của một đối tượng, chúng ta đều có thể thực hiện một việc gì đấy. Chú ý, ở đây chúng ta chủ động thực hiện xóa đối tượng khi sử dụng xong bằng lệnh unset($demo), trong trường hợp không xóa đối tượng, ứng dụng sẽ tự động xóa đối tượng khi kết thúc thực thi đoạn mã. Nếu bạn bỏ dòng unset($demo) thì thứ tự của sự kiện thứ 5 và thứ 6 ở trên sẽ đảo cho nhau. 3.3 Phương thức __get(), __set() và __isset() làm việc với thuộc tính trong classVới toán tử đối tượng -> chúng ta có thể truy nhập một thuộc tính của đối tượng, tuy nhiên nếu thuộc tính chưa được khai báo trong class thì làm thế nào? Phương thức __get và __set() giúp chúng ta khai báo các giá trị thích hợp cho các thuộc tính không được khai báo của một class. Chúng ta cùng xem ví dụ sau:
Trong ví dụ này, class Test sử dụng cách khai báo thuộc tính động theo kiểu mảng thuộc tính, thuộc tính speed_limit không được khai báo khi định nghĩa lớp Test, tuy nhiên khi truy xuất thuộc tính này, phương thức __get() sẽ được gọi đến. Nó kiểm tra nếu thuộc tính gọi đến nằm trong mảng thuộc tính thì trả về giá trị trong mảng, nếu không có thuộc tính này thì trả về dòng thông báo. Phương thức __isset() được dùng xử lý các công việc khi thực hiện lệnh isset() với thuộc tính một đối tượng. 3.4 Phương thức __call(), __callStatic() xử lý khi gọi phương thức của đối tượngCác phương thức __get(), __set() ở trên để xử lý khi truy cập các thuộc tính của đối tượng, còn với phương thức của đối tượng thì sao, chúng ta có phương thức __call() và __callStatic(). Các phương thức này được gọi đến khi chúng ta cố tình gọi một phương thức không tồn tại trong một đối tượng. Phương thức __call() được gọi đến khi gọi một phương thức thông thường không tồn tại, __callStatic() được gọi đến khi gọi một phương thức static không tồn tại. Ví dụ:
Trong đoạn mã trên, class Test không khai báo phương thức nào, tuy nhiên khi tạo ra một đối tượng từ class này chúng ta vẫn có thể gọi một phương thức bất kỳ không tồn tại trong đối tượng này. Khi thực hiện $x->non_existing_method(1, 2, 3); phương thức __call() của class Test được thực hiện, còn khi gọi Test::non_existing_method() thì phương thức __callStatic() sẽ được thực hiện. ### 3.5 Phương thức __toString() xử lý việc in đối tượng ra màn hình Như tên gọi của nó, phương thức này được gọi đến khi bạn sử dụng các lệnh in để in đối tượng ra màn hình. Chúng ta cùng xem ví dụ sau:
3.6 Phương thức __clone()Trong PHP, đối tượng là một biến tham chiếu đến một vùng bộ nhớ, do vậy khi chúng ta tạo ra một đối tượng khác bằng cách gán với đối tượng cũ thì chúng ta chỉ có duy nhất một thực thể trong bộ nhớ. Bạn hãy xem ví dụ sau:
Không như chúng ta nghĩ phải không? Để thực hiện tạo ra một đối tượng khác thật sự, chúng ta phải sử dụng câu lệnh clone().
Phương thức __clone() được gọi đến khi bạn sử dụng câu lệnh clone(), phương thức này có thể dùng xử lý các công việc bạn muốn thực hiện khi clone, ví dụ có những thuộc tính bạn muốn thiết lập lại khi clone chẳng hạn. 4. Mô hình hóa thiết kế class với UML4.1 Các thành phần class trong sơ đồ UMLUML viết tắt của Unified Modeling Language là một cách để mô hình hóa trong thiết kết hướng đối tượng. Một class có 3 thành phần là tên class, các thuộc tính và các phương thức. UML thể hiện một class bởi một hình chữ nhật gồm 3 phần. Với các thuộc tính, dạng dữ liệu của thuộc tính được liệt kê sau tên thuộc tính
Nếu thuộc tính có giá trị mặc định, bạn có thể đưa vào UML.
Để định nghĩa một phương thức trong sơ đồ class, chúng ta bắt đầu với tên phương thức, tiếp theo là các tham số và dạng dữ liệu tham số và cuối cùng là dạng giá trị phương thức sẽ trả về.
Ví dụ sử dụng UML để mô tả class Rectangle trong phần 1.3 4.2 Lợi ích sử dụng UML để thiết kế classĐầu tiên, nếu bạn phác thảo các thiết kế trước khi viết code, code của bạn sẽ đúng ngay từ khi bắt đầu. Hay nói một cách khác, nếu bạn nỗ lực trong quá trình thiết kế trực quan, thiết kế sẽ có đầy đủ các yêu cầu do đó giảm được số lần phải sửa đổi các class sau này. Thứ hai, nguyên lý của OOP là đóng gói: tách biệt và ẩn đi cách một việc nào đó được hoàn thành. UML với việc liệt kê danh sách các thuộc tính, phương thức và tham số có thể được sử dụng như bản hướng dẫn người dùng sử dụng các class. 5. Lời kếtTrong phần đầu tiên giới thiệu về lập trình hướng đối tượng trong PHP chúng ta đã được làm quen với những khái niệm cơ bản nhất cũng như khai phá tư duy giải quyết vấn đề theo cách hướng đối tượng. Các phần cơ bản này là tiền đề cho những lý thuyết tiếp theo của OOP như kế thừa trong class sẽ được trình bày trong phần 2. Dự định loạt bài viết sẽ thực hiện với 3 phần đủ để cung cấp cho bạn đọc các kiến thức về Lập trình hướng đối tượng. Đón xem phần tiếp theo bạn nhé. Loạt bài viết này gồm 4 phần, bạn đang ở phần 1:
CÁC BÀI VIẾT KHÁC |