Thiết kế Component cho Joomla theo mô hình MVC


I. Tổng quan về component trong Joomla
Component là một thành phần mở rộng lớn nhất và phức tạp nhất của Joomla CMS. Các component có thể xem như là các ứng dụng con và nếu joomla là một hệ điều hành thì các component là các ứng dụng desktop. Ví dụ component nội dung (com_content) là một ứng dụng mini xử lý tất cả các vấn đề về nội dung được trả lại như thế nào mỗi khi có yêu cầu duyệt nội dung được đưa ra. Một component có hai thành phần chính: phần quản trị và phần trên site. Phần trên site là phần được sử dụng để tải về các trang khi được triệu gọi trong quá trình hoạt động của một website thông thường. Phần quản trị cung cấp giao diện để cấu hình, quản lý các khía cạnh khác nhau của component và được truy cập thông qua ứng dụng quản trị của Joomla

Bắt đầu từ phiên bản Joomla 1.5.x hoặc các phiên bản sau này, Joomla đã đưa vào một framework mới, mang lại những thuận tiên rất lớn cho những người phát triển. Các đoạn code giờ đây rất dễ dàng để kiểm tra và khá rõ ràng. Framework này đưa ra một mẫu thiết kế mới, thiết kế MVC (Model-View-Controller) trong Joomla.
Model-View-Controller (gọi tắt là MVC) là một mẫu thiết kế phần mềm được dùng để tổ chức các đoạn mã theo cách mà việc xử lý dữ liệu và biểu diễn dữ liệu tách rời nhau. Điều này tạo ra tiền đề cho hướng tiếp cận sau này khi mà việc xử lý dữ liệu được nhóm vào trong một section, khi đó giao diện hay quá trình tương tác với người dùng bao quanh dữ liệu có thể được định dạng và tùy biến lại mà không phải lập trình lại việc xử lý dữ liệu nữa.


1 – Model: là thành phần của component đóng gói dữ liệu cho ứng dụng. Nó thường cung cấp các thủ tục để quản lý, thao tác dữ liệu theo một cách nào đó, trong đó có thêm các thủ tục để lấy dữ liệu từ model. Có thể là bổ sung (insert), loại bỏ (delete) hay cập nhật (update) thông tin về một trường nào đó trong cơ sở dữ liệu (CSDL). Theo cách này, nếu một ứng dụng chuyển đổi sang việc sử dụng một file bình thường để lưu trữ thông tin của nó thay vì sử dụng CSDL thì chỉ có thành phần Model là thay đổi còn các thành phần View và Controller là không đổi.
2 – View: là một thành phần của component được sử dụng để trả lại dữ liệu từ model theo cách phù hợp với tương tác. Đối với ứng dụng web, view thông thường là các trang HTML để trả lại dữ liệu. View lấy dữ liệu từ Model (dữ liệu này được chuyển qua View tới Controller). Sau cùng là đưa dữ liệu vào trong template (dữ liệu này sẽ hiển thị với người dùng). View không làm thay đổi dữ liệu, nó chỉ hiển thị dữ liệu lấy từ Model mà thôi)
3 – Controller: Controller chịu trách nhiệm phản hồi các hành động của người dùng. Trong các ứng dụng web, một hành động của người dùng thông thường là một yêu cầu tải trang. Controller sẽ xác định yêu cầu gì được người dùng đưa ra và phản hồi thích hợp bằng việc yêu cầu Model tính toán dữ liệu phù hợp và chuyển từ Model vào View. Controller không thể hiện dữ liệu từ Model, nó kích hoạt các phương thức trong Model để hiệu chỉnh dữ liệu và sau đó chuyển từ Model sang View để hiển thị dữ liệu
Trong Joomla, mô hình MVC được hỗ trợ thông qua 3 lớp JModel, JView và Jcontroller.

II. Khởi tạo một compenent
Một component đầy đủ có cấu trúc như sau:


