Tóm tắt khóa luận
Drupal là một hệ quản trị nội dung được sử dụng khá phổ biến trên Internet trong
thời gian gần đây. Với thiết kế mang tính module, Drupal cho phép mở rộng các tính
năng một cách linh hoạt thông qua các module được thêm vào mà không phải thay đổi
mã nguồn của hệ thống.
Trong khoá luận này, chúng tôi tập trung tìm hiểu các kiến thức liên quan đến
việc xây dựng module cho Drupal bao gồm triển khai các hook, làm việc với cơ sở dữ
liệu, thực thi mã JavaScript, xử lý form v v. Đi vào thực nghiệm, chúng tôi đã thiết kế
và cài đặt thành công một module có chức năng tích hợp bản đồ số Google Maps vào
trang web bằng cách sử dụng API do Google cung cấp. Module này hướng tới các đối
tượng website liên quan đến địa danh, địa điểm như website du lịch, tra cứu địa điểm
trên bản đồ .
Mục lục
Lời cảm ơn .i
Tóm tắt khóa luận .ii
Mục lục . iii
Bảng từ viết tắt vi
Mở đầu 1
Chương 1: Tổng quan về Drupal . .2
1.1 Giới thiệu về Drupal .2
1.2 Kiến trúc của Drupal 2
1.2.1 Kiến trúc module .3
1.2.2 Các module lõi .4
1.2.3 Hook 5
1.2.4 Giao diện .6
1.3 Các khái niệm cơ bản trong Drupal 6
1.3.1 Node 6
1.3.2 Người dùng (User) .8
1.3.3 Khối và cách thể hiện trang .9
1.3.4 Thực đơn – Menu 10
1.3.5 Form 11
1.3.6 API cơ sở dữ liệu và lược đồ .11
1.4 Hệ thống tệp tin và thư mục của Drupal .11
1.5. Drupal xử lý yêu cầu như thế nào? 13
1.5.1 Vai trò của Web server 13
1.5.2 Quá trình khởi động .13
1.5.3 Xử lý yêu cầu .15
1.5.4 Giao diện hoá nội dung 15
1.6 Công cụ dành cho người phát triển .15
1.6.1 Module Devel 15
1.6.2 Module Coder 16
Chương 2 - Xây dựng module cho Drupal .17
2.1 File .info và .module .17
2.1.1 File .info 17
2.1.2 File .module .19
2.2 Chú thích trong mã nguồn 19
2.3 Một số hook cơ bản 20
2.4 Định nghĩa một hook mới .24
2.4.1 Cách tạo một hook .25
2.4.2 Sử dụng hook vào các module khác 26
2.5 Một số hàm quan trọng trong thư viện hàm của Drupal .26
2.6 Sử dụng Javascript và AJAX/JSON .28
2.6.1 Giới thiệu về jQuery 28
2.6.2 jQuery hoạt động như thế nào .29
2.6.2.1 Sử dụng bộ lọc ID của CSS 29
2.6.2.2 Sử dụng XPath 29
2.6.3 jQuery trong Drupal 30
2.7 Form API 31
2.7.1 Quá trình thao tác với form .31
2.7.2 Một số thao tác cơ bản .34
2.7.2.1 Tạo form .34
2.7.2.2 Giao diện hoá form .35
2.7.2.3 Kiểm tra dữ liệu 35
2.7.2.4 Gửi form lên trang web 36
2.8 Làm việc với cơ sở dữ liệu .36
2.8.1 Định nghĩa các tham số trong CSDL .36
2.8.2 Một số truy vấn đơn giản .37
2.8.3 Lấy kết quả truy vấn 38
Chương 3: Xây dựng module tích hợp .40
Google Maps vào Drupal. .40
3.1 Giới thiệu về Google Maps 40
3.2 Nhúng bản đồ vào trang web 40
3.2.1 Tạo một bản đồ đơn giản .41
3.2.2 Dịch vụ Geocoder - Chuyển đổi giữa địa chỉ và toạ độ 42
3.3 Xây dựng module Google Maps cho Drupal 42
3.3.1 Module Google Maps 42
3.3.1.1 File .info .42
3.3.1.2 File .module 43
3.3.1.3 Tạo thêm trường thông tin cho bài viết 43
Kết luận 46
Phụ lục A 47
A.1 Cài đặt module Google Maps 48
A.2 Chạy thử chương trình .50
Tài liệu tham khảo 47
Bảng từ viết tắt
Từ viết tắt Cụm từ đầy đủ
URI Uniform Resource Identifier
CVS Concurrent Version System
API Application Programming Interface
CSDL Cơ sở dữ liệu
CMS Content Management System
Mở đầu
Trong thời đại Công nghệ thông tin ngày nay, các dịch vụ và ứng dụng web ngày
càng phát triển. Việc một cá nhân hay tổ chức sở hữu một website, một cổng thông tin
là điều dễ thấy trên Internet. Để thiết kế một trang web phục vụ mục đích riêng, người
dùng có nhiều lựa chọn. Một trong số đó là sử dụng hệ quản trị nội dung sẵn có để tổ
chức và xây dựng các trang thông tin.
Với mục đích đó, chúng tôi đã chọn Drupal, một trong các CMS phổ biến nhất,
để thực hiện nghiên cứu. Sở dĩ chúng tôi chọn CMS này vì đây là một hệ mã nguồn
mở miễn phí, được sử dụng rộng rãi và được cộng đồng mạng phát triển ngày càng
hoàn thiện.
Drupal có thể được sử dụng trong nhiều mục đích như xây dựng cổng thông tin
trực tuyến, website cá nhân, tổ chức, website thương mại, báo điện tử, thư viện hình
ảnh .
Hệ thống Drupal được thiết kế để có thể tuỳ biến theo mong muốn của người
dùng và việc tuỳ biến chỉ được thực hiện bằng cách thêm các module để làm tăng khả
năng của hệ thống mà không thay đổi bộ nhân. Do đó, trong khoá luận này chúng tôi
chú trọng tìm hiểu cách xây dựng module cho Drupal và các vấn đề liên quan.
Chúng tôi hi vọng phần kiến thức tìm hiểu được trong khóa luận sẽ mạng lại
những ý nghĩa tích cực trong thực tiễn.
Ngoài phần mở đầu, bố cục của khóa luận gồm 3 chương sau:
ã Chương 1: Trình bày các kiến thức cơ bản về hệ thống Drupal và cách hoạt
động.
ã Chương 2: Tìm hiểu cách viết một module trong Drupal.
ã Chương 3: Đưa lý thuyết đã trình bày vào thực tế để thiết kế một module cụ
thể.
ã Cuối cùng là phần kết luận và hướng phát triển trong tương lai.
57 trang |
Chia sẻ: lvcdongnoi | Lượt xem: 4718 | Lượt tải: 4
Bạn đang xem trước 20 trang tài liệu Tìm hiểu cách xây dựng module cho Drupal và các vấn đề liên quan, để xem tài liệu hoàn chỉnh bạn click vào nút DOWNLOAD ở trên
diện lập trình linh hoạt 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.
1.3.6 API cơ sở dữ liệu và lược đồ
Nằm ở dưới các framework cung cấp ứng dụng và giao diện là một lớp chịu trách
nhiệm về quản lý và thao tác về cơ sở dữ liệu. Drupal cung cấp một API cơ sở dữ liệu
ở cấp thấp để đơn giản hoá việc viết truy vấn SQL.
API này có cơ chế bảo mật giúp kiểm soát và lọc các truy vấn, đồng thời giúp
người phát triển dễ dàng viết các đoạn mã SQL để có thể thực thi ở các cơ sở dữ liệu
khác nhau.
Ngoài ra, một API mới được giới thiệu từ phiên bản Drupal 6 là API lược đồ,
cho phép định nghĩa cấu trúc một cơ sở dữ liệu mà không cần phải viết mã SQL.
Trong khi các cơ sở dữ liệu khác nhau sử dụng các cấu trúc riêng biệt cho việc định
nghĩa bảng, API này giúp giải quyết vấn đề phát triển module có tính di động.
1.4 Hệ thống tệp tin và thư mục của Drupal
Hiểu rõ cấu trúc thư mục của Drupal giúp người quản trị quản lý website một
cách toàn diện và người phát triển có thể can thiệp sâu hơn vào hệ thống. Mặc định,
cấu trúc thư mục của Drupal được sắp xếp như sau:
Hình 1.4.a. Hệ thống tệp tin và thư mục của Drupal
12
Thư mục files sử dụng cho các logo tuỳ biến, hình ảnh đại diện người dùng
hoặc chứa các file đa phương tiện được tải lên website. Thư mục này phải được đặt
quyền đọc và ghi bởi web server phục vụ Drupal.
Thư mục includes chứa thư viện các hàm thường dùng.
Thư mục misc lưu trữ các biểu tưởng và hình ảnh dùng cho Javascript và một số
tài nguyên khác.
Thư mục profiles chứa các profile khác nhau dùng cho cài đặt và thiết lập
Drupal. Ở lần đầu tiên cài đặt, Drupal sẽ hỏi xem người dùng sử dụng profile nào.
Mục đích của các profile là giúp tự động hoá việc cài đặt bằng cách bật các module và
chức năng định sẵn trong phần nhân hệ thống để phù hợp với mục đích sử dụng
website.
Thư mục scripts chứa các tập lệnh dùng để phân tích cú pháp, dọn dẹp mã
nguồn và xử lý các tác vụ đặc biệt với cron. Những tập lệnh tiện ích này được viết
bằng ngôn ngữ shell và Perl.
Thư mục themes chứa các công cụ tạo khuôn mẫu và giao diện mặc định cho
Drupal.
Thư mục sites chứa các thay đổi đối với Drupal dưới dạng thiết lập, module và
giao diện. Các module được thêm vào sẽ nằm trong sites/all/modules. Trong thư
mục sites có thư mục được đặt tên là default chứa các thiết lập mặc định cho hệ
thống Drupal, được ghi lại trong file settings.php. Dưới đây là cấu trúc bên trong thư
mục sites:
13
Hình 1.4.b. Cây thư mục con của thư mục sites
1.5. Drupal xử lý yêu cầu như thế nào?
Nắm được cách thức Drupal xử lý yêu cầu từ phía người dùng và người quản trị
sẽ giúp lập trình viên tác động sâu vào trong hệ thống. Quá trình này có thể tự tìm hiểu
bằng cách sử dụng một bộ dò lỗi và bắt đầu từ file index.php, nơi mà Drupal tiếp nhận
hầu hết các yêu cầu.
1.5.1 Vai trò của Web server
Drupal hoạt động trên một web server, thường là Apache. Nếu web server hỗ trợ
file .htaccess, một số tuỳ chọn trong PHP sẽ được khởi tạo và chức năng URL rút
gọn cũng được bật. Chức năng này giúp chuyển các URL yêu cầu thành dạng ngắn
gọn, ví dụ URL sẽ được chuyển thành
Đối với các web server khác như Microsoft IIS, chức
năng này được hỗ trợ trong các module interface (ISAPI – Windows Internet Server
Application Programming Interface) như ISAPI_Rewrite.
1.5.2 Quá trình khởi động
Drupal tự nạp phần khởi động khi có yêu cầu bằng cách thao tác qua một chuỗi
các bước được định nghĩa trong file bootstrap.inc. Những thao tác này gồm:
Cấu hình
14
Bước này sinh ra một mảng chứa cấu hình bên trong Drupal và thiết lập biến
$base_url cho trang web. File settings.php được phân tích thông qua hàm
include_once() và sử dụng các biến được nạp chồng trước đó.
Bộ nhớ đệm
Trong những trường hợp yêu cầu khả năng mở rộng hệ thống cao, một bộ nhớ
đệm cần được thiết lập trước khi kết nối cơ sở dữ liệu. Bước này cho phép dẫn giải đến
một file PHP chứa hàm page_cache_fastpath() có nhiệm vụ lấy thông tin và trả lại
dữ liệu cho trình duyệt. Chức năng tạo bộ nhớ đệm được bật bằng cách đặt giá trị
TRUE cho biến page_cache_fastpath và file được tham chiếu phải được định nghĩa
thông qua đường dẫn của biến cache_inc.
Cơ sở dữ liệu
Quá trình này xác định loại cơ sở dữ liệu được sử dụng và một kết nối ban đầu
được thiết lập để sử dụng cho các truy vấn.
Truy cập
Drupal cho phép ngăn chặn các truy cập từ máy khách thông qua tham chiếu IP
và tên máy. Trong bước này, hệ thống sẽ kiểm tra xem yêu cầu có phải được thực hiện
từ địa chỉ bị chặn hay không, nếu phải thì truy cập sẽ bị từ chối.
Phiên phục vụ
Drupal tận dụng lợi thế của PHP trong việc quản lý phiên đồng thời phát triển
thêm các chức năng riêng để bổ sung cho việc quản lý phiên cơ sở dữ liệu. Trong bước
này, các phiên sẽ được khởi tạo hoặc thiết lập lại.
Xử lý đường dẫn
Tại bước này, đoạn mã dùng để xử lý đường dẫn và định danh được nạp. Những
URL ở dạng rút gọn hoặc đã được chuyển sang dạng dễ đọc sẽ được phân tích thành
các yêu cầu.
Bước kết thúc
Bước này hoàn thành quá trình khởi động bằng cách nạp các thư viện và các hàm
dùng chung, bộ phận giao diện, xử lý file, mã Unicode, bộ công cụ ảnh PHP, khởi tạo
và xử lý form... Đến đây tất cả các module ở trạng thái bật cũng được nạp. Cuối cùng,
Drupal gọi hook có tên là init để các thông báo đến các module trước khi quá trình xử
lý yêu cầu chính thức bắt đầu.
15
Khi Drupal đã hoàn thành quá trình khởi động, tất cả các thành phần của
framework đều chuyển sang trạng thái sẵn sàng. Lúc này, hệ thống lấy và phân tích
yêu cầu từ phía trình duyệt và chuyển sang các hàm PHP tương ứng để xử lý.
1.5.3 Xử lý yêu cầu
Việc ánh xạ giữa địa chỉ URL và các hàm xử lý được thực hiện thông qua một
bước đăng ký hàm callback để quản lý URL và quyền truy cập. Các module đăng ký
hàm callback của mình bằng cách sử dụng hook menu.
Khi Drupal xác định được có tồn tại một callback đến địa chỉ URL của trình
duyệt mà yêu cầu được ánh xạ và người dùng gửi yêu cầu này có quyền truy cập
callback thì việc xử lý yêu cầu sẽ được giao cho hàm callback đó.
Ví dụ, nếu nhận được một yêu cầu về nội dung là
URL sẽ được ánh xạ đến hàm node_page_view() ở
trong node.module. Các quá trình xử lý tiếp theo sẽ tiếp nhận dữ liệu cho node đó từ cơ
sở dữ liệu. Cuối cùng, phản hồi sẽ được gửi trả lại trình duyệt qua bộ phận giao diện.
1.5.4 Giao diện hoá nội dung
Việc giao diện hoá thực chất là chuyển dữ liệu mà Drupal nhận được, dữ liệu
thông qua xử lý hay dữ liệu tự tạo ra sang dạng HTML. Drupal sẽ sử dụng giao diện
mà người quản trị chọn trước để thiết kế trang web đúng với yêu cầu và chuyển kết
quả HTML cho trình duyệt để hiển thị tới người dùng.
1.6 Công cụ dành cho người phát triển
Drupal đưa ra một số công cụ đặc thù dành cho người phát triển module Drupal.
Những công cụ này được cung cấp bởi 2 module chủ yếu, có thể lấy từ trang web của
Drupal, là module Devel và module Coder.
1.6.1 Module Devel
Module này cung cấp một số công cụ đặc biệt hữu dụng cho việc phát triển
Drupal, gồm có quản lý bộ nhớ cache, công cụ dò lỗi SQL, công cụ thăm dò, công cụ
tham chiếu API...
Thông tin chi tiết về module này có ở:
16
Các công cụ trên được hiển thị dưới dạng các mục trong một Khối. Vì thế, sau
khi cài đặt module Devel, người quản trị phải vào Administer | Site building |
Modules để bật module và vào mục Blocks để xác định ví trí hiện thị nội dung trên
trang chủ.
Module này còn bao gồm các công cụ để xây dựng giao diện, bộ sinh mã macro
để giả lập dữ liệu dành cho form và các dữ liệu cho quá trình testing.
1.6.2 Module Coder
Cũng như một số framework khác, người phát triển Drupal phải tuân theo những
quy ước nhất định trong việc viết mã. Module Coder là một công cụ được thiết kế
nhằm giúp xác định và sửa những đoạn mã không theo quy ước định sẵn.
Ngoài ra, công cụ này còn thực hiện một số bước kiểm tra tính bảo mật bằng
cách quản lý việc các đoạn mã được xử lý như thế nào. Chức năng này hữu ích trong
việc phát hiện các lỗi lập trình và cảnh báo trước khi trở thành các lỗ hổng bảo mật.
Thông tin chi tiết về module này có thể tìm tại trang:
Mặc dù không làm tăng hiệu suất trong việc phát triển như module Devel nhưng
Coder giúp tạo nên những đoạn mã gọn gàng và mang phong cách Drupal. Quá trình
kiểm tra cú pháp của công cụ này còn có thể phát hiện các lỗ hổng về bảo mật.
17
Chương 2 - Xây dựng module cho Drupal
Trong nhiều ứng dụng mã nguồn mở, người dùng có thể tuỳ biến chương trình
bằng cách thay đổi hoặc thêm các đoạn mã. Điều này dẫn đến việc mỗi khi có bản cập
nhật, người dùng phải kiểm tra xem sự tuỳ chỉnh có còn tương thích và hoạt động
đúng như mong muốn hay không. Drupal hoạt động theo một cách khác. Mọi thay đổi
và sự mở rộng được thực hiện thông qua các module. Chương này sẽ tập trung tìm
hiểu cách viết một module cho Drupal.
2.1 File .info và .module
Cấu trúc của một module có thể gồm nhiều tập tin khác nhau nhưng phải có ít
nhất một tập tin .info và một tập tin .module trong đó
là tên của thư mục chứa module được tạo, tên này không được trùng với
các module đã tồn tại trong hệ thống.
2.1.1 File .info
Trước khi thực sự đi vào viết mã cho một module, chúng ta phải tạo ra một file
văn bản chứa các thông tin cơ bản 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.
File .info được viết theo kiểu của file PHP INI, một định dạng file dùng cho
việc xác định các thiết lập. Nội dung một file .info có dạng như sau:
name = “Google Maps”
description = “Displays a map using Google Maps API”
core = 6.x
php = 5.1
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ị. Ví dụ:
18
Hình 2.1.1. Minh họa giao diện hiển thị tên module
Trong hình trên, Aggregrator và Blog được lấy từ giá trị của trường name trong
file .info của các module tương ứng.
Tiếp theo là phần 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 thông tin thứ ba là core. Mục này chỉ rõ module sẽ hoạt động tốt trên
phiên bản nào của Drupal. Giá trị 6.x cho biết module này yêu cầu phiên bản Drupal 6,
bao gồm các phiên bản nâng cấp từ bản 6. Trong nhiều trường hợp, Drupal sẽ tự động
đặt giá trị này một cách hợp lý, nhưng những người phát triển làm việc với CVS
(Concurrent Version System - hệ thống quản lý phiên bản ứng dụng) được khuyến cáo
nên tự mình đặt giá trị cho trường core.
Chỉ dẫn cuối cùng trong file .info trên là php, cho biết phiên bản tối thiểu của
PHP mà module yêu cầu.
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ư:
- 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.
Sau khi có file .info, chúng ta bắt đầu việc viết mã cho module trong file
.module.
19
2.1.2 File .module
File .module là file quan trọng nhất trong một module, chứa các đoạn mã PHP
thực hiện chức năng của module đó. File này thông thường sẽ mở rộng một số hàm
hook mà Drupal gọi tại các thời điểm nhất định đối với một yêu cầu.
Cũng giống như file .info, file .module được đặt tên theo quy tắc
.module, trong đó là tên thư mục chứa 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. Ví dụ, nếu các ký tự
trống được xuất ra trước khi phần thông tin header của HTML gửi đi, ở trình duyệt
máy khách sẽ xuất hiện thông báo lỗi trên đầu của trang web.
Mã nguồn chi tiết của file này sẽ được đề cập trong những phần tiếp theo.
2.2 Chú thích trong mã nguồn
Như đã đề cập ở trên, Drupal tuân theo các tiêu chuẩn viết mã và tài liệu một
cách chặt chẽ. Xem chi tiết tại Một trong số
đó là chuẩn viết chú thích trong mã nguồn.
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 của module
GoogleMaps:
/**
* @file
* Module for displaying a map from Google Maps.
* This module provides block content retrieved from
* Google Maps data.
* @see
*/
Phần này chính là tài liệu cho API, chứa trong một khối chú thích đặc biệt 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ý.
20
Trong ví dụ trên có hai định danh là @file và @see. Đị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.
Đị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. Trong ví dụ, nguồn dẫn là một địa chỉ URL. Các hàm, hằng số và biến
cũng được tham chiếu bởi định danh @see. Trong các trường hợp này, bộ xử lý tài liệu
sẽ liên kết khối chú thích đến thông tin API của các đối tượng tương ứng.
Khi chú thích cho một hàm, các định danh khác sẽ được sử dụng. Ví dụ:
/**
* Retrieve information from the Goodreads bookshelp XML API.
*
* This makes an HTTP connection to the given URL, and
* retrieves XML data, which it then attempts to format
* for display.
*
* @param $url
* URL to the goodreads bookshelf.
* @param $num_items
* Number of items to include in results.
* @return
* String containing the bookshelf.
*/
Khối này bắt đầu bằng một câu khái quát về chức năng của hàm, theo sau là các
dòng chú thích chi tiết hơn. Từ khoá đị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. Từ khoá này được
khai báo theo theo định dạng: @param . Một định danh khác được
sử dụng cho chú thích hàm là @return cho biết giá trị mà hàm sẽ trả về.
Từ những chú thích này, người phát triển có thể sử dụng những chương trình
phân tích tài liệu như Doxygen để trích ra làm tài liệu dành cho người dùng.
2.3 Một số hook cơ bản
- Hook block:
21
Hook này được sử dụng để tạo một block hiển thị thông tin. Khi hook_block
được gọi, Drupal sẽ truyền 3 tham số vào hàm: $op, $delta và $edit.
Tham số $op chứa thông tin về loại thao tác mà module sẽ thực hiện. Tham số
này có thể nhận một trong 4 giá trị sau:
list: Giá trị này được dùng khi module cung cấp thông tin về chính nó. Ví dụ, ở
danh sách các module hiển thị trong khu vực quản trị, tham số $op sẽ được đặt là list.
view: Giá trị này được truyền vào khi Drupal muốn hook block cung cấp thông
tin để hiển thị cho người dùng.
configure: Dùng để điều chỉnh các thiết lập cho block.
save: Giá trị này được dùng khi thông tin về thiết lập của block lấy từ form dữ
liệu sinh ra bởi configure cần được lưu lại.
Tham số $delta được đặt phụ thuộc vào các thao tác nhất định của module. Khi
$op có giá trị là view thì $delta sẽ được đặt. Tham số này chứa các thông tin thêm về
nội dung sẽ hiển thị trong block. Bằng cách sử dụng $delta, một hàm hook_block()
có thể hiển thị nhiều block khác nhau. Nội dung nào trong block sẽ được sử dụng tuỳ
thuộc vào giá trị của $delta được truyền vào.
Cuối cùng là tham số $edit, được sử dụng trong quá trình điều chỉnh các thiết
lập của block (khi thao tác save được gọi). $edit thực chất là một mảng chứa các thay
đổi mà người quản trị thực hiện lên các thiết lập của block.
Giá trị trả về của hàm này phụ thuộc vào thao tác mà nó thực hiện. Thông
thường, hàm sẽ trả về một mảng chứa thông tin của block (info), tiêu đề (subject) và
nội dung (content).
- Hook help:
Hook này được dùng để cung cấp các thông tin trợ giúp cho người sử dụng. Hàm
hook_help() nhận hai tham số: $path chứa một đoạn URI cho biết trang trợ giúp nào
được gọi, và tham số $arg chứa một số thông tin thêm.
Với các trường hợp phức tạp, lập trình viên có thể sử dụng phát biểu switch đối
với giá trị của $path để trả về các văn bản trợ giúp khác nhau đối với mỗi đường dẫn.
Giá trị này tuân theo định dạng admin/help# , trong đó
được thay bằng tên của module tương ứng. Kết quả của hàm này được hiển thị tại mục
Administer | Help page:
22
Hình 2.3.a. Minh họa nội dung sử dụng hook_help().
- Hook user:
Mặc định, mỗi người dùng đã đăng ký đều có thể truy cập trang My account để
xem thông tin tài khoản của họ. Địa chỉ URL của trang này có dạng:
Người dùng sẽ thấy những thông tin sau:
Hình 2.3.b. Giao diện thông tin tài khoản người dùng
Trang thông tin người dùng cũng có thể được truy cập bởi một người quản trị có
quyền tương ứng. Phần lớn nội dung của trang này được tạo ra bởi hook_user(). Bằng
cách triển khai hook này trong module, người phát triển có thể liên kết với giao diện
quản lý người dùng.
Thực ra, hook người dùng làm được nhiều việc hơn là hiển thị trang tài khoản
người dùng. Trong Drupal 6 có 13 thao tác mà hook này thực thi, bao gồm việc thêm,
sửa chữa hoặc xoá bộ ghi nhớ đăng nhập.
Một bản triển khai của hook_user() sẽ nhận 4 tham số sau:
$op: Tên của thao tác mà người dùng thực hiện. Tham số này nhận 1 trong 13 giá
trị tương ứng với 13 thao tác (view, login, delete...).
$edit: Một mảng chứa các giá trị được gửi lên từ một form. Giá trị này được
truyền vào qua tham chiếu &$edit và được sử dụng bởi các thao tác xử lý dữ liệu như
insert.
23
$account: Dùng để chứa đối tượng tài khoản cho một người dùng nhất định.
Tham số này cũng được truyền qua tham chiếu &$account.
$category: Một vài thao tác sử dụng tham số này để xác định phần nào của thông
tin người dùng sẽ được trích xuất cho yêu cầu.
Chi tiết về hook này xem tại địa chỉ
- Hook mail:
Phần lớn các yêu cầu về việc gửi email trong Drupal đều được hỗ trợ bởi các
hàm có trong Mail API nên người phát triển không cần phải viết mã cho những thao
tác này. Tuy nhiên, tuỳ theo yêu cầu, người phát triển có thể tuỳ chỉnh định dạng của
thông điệp, và việc này được thực hiện thông qua hook_mail(). Việc triển khai hook
này cho phép thiết lập các phần đầu và thân của thông điệp trước khi gửi đi.
Khi hàm triển khai hook mail được thực thi, nó sẽ truyền 3 tham số sau:
$key: Một khoá dạng chuỗi dùng để xác định thông tin về việc thông điệp sẽ
được định dạng như thế nào.
$message: Là cấu trúc dữ liệu thể hiện thông điệp mà Drupal đã khởi tạo trước
đó. Tham số này phải được truyền dưới dạng tham chiếu &$message nếu muốn thay
đổi giá trị.
$params: Một tập các tham số được truyền vào từ lời gọi hàm drupal_mail() của
module.
- Hook view:
Trước khi một node được hiển thị đến người dùng, thông tin của nó có thể được
cập nhật bằng cách sử dụng hook_view(). Hook này được gọi khi hệ thông nạp một
đối tượng $node, nhưng vào thời điểm trước khi node được hiển thị. Hàm này sẽ cần
thiết trong một số trường hợp mà nội dung của node có thêm một số trường thông tin
Drupal chưa xử lý được.
Đồng thời, hook này sẽ cung cấp thêm thông tin cho hệ thống giao diện để có thể
biểu diễn nội dung như mong muốn của người dùng.
Hàm triển khai của hook này sẽ nhận 3 tham số:
$node chứa đối tượng node cần hiển thị.
24
$teaser là cờ đánh dấu cho biết bài viết sẽ được hiển thị đầy đủ hay chỉ có bản
tóm tắt. Tham số này nhận giá trị Logic, TRUE hoặc FALSE.
$page cho biết node này sẽ hiển thị ở trang riêng hay không. Nếu $page có giá trị
TRUE, tiêu đề của node sẽ không được hiển thị.
Giá trị trả về của hàm khai triển hook_view() chính là $node. Tham số này sẽ
được thay đổi nếu cần thiết để có thể được biểu diễn một cách chính xác. Các node
được chuẩn bị cho việc hiển thị bằng cách tập hợp một mảng có cấu trúc trong
$node->content, thay cho việc thao tác với từng thành phần riêng $node->body và
$node->teaser.
Chi tiết của hook này xem thêm tại địa chỉ
- Hook menu:
Chức năng cơ bản của hook_menu() là cho phép người phát triển module đăng ký
một URI nhất định (hoặc chi tiết hơn là một đường dẫn URL tương đối) và ánh xạ URI
đó với một hàm xử lý. Hook này thường được dùng để tạo các thực đơn cho trang
quản lý của module.
Giống như các hook khác, một bản triển khai của hook_menu() trả về một mảng,
trong trường hợp này là mảng các mục thực đơn sẽ được đăng ký với nhân của Drupal.
Mảng liên kết này sẽ chứa một địa chỉ thực (giá trị) cho mỗi đường dẫn được đăng ký
trước (khoá).
Dựa vào những tham số cấu hình này, Drupal sẽ xác định cách chuyển một yêu
cầu từ máy khách tới đường dẫn tương ứng để xử lý. Việc này được thực hiện bằng
cách ánh xạ các hàm callback.
2.4 Định nghĩa một hook mới
Trong phần này, chúng tôi sẽ xem xét kỹ cơ chế hoạt động của hook bằng cách
tạo một hook riêng và triển khai vào các module. Mục đích của việc định nghĩa hook
riêng là giúp người phát triển module có thể chỉ định nội dung sẽ được đưa vào bản tin
và cách hiển thị chúng.
25
2.4.1 Cách tạo một hook
Việc định nghĩa một hook mới rất đơn giản, thậm chí chỉ cần một dòng mã.
Nhưng để thuận tiện hơn cho những người phát triển sử dụng sau này, hook nên được
định nghĩa một cách chi tiết.
Có một số cách để làm cho hook trở nên dễ sử dụng và triển khai. Cách thứ nhất
là thêm các thông tin chi tiết về hook vào trong khối tài liệu của đoạn mã. Cách thứ hai
là tạo ra một hàm hook trong mã nguồn, hàm này sẽ không được gọi đến mà chỉ đóng
vai trò làm mẫu.
Ví dụ:
/**
* Use this hook to build content for a sitenews message.
*
* This should return an array of items:
* array('item_name' => $item)
* An item is an associative array with the following
* fields set:
*
* - #weight: An integer from -10 to 10
* - #content: Text content
* - #title: A title for the text content
*
* Weight and content are required. If #title
* is set, then it will be added as a title.
*
* @return
* A content array.
*/
function hook_sitenews() {
$content['report'] = array(
'#weight' => 0,
'#title' => t('Sample Title'),
'#body' => t('Sample content')
26
);
$content['another report'] = array(
'#weight' => 0,
'#title' => t('Another Sample Title'),
'#body' => t('More sample content')
);
return $content;
}
Nhiệm vụ chính của hàm này là làm mẫu để hướng dẫn người dùng sử dụng
hook_sitenews(). Nó sẽ không được gọi trong mọi trường hợp, kể cả khi hệ thống
nhận lời gọi hàm module_invoke() hay module_invoke_all() vì tên hàm không tuân
theo quy tắc _.
Phần tài liệu trong khối chú thích mô tả một cách chi tiết chức năng của hàm
hook cho người phát triển. Phần mã nguồn được thiết kế để thể hiện cách tạo một bản
triển khai mà người phát triển nên tuân theo.
2.4.2 Sử dụng hook vào các module khác
Việc sử dụng hàm hook tự định nghĩa vào trong module cũng giống như đối với
các hook có sẵn của Drupal. Bản triển khai của một hook phải được đặt theo quy tắc
_() và có các tham số trùng với phần khai báo của hook.
Ví dụ:
function biography_sitenews() {
//code goes here
}
Các hook được định nghĩa trong một module có thể được triển khai trong module
khác và module chứa khai báo hook phải được bật.
2.5 Một số hàm quan trọng trong thư viện hàm của Drupal
- Hàm chuyển đổi ngôn ngữ t():
Đây là hàm chuyển đổi ngôn ngữ trong Drupal, được sử dụng để hỗ trợ chức
năng đa ngôn ngữ, đồng thời cung cấp một cách thức chuẩn trong việc thay thế văn
bản. Khi hàm t() được gọi, Drupal sẽ kiểm tra xem ngôn ngữ mà người dùng lựa chọn
27
có khác với ngôn ngữ mặc định (Anh-Mỹ) hay không. Nếu có thì Drupal sẽ cố gắng
dịch xâu đầu vào sang ngôn ngữ người dùng chỉ định.
Để Drupal hỗ trợ đa ngôn ngữ, module Content translation phải được bật.
Trong những trường hợp đơn giản, hàm t() nhận chỉ một tham số vào là xâu
chứa thông điệp cần chuyển đổi. Khi đó, toàn bộ xâu sẽ được dịch nghĩa. Nhưng trong
một số trường hợp khác, hàm sẽ nhận các dữ liệu thêm vào. Ví dụ, khi cần thêm một
địa chỉ URL vào trong một xâu:
‘Trying to access !url.’
và muốn hàm t() dịch nghĩa xâu này, đồng thời thay thế URL tương ứng vào vị trí của
!url. Lúc đó, hàm t() được sử dụng như sau:
t(‘Trying to access !url.’, array(‘!url’=>’http:///example.com’));
Trong ví dụ trên, t() nhận 2 tham số: xâu cần dịch nghĩa, và một mảng liên hợp
ánh xạ cờ giữ chỗ và giá trị thay thế. Nếu ngôn ngữ lựa chọn là tiếng Anh, hàm trên sẽ
cho ra kết quả:
Trying to access
- Hàm watchdog():
Một hàm khác nằm trong bộ nhân của Drupal là hàm watchdog(), cung cấp cơ
chế ghi biên bản cho Drupal.
Hàm watchdog() nhận 4 tham số. Tham số đầu tiên xác định danh mục của bản
ghi. Thông thường, các module sẽ sử dụng tên của module làm danh mục để có thể dễ
dàng tìm kiếm các bản ghi sau này.
Tham số thứ hai và thứ ba gồm có thông điệp dưới dạng văn bản, và một mảng
liên hợp có giá trị khoá sẽ được thay thế vào thông báo.
Tham số cuối cùng là một hàng số, xác định quyền ưu tiên dành cho bản ghi đó.
Tham số này lấy 1 trong 8 giá trị sau:
WATCHDOG_EMERG: Hệ thống lúc này đang trong tình trạng không ổn định.
WATCHDOG_ALERT: Nhắc nhở người dùng cần thực hiện một việc nào đó ngay lập
tức.
WATCHDOG_CITICAL: Thông báo tình trạng nguy cấp.
WATCHDOG_ERROR: Xảy ra lỗi.
28
WATCHDOG_WARNING: Cảnh báo xảy ra sự cố không mong đợi nhưng không gây ra
vấn đề nghiêm trọng.
WATCHDOG_NOTICE: Một sự kiện quan trọng (nhưng không ảnh hưởng xấu) xảy ra.
WATCHDOG_INFO: Cho biết thông tin có thể được ghi lại.
WATCHDOG_DEBUG: Thông tin về việc gỡ lỗi sẽ được ghi lại.
Mức độ ERROR và WARNING thường được sử dụng bởi các nhà phát triển module để
ghi lại lỗi. Hầu hết các module không chứa các đoạn mã đủ để gây ra vấn đề nghiêm
trọng cho Drupal, vì thế 3 mức độ trên cùng (ALERT, CRITICAL và EMERG) không nên sử
dụng trừ khi hệ thống đang trong tình trạng xấu.
Đồng thời với việc ghi lại biên bản trong hệ thống, trang web nên hiển thị thông
báo tới người dùng. Điều này được thực hiện bằng cách trả về một chuỗi chứa thông
báo:
return t(“This page is not accessible”);
Bên cạnh việc ghi biên bản các sự kiện, người phát triển có thể thực hiện các
thao tác liên quan bằng cách triển khai hook_watchdog() mà Drupal cung cấp. Mặc
định, các bản ghi được lưu vào trong cơ sở dữ liệu. Người quản trị có thể xem lại bằng
cách truy cập vào mục Administer | Logs.
2.6 Sử dụng Javascript và AJAX/JSON
2.6.1 Giới thiệu về jQuery
jQuery là một trong số các thư viện JavaScript mạnh mẽ hiện nay. Sử dụng một
mô hình thiết kế hướng đối tượng là Fluent Interface, jQuery cho phép liên kết một
chuỗi các lời gọi hàm với nhau để tạo nên các truy vấn phức tạp.
Thông thường, jQuery truy vấn tới cây DOM. Một cây DOM (Document Object
Model) là một cấu trúc dữ liệu định nghĩa nên cấu trúc của một văn bản, thường là
HTML hoặc XML. Văn bản này sẽ được biểu diễn dưới dạng cây với thành phần đầu
tiên là gốc. DOM được biết đến là một mô hình đối tượng phức tạp. jQuery cung cấp
một API nhẹ hơn và dễ sử dụng hơn cho người lập trình.
Tuy nhiên, jQuery được sử dụng trong nhiều trường hợp, không chỉ riêng truy
vấn. Nó có một bộ công cụ AJAX, công cụ xử lý sự kiện, hiệu ứng ảo và một số hàm
tiện ích khác.
Thông tin thêm về jQuery có tại địa chỉ
29
2.6.2 jQuery hoạt động như thế nào
Trong phần này, chúng tôi sẽ tìm hiểu cách jQuery tìm kiếm trong một văn bản
có cấu trúc bằng cách sử dụng CSS và XPath. CSS được sử dụng cho một văn bản
HTML hoặc XHTML. XPath sử dụng trong văn bản XML. Thay cho việc tạo các cú
pháp để tìm kiếm trong JavaScript, jQuery triển khai cú pháp truy vấn sẵn có của CSS
và XPath, giúp cho người phát triển không phải nhớ các ngôn ngữ khác nhau.
2.6.2.1 Sử dụng bộ lọc ID của CSS
Giả sử đoạn mã HTML cần thao tác là :
Welcome to the World of Widgets
Nếu muốn đặt màu sắc cho nền của đoạn trong thẻ , chúng ta sẽ sử dụng
CSS để xác định đoạn văn bản thông qua ID #intro. ID này không được trùng với các
ID khác trong cùng một trang.
#intro {
background-color: blue;
}
Việc này có thể được thử hiện bằng cách sử dụng jQuery như sau:
// Định nghĩa biến jQuery như một hàm.
var jQuery = function(a,c) {...}
// Ánh xạ không gian tên jQuery đến ký hiệu “$”
var $ = jQuery;
$("#intro").css("background-color", "blue");
Trong trường hợp sử dụng lớp CSS, đoạn mã jQuery sẽ là:
$(".intro").css("background-color", "blue").fadeIn("slow");
jQuery cũng có thể thực hiện một số hiệu ứng lên trang web, ví dụ:
$("#intro").css("background-color", "blue").fadeIn("slow");
hoặc:
$("p.intro").css("background-color", "blue").fadeIn("slow");
2.6.2.2 Sử dụng XPath
Nếu một thành phần của trang HTML không được đánh dấu bằng ID hoặc bộ lọc
lớp, cách truy vấn trên sẽ không thực hiện được. Lúc đó, XPath là một giải pháp tốt để
30
thay thế. XPath có phần linh hoạt hơn trong việc tạo các quy tắc để xác định thành
phần trong HTML. Ngoài ra, XPath còn hỗ trợ sử dụng biểu thức chính quy.
Ví dụ:
- Tìm các thẻ có thuộc tính target là _blank:
$(“a[@target=_blank]”)
- Tìm các checkbox trong form:
$(“input[@type=checkbox]”)
Chi tiết về các biểu thức sử dụng trong XPath có thể xem thêm tại địa chỉ
2.6.3 jQuery trong Drupal
Mặc định, jQuery sẽ được cài đặt cùng với Drupal, vì thế việc sử dụng là khá dễ
dàng. Mã nguồn của jQuery được chứa trong file jquery.js nằm trong thư mục misc.
File này sẽ được nạp khi có lời gọi hàm drupal_add_js(). Hàm này có nhiệm vụ nhận
mã JavaScript và thêm vào mã nguồn trang web. Ví dụ:
<?php
drupal_add_js(
'$(document).ready(function(){
$("p").fadeIn("slow");
});',
'inline'
);
?>
Tham số đầu tiên của hàm drupal_add_js() là đoạn mã JavaScript sẽ được thực
thi. Tham số thứ hai (inline) cho biết Drupal sẽ ghi đoạn mã vào giữa hai thẻ
ở trong thẻ của trang HTML.
Tuy nhiên, để đảm bảo rằng module hoạt động đúng như mong đợi, chúng ta cần
phải đảm bảo các truy vấn jQuery chỉ chạy khi trình duyệt hỗ trợ JavaScript và AJAX.
Nếu trình duyệt không hỗ trợ, các thay đổi đối với HTML phía máy khách sẽ không
được thực hiện. Thư viện JavaScript của Drupal có hàm Drupal.jsEnabled() sẽ kiểm
tra điều kiện này.
if(Drupal.jsEnabled) {
// code goes here
31
}
Giá trị trả về của hàm này là TRUE hoặc FALSE tương ứng với kết quả kiểm tra.
2.7 Form API
Từ phiên bản 4.7 trở về sau, Drupal cung cấp một API hỗ trợ việc tạo, xác thực
và xử lý form trong HTML. API này biểu diễn các form bằng một mảng chứa các
thuộc tính và giá trị. Một số ưu điểm của bộ máy này:
• Dễ sử dụng.
• Không cần phải viết mã HTML mà chỉ cần khai báo các thuộc tính và
giá trị của form.
• Dễ dàng thêm, xoá, đảo thứ tự và thay đổi các form. Điều này thuận tiện
khi muốn chỉnh sửa một form được tạo bởi module khác.
• Mỗi thành phần trong một form có thể được liên kết với một hàm giao
diện riêng.
• Có thể thêm các bước xác thực và xử lý riêng cho từng form.
• Các thao tác liên quan được bảo vệ tránh việc tấn công bằng cách thực
hiện những thay đổi ảnh hưởng xấu đến hệ thống.
Trong phần này, chúng tôi sẽ tìm hiểu về Form API và ứng dụng vào một số ví
dụ cụ thể.
2.7.1 Quá trình thao tác với form
Biều đồ dưới đây mô tả quá trình xây dựng, kiểm tra tính hợp lệ và trình bày
form.
Để có thể sử dụng Form API một cách hiệu quả, người phát triển phải biết được
cách mà bộ máy phía sau API hoạt động.
32
Hình 2.7.1. Quá trình xử lý form
33
Các bước trong quá trình xử lý:
• Khởi tạo: hàm drupal_get_form() bắt đầu bằng việc khởi tạo giá trị
$form_values (mảng chứa các giá trị được gửi lên) bằng rỗng và
$form_submitted bằng FALSE.
• Đặt một token: Drupal đặt giá trị khoá riêng cho mỗi bản cài đặt. Khi khoá được
tạo ra sẽ được lưu trong bảng variables với trường drupal_private_key. Một
token giả ngẫu nhiên dựa vào khoá này để kiểm tra một form khi được gửi lên.
• Đặt ID: Một trường thông tin dạng ẩn chứa ID của form hiện tại sẽ được gửi đến
trình duyệt. Mỗi ID thường tương ứng với hàm định nghĩa của form và là tham
số đầu tiên của drupal_get_form().
• Tập hợp thông tin các thành phần của form: Hàm element_info() sẽ được gọi.
Hàm này sẽ thực thi hook_elements() trong tất cả các module có bản triển khai.
Các thành phần cơ bản như nút checkbox, radio... được định nghĩa trong
system.module. Một module cũng có thể tự định nghĩa kiểu thành phần riêng
bằng cách sử dụng hook_elements().
• Tìm kiếm hàm kiếm tra giá trị: Một hàm kiểm tra giá trị có thể được gán bằng
cách đặt thuộc tính #validate trong form vào một mảng với tên hàm là khoá và
mảng khác làm giá trị.
• Tìm kiếm hàm gửi form: Hệ thống sẽ tìm kiếm những hàm có thuộc tính #submit
và thực thi. Nếu không tìm thấy, Drupal thực thi hàm có ID plus_submit nếu
có.
• Xây dựng form: Tại bước này, form sẽ được chuyển sang hàm form_builder()
để xử lý thông qua một cây đệ quy và thêm các giá trị bắt buộc theo chuẩn.
• Tìm hàm chuyển đổi giao diện cho form: Nếu giá trị $form[‘#theme’] được đặt
trong một hàm, Drupal sẽ sử dụng hàm đó. Nếu không, hàm
theme_get_function() sẽ được gọi để xác định nếu có hàm giao diện cho form
hiện tại.
• Thể hiện form trong HTML: Bộ xây dựng form sẽ gọi hàm drupal_render().
Đây là một hàm đệ quy, duyệt qua mỗi cấp của cây biểu diễn form và xử lý
từng node. Với mỗi node, hàm drupal_render() sẽ phân tích thông tin của các
thành phần có trong form và tạo ra mã HTML.
34
2.7.2 Một số thao tác cơ bản
2.7.2.1 Tạo form
Các thành phần của một form được khai báo trong một mảng có cấu trúc phân
cấp và có thể ghép lồng nhau. Mỗi thành phần gồm có các cặp thuộc tính/giá trị. Ví dụ
sau định nghĩa một thành phần textfield:
<?php
$form['foo'] = array(
'#type' => 'textfield',
'#title' => t('bar'),
'#default_value' => $object['foo'],
'#size' => 60,
'#maxlength' => 64,
'#description' => t('baz'),
);
?>
Tạo một nút bấm gửi dữ liệu:
<?php
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Save'),
);
?>
Một vài điểm lưu ý:
• Thuộc tính name của thành phần được khai báo trong mảng $form và nằm ở cuối
mảng. Ví dụ:
$form['account_settings']['username']
• Kiểu của thành phần form được khai báo qua thuộc tính #type.
• Các khoá thuộc tính được khai báo trong dấu [], giá trị của khoá có kiểu xâu.
• Thứ tự khai báo các thuộc tính không quan trọng. Một số thuộc tính có giá trị
mặc định.
35
• Không nên sử dụng thuộc tính #value cho các thành phần có thể được thay đổi
bởi người dùng, thay vào đó, nên sử dụng thuộc tính #default_value.
2.7.2.2 Giao diện hoá form
Form API cho phép tuỳ chỉnh giao diện đối với từng form, thậm chí đối với riêng
từng thành phần trong một form. Việc tuỳ chỉnh được thực hiện bằng cách nạp chồng
các thành phần giao diện tại thời điểm tạo form:
• Thêm thuộc tính #theme vào form chính hoặc các thành phần, cho phép chỉ định
hàm giao diện nào sẽ được áp dụng.
• Chèn thẻ đánh dấu trực tiếp vào form như một thành phần của form đó. Các thẻ
đánh dấu có thể là #prefix, #suffix hoặc #markup. Thẻ này dùng để chỉ định
vị trí các đoạn mã thiết lập giao diện trong form. Ví dụ:
$form['access'] = array(
'#type' => 'fieldset',
'#title' => t('Access log settings'),
'#prefix' => '',
'#suffix' => '',
);
• Ghép các đoạn mã của từng thành phần trong form để hiển thị ra trang web. Ở
bước này, hàm drupal_render() sẽ được gọi.
2.7.2.3 Kiểm tra dữ liệu
Form API có bước kiểm tra dữ liệu vào, thực hiện trên tất cả các form được gửi
lên. Ngoài các hàm có sẵn, người phát triển cũng có thể tự tạo các hàm kiểm tra theo ý
muốn. Tên hàm phải được đặt theo quy tắc _validate. Hàm này nhận hai
tham số: $form và $form_state. $form là mảng chứa khai báo của form.
$form_state[‘values’] chứa giá trị cần kiểm tra. Ví dụ:
function test_form_validate($form, &$form_state) {
if ($form_state['values']['name'] == '') {
form_set_error('', t('You must select a name.'));
}
}
36
2.7.2.4 Gửi form lên trang web
Cách thức thông thường được sử dụng để gửi form lên là thông qua hàm. Một
form được gửi lên bằng nút bấm có thuộc tính type => 'submit' sẽ được truyền
tới hàm tương ứng. Ví dụ:
function test_form_submit($form, &$form_state) {
db_query("INSERT INTO {table} (name, log, hidden) VALUES ('%s',
%d, '%s')", $form_state['values']['name'],
$form_state['values']['access']['log'],
$form_state['values']['hidden']);
drupal_set_message(t('Your form has been saved.'));
}
Hàm gửi dữ liệu chỉ được gọi khi nhận lệnh từ nút bấm submit có phương thức
POST và dữ liệu được kiểm tra hợp lệ.
2.8 Làm việc với cơ sở dữ liệu
Phần này sẽ giới thiệu sơ lược về cách kết nối và truy vấn CSDL trong Drupal.
2.8.1 Định nghĩa các tham số trong CSDL
Drupal xác định được CSDL, tài khoản và mật khẩu của người dùng khi thiết lập
kết nối bằng cách phân tích file settings.php. nằm trong thư mục sites/default.
Dòng thông tin định nghĩa kết nối tới CSDL có dạng:
$db_url = 'mysql://username:password@localhost/databasename';
Phương thức định nghĩa kết nối là mysql hoặc pgsql phụ thuộc vào CSDL được
sử dụng là MySQL hay PostgreSQL.
Dựa vào đó, Drupal xác định file thiết lập CSDL sẽ tham chiếu tới và khởi động
CSDL tương ứng. Quá trình này được minh hoạ bởi hình dưới đây:
37
Hình 2.8.1. Quá trình thao tác với CSDL.
Một đoạn mã bên ngoài muốn truy cập vào CSDL của Drupal sẽ phải gọi
include_once(‘includes/bootstrap.inc’) sau đó gọi
drupal_bootstrap(DRUPAL_BOOTSTRAP_DATABASE) để tạo kết nối, sau đó thực hiện truy
vấn bằng hàm db_query().
2.8.2 Một số truy vấn đơn giản
Drupal cung cấp hàm db_query() để thực thi một truy vấn tới kết nối đang hoạt
động. Những truy vấn được hỗ trợ bao gồm SELECT, INSERT, UPDATE và
DELETE. Dưới đây là một số ví dụ.
Lấy tất cả các hàng của một trường từ bảng joke có vid là số nguyên, có giá trị
bằng $node->vid:
38
db_query('SELECT * FROM {joke} WHERE vid = %d', $node->vid);
Chèn một hàng mới vào bảng joke. Hàng mới chứa 2 giá trị nguyên và một xâu
ký tự:
db_query("INSERT INTO {joke} (nid, vid, punchline) VALUES (%d, %d,
'%s')",$node->nid, $node->vid, $node->punchline);
Cập nhật tất cả các hàng trong bảng joke có trường vid là số nguyên có giá trị
bằng $node->vid. Các hàng thoả mãn điều kiện này sẽ thay đổi bằng cách đặt trường
punchline bằng giá trị của xâu chứa trong $node->punchline:
db_query("UPDATE {joke} SET punchline = '%s' WHERE vid = %d",
$node->punchline,$node->vid);
Xoá các hàng trong bảng joke có cột nid chứa giá trị nguyên bằng với $node-
>nid:
db_query('DELETE FROM {joke} WHERE nid = %d', $node->nid);
Drupal đặt ra một số quy tắc về cú pháp trong phát biểu SQL. Đầu tiên, tên bảng
phải được đặt trong dấu {}. Quy ước này cho phép những người dùng bị giới hạn số
lượng CSDL tạo ra có thể cài đặt Drupal trong một CSDL có sẵn mà không bị xung
đột.
Tiếp theo là cờ giữ chỗ trong truy vấn. Ở ví dụ trên, %d sẽ tự động được thay thế
bằng giá trị $node->nid tương ứng. Dưới đây là bảng ký hiệu giữ chỗ và kiểu dữ liệu
thay thế:
Hình 2.8.2. Bảng ký hiệu giữ chỗ trong truy vấn CSDL.
2.8.3 Lấy kết quả truy vấn
Có nhiều cách khác nhau để lấy kết quả truy vấn.
Lấy một giá trị: Nếu muốn kết quả trả về chỉ một giá trị thì có thể sử dụng hàm
db_result().
39
$sql = "SELECT COUNT(*) FROM {node} WHERE type = 'blog' AND status =
1";
$total = db_result(db_query($sql));
Trả về nhiều hàng: Với kết quả là một tập gồm nhiều hàm, hàm
db_fetch_object() giúp chọn ra từng hàng để xử lý.
$sql = "SELECT * FROM {node} WHERE type = 'blog' AND status = 1";
$result = db_query(db_rewrite_sql($sql));
while ($data = db_fetch_object($result)) {
//code goes here
}
Để nhận được kết quả là một mảng, chúng ta có thể sử dụng hàm
db_fetch_array() thay cho db_fetch_object().
Giới hạn phạm vi kết quả: Với những truy vấn cho ra rất nhiều hàng, có thể giới
hạn phạm số lượng như sau:
$sql = "SELECT * FROM {node} n WHERE type = 'blog' AND status = 1
ORDER BY n.created DESC";
$result = db_query_range(db_rewrite_sql($sql), 0, 10);
Trong trường hợp này, hàm db_query_range() được sử dụng thay cho điều kiện
LIMIT vì không phải tất cả CSDL đều hỗ trợ cú pháp LIMIT.
40
Chương 3: Xây dựng module tích hợp
Google Maps vào Drupal
Với lý thuyết đã nêu ra ở những phần trên của khoá luận, chúng tôi sẽ ứng dụng
vào thực tế bằng cách xây dựng một module cho Drupal. Module này có tên là Google
Maps, có chức năng hiển thị bản đồ trên trang web.
Trước hết, chúng tôi sẽ giới thiệu sơ lược về dịch vụ Google Maps.
3.1 Giới thiệu về Google Maps
Google Maps (trước đây được gọi là Google Local) là một ứng dụng dịch vụ bản
đồ web và công nghệ miễn phí được cung cấp bởi Google, có thể dùng để nhúng vào
các trang web của bên thứ ba thông qua Google Maps API. Nó cho phép hiển thị bản
đồ đường xá, đường đi cho xe đạp, cho người đi bộ hoặc xe hơi, và những địa điểm
kinh doanh trong khu vực cũng như khắp nơi trên thế giới. (Theo wikipedia.org)
Địa chỉ chính thức của Google Maps:
Google Maps cung cấp các cách thể hiện bản đồ khác nhau gồm có bản đồ
ranh giới, bản đồ vệ tinh và bản đồ dạng 3 chiều. Giao diện của chương trình rất thân
thiện với người dùng.
3.2 Nhúng bản đồ vào trang web
Việc nhúng bản đồ vào trang web được thực hiện Google Maps API. Người dùng
không cần phải tìm kiếm và quản lý dữ liệu hay thiết lập máy chủ mà chỉ cần viết một
ít đoạn mã JavaScript.
Với mỗi người phát triển, Google cung cấp một khoá API riêng. Khoá này có thể
đăng ký miễn phí tại
Mỗi khi muốn nhúng bản đồ của Google vào trang web, trong thẻ phải
khai báo chèn file JavaScript:
<script src=
type="text/javascript">
Trong đó, xyz được thay bằng khoá API. Lúc này, trang web có thể sử dụng các
hàm và đối tượng được cung cấp trong API của Google Maps.
41
3.2.1 Tạo một bản đồ đơn giản
Thông thường, việc nhúng bản đồ trên một trang web được thực hiện bằng cách
sử dụng một thẻ giữ chỗ và dùng JavaScript hiển thị bản đồ vào vị trí đó. Ví dụ:
var map = new GMap2(document.getElementById("map"));
//zoom levels 0-17+, 0 == world
map.setCenter(new GLatLng(39.754286, -104.994637), 16);
Ví dụ trên sẽ cho kết quả như sau:
Hình 3.2.1. Minh họa trang web tích hợp bản đồ Google Maps.
Phần bản đồ hiển thị được gán vào đối tượng map dựa vào toạ độ của điểm trung
tâm.
Tài liệu chi tiết về các dịch vụ của Google Maps API cũng như tính năng cao cấp
có thể tham khảo tại địa chỉ:
42
3.2.2 Dịch vụ Geocoder - Chuyển đổi giữa địa chỉ và toạ độ
Google Maps API cung cấp một dịch vụ rất hữu ích là Geocoder, giúp xác định
toạ độ tương đối khi biết một địa chỉ trên trên thế giới và ngược lại. Toạ độ phân tích
được gồm Kinh độ (longitude) và Vĩ độ (latitude). Từ đó, chúng ta tạo ra được một đối
tượng điểm và hiển thị lên bản đồ.
3.3 Xây dựng module Google Maps cho Drupal
Module mà chúng tôi xây dựng có chức năng hiển thị bản đồ số trong một khối
đối với các bài viết dạng Blog. Mỗi bài viết tương ứng với một mảnh bản đồ riêng dựa
vào thông tin địa chỉ chứa trong bài đó.
Trong quá trình xây dựng module này, chúng tôi đã sử dụng lại 2 module do
cộng đồng Drupal phát triển là module Content có trong gói CCK (Content
Construction Kit) [5] và module Example fields [6]. Module Content cho phép người
quản trị tạo các kiểu nội dung mới. Module Example fields được dùng để thêm các
trường thông tin cho bài viết. Cả hai module này đều được phấn phối miễn phí.
Ý tưởng xây dựng module:
• Lấy node id của bài viết hiện tại.
• Truy vấn CSDL để lấy trường thông tin đã thêm vào.
• Sử dụng các giá trị ẩn trong form truyền dữ liệu vào JavaScript.
• Tạo đối tượng bản đồ GMap2 hiển thị vào trong thẻ đã khai báo.
• Tạo đối tượng chuyển đổi địa chỉ sang tọa độ GClientGeocoder.
• Truyền tọa độ nhận được vào một hàm tạo điểm trên bản đồ.
• Hiển thị bản đồ bằng cách đặt điểm vừa tạo làm trung tâm.
• Sử dụng chức năng đánh dấu địa điểm marker để chú thích điểm trên bản đồ.
Phần tiếp theo sẽ mô tả các đoạn mã mà tác giả khóa luận viết trong quá trình
xây dựng module.
3.3.1 Module Google Maps
3.3.1.1 File .info
Nội dung file .info gồm có:
;$Id$
43
name = "Google Maps"
description = "Displays a Google Maps form in a block"
core = 6.x
php = 5.1
dependencies[] = content
Khai báo dependencies cho biết module Google Maps phụ thuộc vào module
Content. Muốn module này hoạt động thì người quản trị phải bật module Content
trong gói CCK.
3.3.1.2 File .module
File này sẽ triển khai hook_block() có sẵn trong Drupal để hiển thị bản đồ trong
một khối.
function googlemaps_block($op='list', $delta=0, $edit=array()) {
return $block;
}
Giá trị trả về của hàm này là một mảng $block chứa tiêu đề (subject) và nội dung
(content) của khối.
Để hiển thị bản đồ trong khối này, chúng tôi sẽ gán giá trị cho
$block[‘content’] là một thẻ có ID là map_canvas để xác định vị trí đặt bản
đồ.
$block['content'] = "<div id=\"map_canvas\" style=\"width:600px;
height:400px\">" . $hAddr . $hTitle . $hInfo;
Khi đó JavaScript có thể tìm kiếm thành phần HTML thông qua ID và thay thế
nội dung:
var map = new GMap2(document.getElementById("map_canvas"));
Để bản đồ chỉ hiển thị trong các bài viết, module thực hiện quá trình phân tích và
kiểm tra địa chỉ URL của trang hiện tại. Nếu địa chỉ có chứa node/x thì đoạn mã hiển
thị bản đồ sẽ được thực thi.
3.3.1.3 Tạo thêm trường thông tin cho bài viết
Để hiển thị các mảnh bản đồ khác nhau cho mỗi bài viết, chúng tôi sử dụng bộ
xây dựng nội dung CCK để thêm một trường thông tin address vào kiểu nội dung
Blog. Thực hiện tạo một mục có dạng Blog entry sẽ xuất hiện thêm một trường như
trong hình:
44
Hình 3.3.1.3.a. Giao diện tạo Block entry.
Giá trị này được lưu trong CSDL và có thể lấy ra thông qua node ID.
$nid = (arg(0)=='node' && is_numeric(arg(1)))?arg(1):0;
$sql = "SELECT field_addr_value FROM content_type_blog WHERE nid
= $nid";
Khi lấy được giá trị của trường này, module sẽ truyền qua JavaScript và sử dụng
dịch vụ Geocoder của Google Maps API để phân tích ra tọa độ và hiển thị ra khung
bản đồ.
45
Hình 3.3.1.3.b. Giao diện bài viết cùng với Block hiển thị bản đồ.
46
Kết luận
Trong khoá luận này, chúng tôi đã tìm hiểu và trình bày một số vấn đề lý thuyết
liên quan đến việc xây dựng module cho hệ quản trị nội dung Drupal. Dựa vào đó,
chúng tôi đã thiết kế thành công một module dùng để nhúng bản đồ từ Google Maps
vào mỗi bài viết kết hợp với hai module miễn phí là CCK [5] và Example fields [6].
Tuy nhiên, đây mới chỉ là bước đầu trong kế hoạch xây dựng một hệ thống tích hợp
dịch vụ hướng vị trí vào website một cách hoàn thiện, đầy đủ tính năng.
Sau khi hoàn thành khoá luận, chúng tôi có ý định tiếp tục nghiên cứu và phát
triển module đã trình bày ở trên và thêm các tính năng nâng cao như kết hợp với cơ sở
dữ liệu ảnh chụp để để hiển thị đường phố, phong cảnh hay sử dụng hình ảnh 3 chiều
tạo ra không gian ảo cho từng địa điểm, địa danh...
Chúng tôi hy vọng khoá luận đã đúc kết được một lượng kiến thức đủ để phục vụ
cho việc tìm hiểu về Drupal cũng như xây dựng module một cách dễ dàng.
47
Tài liệu tham khảo
[1] David Mercer. Building powerful and robust websites with Drupal 6. PACKT
Publishing, 2008.
[2] John K. VanDyk và Matt Westgate. Pro Drupal Development. Apress,
2007.
[3] Matt Butcher. Learning Drupal 6 Module Development. PACKT
Publishing, 2008.
[4] Scott Davis. Google Maps API v2 - Adding Where to your applications. The
Pragmatic Bookshelf, 2006.
[5] Module CCK, Drupal Community,
[6] Module Example, Karen Stevenson,
custom-cck-fields.
[7]Google Maps API Documentation, Google Inc,
48
Phụ lục A
A.1 Cài đặt module Google Maps
Bước 1: Copy thư mục googlemaps vào thư mục modules trong bộ cài đặt Drupal.
Bước 2: Bật các module liên quan gồm Content, Example fields và Google Maps trong
trang quản trị.
Hình A.1.a. Bật các module trong trang quản trị.
Bước 3: Thêm trường thông tin Địa chỉ cho loại nội dung Blog entry. Vào
Administer | Content management | Content types. Trong mục Blog entry chọn
manage fields.
Thêm một trường mới với các thông tin sau:
• Label: Địa chỉ.
• Field name: field_addr.
49
• Type of data to store: Example field.
• Form element to edit the data: Example widget.
Sau khi thêm trường mới vào, cấu trúc một Blog entry sẽ có các trường sau:
Hình A.1.b. Các trường thông tin của Blog entry.
Đến đây, module đã sẵn sàng để sử dụng.
50
A.2 Chạy thử chương trình
Môi trường mà chúng tôi dùng để chạy thử module đã viết như sau:
• Hệ điều hành: Windows 7 Ultimate.
• Server: localhost
• Web server: Apache.
• SQL server: MySQL.
• Trình duyệt: Mozilla Firefox 3.6.3.
Tạo một Blog entry mới như sau:
Hình A.2.a. Tạo Blog entry mới để chạy thử chương trình.
Những thông số còn lại giữ nguyên. Nhấn Save. Kết quả nhận được là bài viết cùng
với bản đồ như hình dưới.
51
Hình A.2.b. Kết quả chạy thử chương trình.
Các file đính kèm theo tài liệu này:
- Tìm hiểu cách xây dựng module cho Drupal và các vấn đề liên quan.pdf