3.2.1. Giới thiệu Drupal [11]
Drupal là hệ thống quản trị nội dung miễn phí và mã nguồn mở, rất thích hợp để phát triển phần mềm hướng module.
Cũng giống như các hệ quản trị nội dung hiện đại khác, Drupal cho phép người quản trị hệ thống, tạo và tổ chức dữ liệu, tùy chỉnh cách trình bày, tự động hóa các tác vụ điều hành và quản lý hệ thống. Drupal có cấu trúc lập trình rất tinh vi, dựa trên đó, hầu hết các tác vụ phức tạp có thể được giải quyết với rất ít đoạn mã được viết, thậm chí không cần. Đôi khi, Drupal cũng được gọi là "khung sườn phát triển ứng dụng web", vì kiến trúc thông minh và uyển chuyển của nó.
Nếu một hệ thống là quá đơn giản, nó chỉ có thể được sử dụng cho một mục đích duy nhất - nhưng nếu nó là quá linh hoạt, nó có thể là quá khó khăn cho người dùng mới để tìm hiểu. Drupal phấn đấu để hòa giải những mục tiêu mâu thuẫn nhau, bằng cách cung cấp cho người dùng các công cụ mà họ cần để quản lý nội dung, trong khi vẫn cung cấp một số thành phần được xây dựng trước. Vì vậy, Drupal được coi như là một hệ thống quản lý nội dung (CMS) và một khuôn khổ quản lý nội dung (CMF).
Drupal có thể được sử dụng để xây dựng hầu hết các loại website, từ website cá nhân cho đến những ứng dụng bán hàng phức tạp. Drupal giúp người dùng có thể phát triển tính năng độc lập, đóng gói các module. Hiện nay, tại drupal.org, cộng đồng đã đóng góp rất nhiều module với tập tính năng đồ sộ. Nếu sử dụng thành thạo và khéo léo các module được cộng đồng đóng góp, các ứng dụng web sẽ phát triển nhanh hơn trên nền tảng Drupal. Ngoài ra, với kiến trúc module, người dùng có thể liên kết các
module, cài đặt các thiết lập mặc định để xây dựng nên các ứng dụng mới chạy trên nền Drupal đáp ứng được các nhu cầu cụ thể.
Drupal được chạy trên rất nhiều môi trường khác nhau, bao gồm Windows, Mac OS X, Linux, FreeBSD, OpenBSD và các môi trường hỗ trợ máy phục vụ web Apache (phiên bản 1.3+) hoặc IIS (phiên bản 5+) có hỗ trợ ngôn ngữ PHP (phiên bản 4.3.3+). Drupal kết nối với cơ sở dữ liệu MySQL hoặc PostgreSQL để lưu nội dung và các thiết lập.
3.2.2. Cách xây dựng một module cho Drupal [3, 4, 12]
Drupal cho phép thêm vào hệ thống của nó bằng cách sử dụng các hook. Các hook được sử dụng trong module. Để xây dựng một module mới trong Drupal trước tiên ta phải hiểu một số khái niệm dưới đây.
3.2.2.1. Các khái niệm cơ bản.
Module
Module là một bộ gồm mã PHP, các file hỗ trợ sử dụng API và kiến trúc của Drupal để tích hợp các thành phần mới vào trong framework của Drupal.
Những file tạo nên module được gộp vào một ví trí nhất định trong cấu trúc thư mục của Drupal. Khi cần thông tin về module nào đó, Drupal sẽ tìm trong những thư mục này. Mỗi module nằm ở một thư mục riêng và có ít nhất là 2 file - một file cung cấp thông tin về module, một hay nhiều file khác chứa mã PHP thực hiện chức năng của module đó và các tài liệu hỗ trợ khác. Để một module sử dụng được thì nó phải được bật lên bởi người quản trị Drupal.
Các module lõi
Có một số module rất quan trọng. Nếu các module này bị gỡ bỏ thì sẽ vô hiệu hóa tính năng cần thiết cho hoạt động của Drupal. Những module này được gọi là module lõi, được mặc định phân phối theo mã nguồn Drupal.
Trong số các module lõi, có năm module quan trọng nhất là Block, Filter, Node, System và User. Những module này không thể gỡ bỏ hoặc vô hiệu hóa.
Dịch vụ mà các module khác nhau cung cấp có thể kết hợp với nhau để tạo nên các tính năng mạnh hơn mà không cần phải viết lại một lượng lớn mã nguồn bằng cách sử dụng cơ chế hook.
Hook
Hệ thống module của Drupal dựa trên khái niệm về hook. Hook là một hàm PHP được đặt tên foo_bar (), trong đó <foo> là tên của module và <bar> là tên của các hook. Mỗi hook có một bộ xác định các tham số và kiểu kết quả trả về.
Một module có thể định nghĩa các hook riêng và các hook này có thể được dùng bởi các module khác. Theo cách này, cơ chế hook được mở rộng để cung cấp các chức năng phức tạp.
Node (Nút)
Một node là một đối tượng biểu diễn nội dung dạng văn bản. Tuy nhiên, có thể tạo ra các module mở rộng khả năng trình bày của node để có thể hiển thị các nội dung ngoài văn bản thuần túy, như hình ảnh, video hay các file âm thanh.
Các node được lưu trữ trong cơ sở dữ liệu và sẽ được lấy ra khi cần thiết. Một node gồm có các thành phần:
- Một định danh phân biệt, duy nhất Node ID (nid).
- Ít nhất một Version ID (vid) thể hiện phiên bản của node.
- Ngày khởi tạo và sửa đổi, cùng với thông tin định danh người dùng làm việc với node đó.
- Dữ liệu meta như trạng thái xuất bản, ngôn ngữ được sử dụng và các bản dịch sang ngôn ngữ khác...
- Thêm vào đó, hầu hết các node đều có phần tiêu đề và phần nội dung. Người quản trị và nhà phát triển có thể chọn vô hiệu hóa hai phần này.
User (người dùng)
User là thực thể đại diện cho người dùng trang web trong thế giới thực. Theo mặc định, người dùng có một tập hợp các thuộc tính bao gồm tên người, mật khẩu, vai trò và địa chỉ e-mail. Tuy nhiên, họ cũng có thể có các thông tin khác được cấp bởi các module khác. Dữ liệu về người dùng được lưu trữ trong cơ sở dữ liệu và được lấy ra trong quá trình xử lý.
Thông tin về người dùng được sử dụng trong việc xác thực, định nghĩa các thiết lập cá nhân và quyền hạn, tạo các bản log.
Mỗi người dùng được gán một vai trò và các đặc quyền được cấp phát hoặc thu hồi qua vai trò đó.
Block (Khối)
Trong khi một node được sử dụng để lưu trữ và trình bày các bài viết, mẫu tin lớn thì block được dùng để biểu diễn các nội dung nhỏ hơn. Ví dụ, menu điều hướng, đoạn trích dẫn, khung bầu chọn hay ô tìm kiếm thường được thể hiện dưới dạng các block.
tượng được sử dụng chủ yếu để hiển thị các đối tượng nội dung khác.
Menu (Thực đơn)
Menu với mục đích chính là xây dựng điều hướng cho trang web. Trong Drupal có 4 menu:
- Main menu: được xây dựng bởi các quản trị viên trang web và tự động hiển thị trong tiêu đề trang của nhiều theme.
- Management: là menu quản trị, được trình bày trong thanh công cụ quản trị. - Navigation: thường chứa các liên kết được cung cấp bởi các module. - User menu: bao gồm các liên kết đến tài khoản người dùng và liên kết đăng xuất.
Có thể tạo thêm các menu tùy chỉnh và hiển thị chúng trong các block.
Trong mọi trường hợp, các mục menu sẽ chỉ được hiển thị cho người truy cập có quyền xem các trang nó liên kết đến.
Form
Để đưa nội dung lên web, cách chủ yếu là thông qua các form HTML. Sử dụng form đem lại sự tiện lợi cho người dùng nhưng lại gây khó khăn cho các lập trình viên.
API form (FAPI) cung cấp một giao diện lập trình giúp cho lập trình viên giảm bớt lượng công việc và thời gian trong việc thiết kế và xử lý form. Bằng cách sử dụng FAPI, người phát triển chỉ cần cung cấp thông tin một form, Drupal sẽ xây dựng và hiển thị form đó, thu thập kết quả và thậm chí kiểm tra tính hợp lệ của dữ liệu người dùng đưa vào.
Database (Cơ sở dữ liệu)
Drupal lưu trữ thông tin trong một cơ sở dữ liệu. Trong cơ sở dữ liệu này, mỗi loại thông tin có bảng cơ sở dữ liệu riêng của mình. Ví dụ, các thông tin cơ bản về các node của trang web được lưu trữ trong bảng node và mỗi field được lưu trữ dữ liệu trong các bảng riêng biệt (mà Drupal tạo ra tự động)...
3.2.2.2. Các bước xây dựng module.
3.2.2.2.1. Cấu trúc thư mục và các tập tin cơ bản cho module.
Một module Drupal cần phải được đặt trong một thư mục cụ thể trong cài đặt Drupal và nó cần phải có một số file cơ bản để nó có thể được xác định như là một module của hệ thống Drupal.
Tạo một thư mục có tên của module cần tạo (tạm đặt là <modulename>). Thư mục đó sẽ được lưu giữ tại sites\all\modules. Trong thư mục này nhất thiết phải có hai tập tin là <modulename>.info và <modulename>.module.
Tập tin .info
Tập tin .info cung cấp các thông tin chung về module. Một số thành phần của Drupal sẽ sử dụng các thông tin trong file này cho việc quản lý module.
Nội dung của tập tin .info có dạng như sau: name = oauthfacebook
description = OAuth with Facebook.com core = 7.x
Trường name: khai báo tên của module, tên này sẽ hiển thị trong danh sách các module có ở khu vực cho người quản trị
Trường description: chứa thông tin thêm về module, mô tả chức năng, nhiệm vụ mà module sẽ thực hiện.
Name và description là hai trường bắt buộc phải có trong file .info. Trường core: Chỉ rõ module sẽ hoạt động tốt trên phiên bản nào của Drupal Ngoài ra, các module phức tạp hơn còn có thêm một số trường thông tin trong file .info như:
- php: Cho biết phiên bản tối thiểu của PHP mà module yêu cầu.
- package: nhóm các chức năng của module, nếu không khai báo
package thì module được đưa vào nhóm “other”.
- dependencies: các module phụ thuộc, cách nhau bằng khoảng
trống. Nếu module được yêu cầu chưa được bật trên hệ thống thì module này không thể bật được.
Khi có tập tin .info ta sẽ nhìn thấy tên module trong danh sách module và ta có thể kích hoạt module này.
Tập tin .module
Tập tin .module chứa các đoạn mã PHP thực hiện chức năng của module. Đây là tập tin quan trọng nhất trong một module.
Nội dung file .module bắt đầu bằng thẻ <?php, sau đó là mã nguồn. Theo quy ước của Drupal, file này sẽ không chứa dấu đóng ?>. Việc này giúp tránh in những ký tự trống trong đầu ra của mã kịch bản trong một số trường hợp.
3.2.2.2.2. Tạo chú thích trong mã nguồn
Các module đóng góp cho drupal.org tuân theo các tiêu chuẩn viết mã và tài liệu một cách chặt chẽ. Chú thích cho biết module và các khối mã hoạt động như thế nào. Drupal sử dụng chương trình phân thích tài liệu như Doxygen để trích các chú thích làm tài liệu cho người dùng.
Mở đầu các module và hàm trong đó, lập trình viên phải chú thích rõ ràng và đầy đủ chức năng của khối mã tiếp theo đó. Ví dụ, dưới đây là chú thích đầu tiên của tập tin .module :
/** * @file
* A block module that displays recent blog and forum posts.
*/
Phần này chính là tài liệu cho API, khối chú thích bắt đầu bằng /** và kết thúc với */. Tất cả các dòng nằm trong cặp dấu này đều được coi là tài liệu và sẽ không được trình biên dịch xử lý.
Định danh @file cho biết khối này sẽ chú thích cho toàn bộ file, không phải cho riêng một hàm hay biến ở trong file. Ngoài ra, còn một số định danh khác như:
Định danh @see chỉ dẫn bộ xử lý tài liệu liên kết file này đến thông tin ở các nguồn khác. Ví dụ, nguồn dẫn là một địa chỉ URL, hàm, hằng số và biến ...
Định danh @param được dùng để mô tả về các tham số mà hàm này sử dụng, bao gồm thông tin về loại dữ liệu. Khai báo theo định dạng: @param <tên_biến> <mô tả>.
Định danh @return cho biết giá trị mà hàm sẽ trả về.
Dưới đây là ví dụ về sử dụng các định danh trong viết chú thích cho module: /**
* Implements hook_help(). *
* Displays help and module information. *
* @param path
* Which path of the site we're using to display help * @param arg
* Array that holds the current path as returned from arg() function
* @return
* String containing the bookshelf. */
3.2.2.2.3. Tạo các hook Drupal
Các hook cơ bản
Drupal đã định nghĩa sẵn rất nhiều hook để làm mọi thứ, từ khai báo block mới đến thay đổi nội dung và hành vi của block đã có. Sau đây là một số hook cơ bản trong Drupal 7:
Hook_help()
Hook đầu tiên cần xây dựng là hook_help. Hook này được khuyến khích đưa vào tất cả các module đã đóng góp. Hook_help cung cấp sự trợ giúp và bổ sung thông tin về các module cho người dùng.
Ví dụ, để thực hiện hook_help() trong module shownodes, ta tạo ra một chức năng gọi là shownodes_help() trong file shownodes.module.
hook_help() nhận hai tham số:
- Tham số $path : chứa một đoạn URI cho biết trang trợ giúp nào được gọi. Giá trị của $path có thể tuân theo định dạng admin/help#<module name>, trong đó <module name> được thay bằng tên của module tương ứng .
- Tham số $arg: chứa một số thông tin thêm.
Khi đã tạo và viết mã nguồn cho hook_help(). Ta xem lại danh sách module bằng cách nhấn vào module trên thanh công cụ trong cài đặt Drupal. Kích hoạt tính năng module và nhấp vào 'Save configuration'. Đóng và mở lại trang Modules, sẽ thấy một liên kết "Help" ở bên phải. Click vào nó để xem nội dung giúp đỡ trả về bởi hook_help.
Ví dụ:
function current_posts_help($path, $arg) { switch ($path) {
case "admin/help#current_posts":
return '<p>' . t("Displays links to nodes created
on this date") . '</p>'; break;
} }
Hook_block_info()
Tất cả các block của module đều được định nghĩa trong hook này. Mỗi block phải được đặt một định danh duy nhất (ví dụ $delta) và được sử dụng trong một số trường hợp:
- Được chuyển vào hook block khác trong module như một tham số.
- Được sử dụng để xây dựng các ID HTML mặc định của block. ID này sau đó có thể được sử dụng cho CSS hoặc lập trình JavaScript.
- Được sử dụng để định nghĩa một theme mẫu - Được sử dụng bởi các module khác.
Mỗi block được định nghĩa bởi một mảng có chứa các giá trị mô tả block như: - info: Bắt buộc phải có. Chứa giá trị là tên block. Được sử dụng để xác định block trên màn hình. Không hiển thị cho người dùng không phải quản trị viên.
- region: Tùy chọn. Có giá trị là tên khu vực chứa block.
- pages: Tùy chọn. Chứa một dãy đường dẫn nơi block sẽ xuất hiện.
- cache: Tùy chọn. Chứa một bitmask mô tả những loại bộ nhớ đệm là thích hợp cho block.
- weight: Tùy chọn. Cho biết thứ tự block trong khu vực hiển thị.
Ngoài ra, block còn có thêm một số cặp giá trị khác như: properties, status... Các cặp giá trị tùy chọn sau này có thể được thay đổi bởi người có quyền.
Ví dụ:
function node_block_info() {
// This example comes from node.module. $blocks['syndicate'] = array(
'info' => t('Syndicate'), 'cache' => DRUPAL_NO_CACHE, );
$blocks['recent'] = array(
'info' => t('Recent content'),
// DRUPAL_CACHE_PER_ROLE will be assumed. );
return $blocks; }
Hook_block_view()
Những gì người dùng xem và nhìn thấy nội dung của block trên trang web có thể được viết trong hook này.
Hook này có dạng: hook_block_view($delta = ''). Tham số
$delta là định danh của block trong module, đã được định nghĩa trong
hook_block_info()
Mảng hiển thị block chứa các thành phần sau:
- Subjects: Tiêu đề mặc định cục bộ của block. Nếu block không có tiêu đề mặc định thì sẽ được thiết lập giá trị NULL.
- Content: Chứa nội dung của block. Có thể là mảng hoặc một chuỗi chứa nội dung HTML. Nếu phần này rỗng thì block sẽ không được hiển thị.
Ví dụ:
function node_block_view($delta = '') {
// This example is adapted from node.module. $block = array(); switch ($delta) { case 'syndicate': $block['subject'] = t('Syndicate'); $block['content'] = array( '#theme' => 'feed_icon', '#url' => 'rss.xml', '#title' => t('Syndicate'),