Thư mục admin chứa các thành phần tạo nên giao diện quản trị cho component ở Joomla Back-End, thư mục site chứa các thành phần tạo nên giao diện site cho component ở Joomla Front-End và file XML chứa thông tin mô tả về cài đặt. Ví dụ ở đây là xây dựng một component hiển thị lời chào lấy từ CSDL theo mô hình MVC của Joomla.
Đối với một component cơ bản (không có phần quản trị) chỉ cần 5 file được đặt trong các thư mục models, views trong thư mục chính sites:
•   Hello.php: đây là file đầu vào cho component.
•   Controller.php: file này chứa controller cơ bản cho component
•   View/hello/view.html.php: file này nhận dữ liệu cần thiết và đặt nó vào template
•   View/hello/tmpl/default.php: file này là template cho đầu ra, hiển thị lên site
•   Hello.xml: đây là một file XML nói cho joomla biết cách cài đặt component như thế nào
Tuy nhiên đó chỉ là mô hình View-Controller đơn giản, không tuân theo mẫu MVC một cách chính xác, bởi View chỉ được hiển thị dữ liệu chứ không chứa nó. Khi đó ta sẽ chuyển dữ liệu ra khỏi View và đưa nó vào Model. Component lúc này sẽ cần thêm các file:
•   Models/hello.php
Nếu có thêm phần quản trị, sẽ có thêm thư mục admin cũng chứa các thư mục như controllers, models, views có các file tương tự như phần site và một số file/thư mục đặc biệt như: file SQL (cài đặt và gỡ bỏ bảng trong CSDL), thư mục tables, v.v.. Trong bài này, chúng ta sẽ lấy ví dụ xây dựng 1 component là Hello hiển thị một lời chào lấy từ CSDL

A) SITE
B1: Tạo điểm vào cho component (hello.php)
Joomla luôn luôn được truy cập thông qua một điểm vào duy nhất là file index.php cho các ứng dụng trên site (administrator/index.php  cho ứng dụng quản trị). Sau đó ứng dụng sẽ tải các component cần thiết dựa trên giá trị chọn lựa trong URL hoặc trong dữ liệu POST. Đối với component này, URL sẽ có dạng: index.php?option=com_hello&view=hello  sẽ tải file chính (components/com_hello/hello.php)
Code:

  1. <?php
  2. // no direct access
  3. defined( ‘_JEXEC’ ) or die( ‘Restricted access’ );
  4. // Require the base controller
  5. require_once( JPATH_COMPONENT.DS.‘controller.php’ );
  6. // Require specific controller if requested
  7. if($controller = JRequest::getWord(‘controller’)) {
  8. $path = JPATH_COMPONENT.DS.‘controllers’.DS.$controller.‘.php’;
  9. if (file_exists($path)) {
  10. require_once $path;
  11. } else {
  12. $controller = ;
  13. }
  14. }
  15. // Create the controller
  16. $classname = ‘HelloController’.$controller;
  17. $controller = new $classname( );
  18. // Perform the Request task
  19. $controller->execute( JRequest::getVar( ‘task’ ) );
  20. // Redirect if set by the controller
  21. $controller->redirect();
  22. ?>
%3C%3Fphp%0A%2F%2F%20no%20direct%20access%0Adefined%28%20%27_JEXEC%27%20%29%20or%20die%28%20%27Restricted%20access%27%20%29%3B%0A%2F%2F%20Require%20the%20base%20controller%0Arequire_once%28%20JPATH_COMPONENT.DS.%27controller.php%27%20%29%3B%0A%2F%2F%20Require%20specific%20controller%20if%20requested%0Aif%28%24controller%20%3D%20JRequest%3A%3AgetWord%28%27controller%27%29%29%20%7B%0A%20%20%20%20%24path%20%3D%20JPATH_COMPONENT.DS.%27controllers%27.DS.%24controller.%27.php%27%3B%0A%20%20%20%20if%20%28file_exists%28%24path%29%29%20%7B%0A%20%20%20%20%20%20%20%20require_once%20%24path%3B%0A%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20%20%20%24controller%20%3D%20%27%27%3B%0A%20%20%20%20%7D%0A%7D%0A%2F%2F%20Create%20the%20controller%0A%24classname%20%20%20%20%3D%20%27HelloController%27.%24controller%3B%0A%24controller%20%20%20%3D%20new%20%24classname%28%20%29%3B%0A%2F%2F%20Perform%20the%20Request%20task%0A%24controller-%3Eexecute%28%20JRequest%3A%3AgetVar%28%20%27task%27%20%29%20%29%3B%0A%2F%2F%20Redirect%20if%20set%20by%20the%20controller%0A%24controller-%3Eredirect%28%29%3B%0A%3F%3E

Câu lệnh đầu tiên là câu lệnh kiểm tra bảo mật. JPATH_COMPONENT là đường dẫn tuyệt đối tới component hiện tại (ví dụ ở đây là: components/com_hello) và tương tự với admin component là JPATH_COMPONENT_ADMINISTRATOR (administrator/components).
DS là dấu phân cách thư mục trong hệ thống của bạn: có thể là “\” hoặc “/”. Điều này được thiết lập tự động bởi framework, vì vậy lập trình viên không phải quan tâm đến việc phát triển các phiên bản khác nhau cho các hệ điều hành khác nhau. DS sẽ luôn được sử dụng khi tham chiếu đến các file trên máy chủ cục bộ.
Sau khi tải controller cơ bản, chương trình sẽ kiểm tra một controller cụ thể cần đến. (Với component Hello đơn giản, controller cơ bản chỉ là một controller nhưng khi mở rộng sau này sẽ có rất nhiều controller).
Lớp Jrequest:getVar() sẽ tìm đến một biến trong URL hoặc POST dữ liệu, bởi vậy nếu URL là: index.php?option=com_hello&controller=controller_name thì tên của Controller ở đây sẽ được lấy về bằng câu lệnh: Jrequest::getVar(‘controller’);
Bây giờ, component đã có controller cơ sở (ở đây là HelloController, trong file com_hello/controller.php) và nếu cần thiết, ta sẽ bổ sung thêm các controller dạng như HelloControllerController1, HelloControllerController2, v.v.. (tương ứng với com_hello/controller1.php, com_hello/controller2.php, v.v..).
Sau khi Controller được tạo ra, Controller sẽ chạy nhiệm vụ như được chỉ định trong URL: index.php?option=com_hello&task=sometask. Nếu không có nhiệm vụ nào được chỉ ra trong URL thì nhiệm vụ mặc định “display” sẽ được giả định. Khi nhiệm vụ “display” được sử dụng thì biến “view”  sẽ quyết định cái gì được hiển thị. Ngoài ra còn các nhiệm vụ khác như “save”, “edit”, “new”, …
Controller có thể quyết định thực hiện tải một trang (redirect), thông thường là sau khi một nhiệm vụ như “save” được hoàn thành.
KL: Điểm vào chính (hello.php) về bản chất đã thông qua việc điều khiển controller thực hiện các nhiệm vụ được đặt ra trong request.

B2: Tạo Controller
Controller trong ví dụ này chỉ có một nhiệm vụ là thể hiện lời chào nên sẽ khá đơn giản, không cần phải tính toán trên dữ liệu. Tất cả những gì cần thiết phải làm là tải View thích hợp. Để hiện thị lời chào, chúng ta chỉ có một phương thức trong controller là display(). Hầu hết các hàm cần thiết được xây dựng trong lớp JController, nên chỉ cần gọi JController::display(); là xong.

  1. <?php
  2. class HelloController extends JController
  3. {
  4. /**
  5. * Method to display the view
  6. *
  7. * @access    public
  8. */
  9. function display()
  10. {
  11. parent::display();
  12. }
  13. }
  14. ?>
%3C%3Fphp%0Aclass%20HelloController%20extends%20JController%0A%7B%0A%20%20%20%20%2F%2A%2A%0A%20%20%20%20%20%2A%20Method%20to%20display%20the%20view%0A%20%20%20%20%20%2A%0A%20%20%20%20%20%2A%20%40access%20%20%20%20public%0A%20%20%20%20%20%2A%2F%0A%20%20%20%20function%20display%28%29%0A%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20parent%3A%3Adisplay%28%29%3B%0A%20%20%20%20%7D%0A%7D%0A%3F%3E%20

Khi khởi tạo một lớp JController, sẽ luôn có một nhiệm vụ là display() khi không có một nhiệm vụ cụ thể nào được chỉ ra, nó được thiết lập như một nhiệm vụ mặc định. Mặc dù trong trường hợp này, phương thức display() thật sự không cần thiết, tuy nhiên nó tạo ra cơ sở khá tốt cho việc phải chỉ ra điều gì cần phải làm trong controller. Phương thức JController::display() sẽ xác định view và layout từ request, tải view đó về là thiết lập layout. Khi tạo một menu item cho component, menu manager sẽ cho phép admin lựa chọn view mà họ thích để thể hiện trên layout cụ thể. Một View thông thường được xem như một cách hiển thị của một tập dữ liệu nào đó còn layout là một cách tổ chức các View đó.
Trong component ở đây (com_hello) có một view đơn được gọi là hello và một layout đơn (default)

B3: Tạo View
Nhiệm vụ của View rất đơn giản: nó nhận dữ liệu được thể hiện và đặt nó lên template. Dữ liệu được đặt lên template sử dụng phương thức JView::assignRef

Nguồn: http://hpcc.hut.vn/forum/index.php?topic=211.new

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s