Nội quy chuyên mục: - Chuyên mục này chỉ dành để viết các bài viết hướng dẫn sử dụng NukeViet 3.x. Vui lòng không mở các chủ đề mới nhằm thảo luận, hỏi đáp... tại đây. Các thảo luận và hỏi đáp liên quan đến các hướng dẫn vui lòng trả lời vào các chủ đề có hướng dẫn đó.
- Ban Quản Trị cũng khuyến khích tất cả các thành viên hoàn thiện các bài viết bổ ích của mình và đưa lên Thư viện tài liệu mở về NukeViet tại địa chỉ http//wiki.nukeviet.vn
#79508 gửi bởi hoaquynhtim99
Ngày 04 Tháng 02 2011 , 19:26
Để dễ thao tác các bạn hãy làm giống mình phần code (số dòng)
Trong khuôn khổ bài viết này mình sẽ trình bày với các bạn cấu trúc cơ bản, công dụng cũng như chức năng của từng file trong thư mục module và cách viết một module chi tiết từ đơn giản tới phức tạp.
-- Cấu trúc một module, chức năng các file, các file, floder bắt buộc phải có.
-- Cách viết một module đơn giản chỉ chứa file PHP.
-- Mở rộng kết hợp file PHP riêng ngoài các file bắt buộc phải có.
-- Làm việc với file ngôn ngữ lang.
-- Sử dụng xtemplate.
-- Mở rộng thêm các file thông tin module, RSS
-- Sử dụng javscript và ajax cho module (phần AJAX các bạn xem tại viewtopic.php?f=117&t=15403).
-- Sử dụng lớp (class) đã được xây dựng sẵn.
-- Tích hợp thêm các phần mở rộng

Trước khi vào phần hướng dẫn mình xin trình bày một số quy ước. Các file PHP được bắt đầu với phần thông tin về tác giả, bản quyền, ngày viết, email tác giả.. VÍ dụ như:
Mã: Chọn hết
/**
* @Project NUKEVIET-MUSIC
* @Author Phan Tan Dung (phantandung92@gmail.com)
* @copyright 2011
* @createdate 26/01/2011 09:17 AM
*/


Tương tự cho các file js

Mã: Chọn hết
/* *
* @Project NUKEVIET-MUSIC
* @Author Phan Tan Dung (phantandung92@gmail.com)
* @copyright 2011
* @createdate 26/01/2011 09:17 AM
*/


Tên module tốt nhất các bạn chỉ đặt tên bằng chữ cái không chứa các kí tự đặc biệt.

Bây giờ ta vào phần chi tiết.

---- CẤU TRÚC CƠ BẢN CỦA MỘT MODULE
Bao gồm các file và thư mục sau:
- admin.functions.php
- version.php
- funcs
- funcs/main.php
- admin
- admin/main.php
- functions.php


Với nhiêu đó là ta đã có một module đơn giản (không có CSDL) có thể hoạt động rồi. Như vậy muốn viết một module đầu tiên ta tạo một thư mục có tên là tên của module trong thư mục modules. Sau đó lần lượt tạo các thư mục, file như trên vào thư mục vừa tạo.
Mình sẽ ví dụ đây là module quanlihs.

Chức năng của các file như sau:

-- file version.php: file này có chức năng khai báo tiêu đề module, các funcs có block, tác giả module, thông tin phiên bản, cấu trúc thư mục trong thư mục uploads.
-- File admin.functions.php: File này thường chứa các function, hằng dùng trong admin
-- File function.php: File này thường chứa các function, hằng dùng cho ngoài site
-- admin/main.php: File này sẽ thể hiện nội dung của module phần admin
-- funcs/main.php: FIle này sẽ thể hiện nội dung (trang chính) của module bên ngoài site.

Thứ tự khởi động một module như sau: Khi module được chạy thì tùy theo admin hay ngoài site mà file admin.functions.php hay file function.php được chạy trước sau đó là các file trong thư mục admin hay funcs được chạy tiếp theo mặc định sẽ là file main.php.
Ta thường thấy url trang web nukeviet (chưa bật rewrite) có dạng http://yourdomain/index.php?lang=vi&nv= ... =listenone
Trong đó lang chính là ngôn ngữ của site, nv là module đang chạy, op chính là funcs đang chạy (ở đây là listenone). Giá trị op này chính là tên của funsc trong thư mục funsc hay admin. Nếu trên url mà khuyết phần op= có nghĩa funcs main.php đang được chạy.

Cấu trúc url như trên là cấu trúc cơ bản. Giá trị op ta có thể thay đổi ví dụ như http://nukeviet.vn/vi/news/viec-lam/ . Ta sẽ tìm hiểu sau.

Bây giờ chúng ta bắt đầu viết một module đơn giản (không có CSDL) để xuất ra dòng chữ "XIN CHÀO CÁC BẠN" bên trong admin và ngoài site.
Đầu tiên tạo một thư mục (là tên module) trong thư mục modules rồi thêm vào đó các file và thư mục sau:
- admin.functions.php
- version.php
- funcs
- funcs/main.php
- admin
- admin/main.php
- functions.php

file version.php có nội dung:
Mã: Chọn hết
<?php

/**
* @Project NUKEVIET-MUSIC
* @Author Phan Tan Dung (phantandung92@gmail.com)
* @copyright 2011
* @createdate 05/12/2010 09:47
*/

if ( ! defined( 'NV_ADMIN' ) or ! defined( 'NV_MAINFILE' )) die( 'Stop!!!' );

$module_version = array(
"name" => "QuanLyHocSinh", // Tieu de module
"modfuncs" => "main" ,
"is_sysmod" => 0,
"virtual" => 1,
"version" => "3.0.01",
"date" => "Wed, 26 Jan 2011 12:47:15 GMT",
"author" => "PHAN TAN DUNG (email: phantandung1912@gmail.com)",
"note"=>"",
"uploads_dir" => array(
$module_name
)
);
?>

Dòng này: if ( ! defined( 'NV_ADMIN' ) or ! defined( 'NV_MAINFILE' )) die( 'Stop!!!' ); các bạn để nguyên ở mọi module
-"modfuncs" => "main": Tên các funcs trong thư mục funcs có block khi hoạt động bên ngoài site. Đối với các funcs không có block ví dụ như để xử lý AJAX, gửi email (popup) thì không cần khai báo. Các funcs được phân cách nhau bởi dấu "," ví dụ:
Mã: Chọn hết
"modfuncs" => "main, funcs1, funcs2, funcs3" ,

-"is_sysmod" => 0, : Có phảo module hệ thông hay không 0: không 1: có.
-"virtual" => 1: CHo phép ảo hóa module không 0: không 1: có
-date,author, version: thông tin ngày , tác giả, phiên bản module.
-uploads_dir: Khai báo cấu trúc thư mục trong thư mục uploads. Với khai báo như trên thì khi kích hoạt module hệ thông sẽ tạo một thư mục có tên là tên của module trong thư mục upload (biến $module_name được hiểu là tên module)
Sửa lần cuối bởi hoaquynhtim99 vào Ngày 03 Tháng 03 2012 , 20:24, với tổng số 3 lần sửa.
Nguyên nhân: Hoàn thành bài viết

Hãy sống là chính mình, bình thường nhưng không tầm thường.
#79543 gửi bởi hoaquynhtim99
Ngày 05 Tháng 02 2011 , 18:28
file admin.functions.php có nội dung như sau:
Mã: Chọn hết
<?php

/**
* @Project NUKEVIET-MUSIC
* @Author Phan Tan Dung (phantandung92@gmail.com)
* @Copyright 2011
* @createdate 26/01/2011 10:08 AM
*/

if ( ! defined( 'NV_ADMIN' ) or ! defined( 'NV_MAINFILE' ) or ! defined( 'NV_IS_MODADMIN' ) ) die( 'Stop!!!' );

$allow_func = array('main');
define( 'NV_IS_MUSIC_ADMIN', true );
?>

- $allow_func = array('main'); : biến $allow_func là một mảng một chiều chứa các funcs rong thư mục admin cho phép chạy. Ở ví dụ này chỉ cho một funcs là main.php. Các funcs không được khai báo trong biến này khi chạy sẽ báo lỗi "Bạn không có quyền truy cập chức năng này."
- define( 'NV_IS_QUANLY_ADMIN', true ); Dòng này sẽ khởi tạo một hằng dùng cho module. Các funcs như main.php sẽ kiểm tra giá trị hằng này nếu đúng sẽ chạy ngược lại sẽ báo lỗi "Stop!!!".
file function.php các bạn thêm như sau:
Mã: Chọn hết
<?php

/**
* @Project NUKEVIET-MUSIC
* @Author Phan Tan Dung (phantandung92@gmail.com)
* @copyright 2011
* @createdate 26/01/2011 10:10 AM
*/

if (!defined('NV_SYSTEM')) die('Stop!!!');
define('NV_IS_MOD_QUANLY', true);
?>

Với module đơn giản như ví dụ này thì file này chỉ có chức năng tạo một hằng để dùng bên ngoài site thôi.
Tạo file main.php trong thư mục admin với nội dung như sau:
Mã: Chọn hết
<?php
/**
* @Project NUKEVIET-MUSIC
* @Phan Tan Dung (phantandung92@gmail.com)
* @Copyright (C) 2011
* @Createdate 26-01-2011 14:43
*/

if ( ! defined( 'NV_IS_QUANLY_ADMIN' ) ) die( 'Stop!!!' );
$page_title = "Trang chính";

$contents = "Xin chào các bạn";

include (NV_ROOTDIR . "/includes/header.php");
echo nv_admin_theme($contents);
include (NV_ROOTDIR . "/includes/footer.php");
?>

- Biến $page_title là tiêu đề của funcs hiện tại.
- Tất cả nội dung sẽ được lưu vào một biến $contents sau đó sẽ được xuất ra sau khi gọi file header.php. Phần :
Mã: Chọn hết
include (NV_ROOTDIR . "/includes/header.php");
echo nv_admin_theme($contents);
include (NV_ROOTDIR . "/includes/footer.php");
Các bạn giữ nguyên mọi module (trong admin)
Tương tự tạo file main.php lưu vào thư mục funcs với nội dung như sau:
Mã: Chọn hết
<?php
/**
* @Project NUKEVIET-MUSIC
* @Author Phan Tan Dung
* @Copyright (C) 2011
* @Createdate 26/01/2011 10:26 AM
*/

if ( ! defined( 'NV_IS_MOD_QUANLY' ) ) die( 'Stop!!!' );
$page_title = $module_info['custom_title'];
$key_words = $module_info['keywords'];

$contents = "Xin chào các bạn";

include ( NV_ROOTDIR . "/includes/header.php" );
echo nv_site_theme( $contents );
include ( NV_ROOTDIR . "/includes/footer.php" );
?>

OK như vậy ta đã tạo xong một module đơn giản để xuất ra dong chữ "Xin chào các bạn" bên trong admin lẫn ngoài site. Bây giờ các bạn vào phần thiết lập module mới kích hoạt modlue vừa tạo rồi vào phần quản lí của module và noài site bạn sẽ thấy kết quả
Với module Đơn giản này ta có thể sử dụng để inframe trang khác hoặc liên kết sang trang khác khi ấn vào menu. Ví dụ thay file main.php bằng:
Mã: Chọn hết
<?php
/**
* @Project NUKEVIET-MUSIC
* @Author Phan Tan Dung
* @Copyright (C) 2011
* @Createdate 26/01/2011 10:26 AM
*/

if ( ! defined( 'NV_IS_MOD_QUANLY' ) ) die( 'Stop!!!' );
$page_title = $module_info['custom_title'];
$key_words = $module_info['keywords'];

$contents = '<iframe id="I1" name="I1" src="http://24h.com.vn/" style="width: 1029px; height: 693px">
Your browser does not support inline frames or is currently configured not to display inline frames.
</iframe>
';

include ( NV_ROOTDIR . "/includes/header.php" );
echo nv_site_theme( $contents );
include ( NV_ROOTDIR . "/includes/footer.php" );
?>
Ta có module inframe của trang 24h
Hay thay file main.php bằng :
Mã: Chọn hết
<?php
/**
* @Project NUKEVIET-MUSIC
* @Author Phan Tan Dung
* @Copyright (C) 2011
* @Createdate 26/01/2011 10:26 AM
*/

if ( ! defined( 'NV_IS_MOD_QUANLY' ) ) die( 'Stop!!!' );
$page_title = $module_info['custom_title'];
$key_words = $module_info['keywords'];

$contents = '';
Header( "Location: http://nhaccuateen.info" ) ;

include ( NV_ROOTDIR . "/includes/header.php" );
echo nv_site_theme( $contents );
include ( NV_ROOTDIR . "/includes/footer.php" );
?>
Ta có module khi vào thì sẽ chuyển sang trang http://nhaccuateen.info. Hay các bạn có thể dùng vào nhiều việc khác

Hãy sống là chính mình, bình thường nhưng không tầm thường.
#79629 gửi bởi hoaquynhtim99
Ngày 07 Tháng 02 2011 , 11:33
Tiếp theo chúng ta sẽ thêm file action.php làm nhiệm vụ thao tác với CSDL khi cài đặt cũng như xóa module. Bây giờ ta thêm một table trong CSDL để quản lí học sinh trong lớp (STT, họ tên, ngày sinh, địa chỉ). Tạo file action.php đặt cùng thư mục với file functions.php với nội dung như sau:
Mã: Chọn hết
<?php
/**
* @Project NUKEVIET-MUSIC
* @Author Phan Tan Dung (phantandung92@gmail.com)
* @copyright 2011
* @createdate 26/01/2011 10:10 AM
*/

if( !defined('NV_IS_FILE_MODULES') ) die('Stop!!!');

$sql_drop_module = array();
$sql_drop_module[] = "DROP TABLE IF EXISTS `" . $db_config['prefix'] . "_" . $lang . "_" . $module_data . "`";

$sql_create_module = $sql_drop_module;

$sql_create_module[] = "CREATE TABLE `" . $db_config['prefix'] . "_" . $lang . "_" . $module_data . "` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`stt` INT( 255 ) unsigned NOT NULL,
`hoten` varchar(255) NOT NULL,
`ngaysinh` INT( 11 ) NOT NULL DEFAULT '0',
`diachi` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM";

?>

Các bạn vào phần quản lí module cài lại module sẽ thấy trong CSDL có thêm một table. Mình giải thích nội dung file trên:
$sql_drop_module[], $sql_create_module[] để chỉ việc xóa, tạo mới module. Biến $db_config['prefix'] là tiếp đầu tố của table, $lang là ngôn ngữ của site, $module_data thông thường được hiểu như tên của module. Nội dung bên trong dấu ngoặc kép là lệnh thao tác với CSDL không nhất thiết phải là xóa, thêm mà có thể chỉnh sửa, xóa trường, chèn dữ liệu... Biến $sql_create_module[] dạng ARRAY nên có thể thêm nhiều lệnh thao thác csdl (tạo nhiều bảng).

Ta đã tạo CSDL thành công bây giờ cần phải viết code để làm việc với nó. Bây giờ phần quản lí module ta cần có thêm một submenu để thêm học sinh. Mở file admin.functions.php lên sửa lại như sau:
Mã: Chọn hết
<?php

/**
* @Project NUKEVIET-MUSIC
* @Author Phan Tan Dung (phantandung92@gmail.com)
* @Copyright 2011
* @createdate 26/01/2011 10:08 AM
*/

if ( ! defined( 'NV_ADMIN' ) or ! defined( 'NV_MAINFILE' ) or ! defined( 'NV_IS_MODADMIN' ) ) die( 'Stop!!!' );

$submenu['add'] = "Thêm học sinh";

$allow_func = array('main', 'add');

define( 'NV_IS_QUANLY_ADMIN', true );
?>


Ta thấy bây giờ có thêm $submenu['add'] có nghĩa là ta đã khai báo một submenu trong admin, biến $allow_func thêm mới 'add' có nghĩa ta đã chấp nhận thêm một funcs mới có tên add (add.php). Bây giờ các bạn vào phần quản lí module sẽ thấy có thêm submenu "Thêm học sinh" nhưng khi ấn vào sẽ hiện : "Lỗi truy cập 404
Lỗi 404: Trang web mà bạn đã cố gắng truy cập không tồn tại trên máy chủ của website." có nghĩa là chưa có file add.php. Ta thêm file add.php vào thư mục admin với nội dung như sau:
Mã: Chọn hết
<?php
/**
* @Project NUKEVIET-MUSIC
* @Phan Tan Dung (phantandung92@gmail.com)
* @Copyright (C) 2011
* @Createdate 26-01-2011 14:43
*/

if ( ! defined( 'NV_IS_QUANLY_ADMIN' ) ) die( 'Stop!!!' );
$page_title = "Thêm học sinh";

$my_head = "<script type=\"text/javascript\" src=\"" . NV_BASE_SITEURL . "js/popcalendar/popcalendar.js\"></script>\n";
$my_head .= "<script type=\"text/javascript\" src=\"" . NV_BASE_SITEURL . "js/shadowbox/shadowbox.js\"></script>\n";
$my_head .= "<link rel=\"stylesheet\" type=\"text/css\" href=\"" . NV_BASE_SITEURL . "js/shadowbox/shadowbox.css\" />\n";
$my_head .= "<script type=\"text/javascript\">\n";
$my_head .= "Shadowbox.init({\n";
$my_head .= "});\n";
$my_head .= "</script>\n";

$contents = "";
$error = "";

$data = array();
$data['hoten'] = filter_text_input( 'hoten', 'post', '' );
$data['ngaysinh'] = filter_text_input( 'ngaysinh', 'post', '', 1, 10 );
unset( $m );
if ( preg_match( "/^([0-9]{1,2})\.([0-9]{1,2})\.([0-9]{4})$/", $data['ngaysinh'], $m ) )
{
$data['ngaysinh1'] = mktime( 0, 0, 0, $m[2], $m[1], $m[3] );
}
else
{
$data['ngaysinh1'] = "";
}

$data['diachi'] = $nv_Request->get_string( 'diachi', 'post', '' );

if ( ($nv_Request->get_int( 'add', 'post', 0 ) == 1) )
{
if ( $data['hoten'] == "" )
{
$error = "Bạn chưa nhập tên học sinh";
}
elseif ( $data['ngaysinh'] == "" )
{
$error = "Bạn chưa nhập ngày sinh";
}
elseif ( $data['diachi'] == "" )
{
$error = "Bạn chưa nhập địa chỉ";
}
else
{
$sql = "SELECT `stt` FROM `" . NV_PREFIXLANG . "_" . $module_data . "` ORDER BY stt DESC LIMIT 0,1";
$resuilt = $db->sql_query( $sql );
list ( $currentstt ) = $db->sql_fetchrow( $resuilt );
$newstt = $currentstt + 1;

$query = "INSERT INTO `" . NV_PREFIXLANG . "_" . $module_data . "`
(
`id`, `stt`, `hoten`, `ngaysinh`, `diachi`
)
VALUES
(
NULL,
" . $newstt . ",
" . $db->dbescape( $data['hoten'] ) . ",
" . $data['ngaysinh1'] . ",
" . $db->dbescape( $data['diachi'] ) . "
)";
if ( $db->sql_query_insert_id( $query ) )
{
$db->sql_freeresult();
Header( "Location: " . NV_BASE_ADMINURL . "index.php?" . NV_NAME_VARIABLE . "=" . $module_name); die();
}
else
{
$error = "Không thể lưu dữ liệu được";
}

}
}

if( $error )
{
$contents .= "<div class=\"quote\" style=\"width: 780px;\">\n
<blockquote class=\"error\">
<span>".$error."</span>
</blockquote>
</div>\n
<div class=\"clear\">
</div>";
}
$contents .="
<form method=\"post\">
<table class=\"tab1\">
<thead>
<tr>
<td colspan=\"2\">
Thông tin học sinh mới
</td>
</tr>
</thead>
<tbody>
<tr>
<td style=\"width: 150px;\">
Tên học sinh
</td>
<td style=\"background: #eee;\">
<input name=\"hoten\" style=\"width: 470px;\" value=\"" . $data['hoten'] . "\" type=\"text\">
</td>
</tr>
</tbody>
<tbody>
<tr>
<td>
Ngày sinh
</td>
<td>
<input id=\"ngaysinh\" name=\"ngaysinh\" style=\"width: 470px;\" value=\"" . $data['ngaysinh'] . "\" type=\"text\" />
<img src=\"" . NV_BASE_SITEURL . "images/calendar.jpg\" style=\"cursor: pointer; vertical-align: middle;\" onclick=\"popCalendar.show(this, 'ngaysinh', 'dd.mm.yyyy', true);\" alt=\"\" height=\"17\" />
</td>
</tr>
</tbody>
<tbody>
<tr>
<td>
Địa chỉ
</td>
<td>
<input name=\"diachi\" style=\"width: 470px;\" value=\"" . $data['diachi'] . "\" type=\"text\" />
</td>
</tr>
</tbody>
<tr>
<td colspan=\"2\" align=\"center\" style=\"background: #eee;\">\n
<input name=\"confirm\" value=\"Lưu\" type=\"submit\">\n
<input type=\"hidden\" name=\"add\" value=\"1\">\n
</td>\n
</tr>\n
</table>\n
</form>\n";

include (NV_ROOTDIR . "/includes/header.php");
echo nv_admin_theme($contents);
include (NV_ROOTDIR . "/includes/footer.php");
?>


Với đoạn code trên ta có một funcs với chức năng thêm học sinh. Mình giải thích như sau:

Đoạn này là phần sử dụng biến $my_head để gọi java và CSS. Tạm thời phần này cho qua đến phần sử dụng java chúng ta sẽ quay lại.
Ở đây ta đã gọi ra shadowbox.css, shadowbox.js, popcalendar.js để làm nhiệm vụ hiển thị lịch.
Mã: Chọn hết
$my_head = "<script type=\"text/javascript\" src=\"" . NV_BASE_SITEURL . "js/popcalendar/popcalendar.js\"></script>\n";
$my_head .= "<script type=\"text/javascript\" src=\"" . NV_BASE_SITEURL . "js/shadowbox/shadowbox.js\"></script>\n";
$my_head .= "<link rel=\"stylesheet\" type=\"text/css\" href=\"" . NV_BASE_SITEURL . "js/shadowbox/shadowbox.css\" />\n";
$my_head .= "<script type=\"text/javascript\">\n";
$my_head .= "Shadowbox.init({\n";
$my_head .= "});\n";
$my_head .= "</script>\n";


Mã: Chọn hết
$data = array();
$data['hoten'] = filter_text_input( 'hoten', 'post', '' );
$data['ngaysinh'] = filter_text_input( 'ngaysinh', 'post', '', 1, 10 );
unset( $m );
if ( preg_match( "/^([0-9]{1,2})\.([0-9]{1,2})\.([0-9]{4})$/", $data['ngaysinh'], $m ) )
{
$data['ngaysinh1'] = mktime( 0, 0, 0, $m[2], $m[1], $m[3] );
}
else
{
$data['ngaysinh1'] = "";
}

$data['diachi'] = $nv_Request->get_string( 'diachi', 'post', '' );


Đoạn này dùng để lấy dữ liệu khi submit form và được lưu dưới dạng mảng (array). Các cách lấy dữ liệu các bạn có thể tham khảo tại bài hướng dẫn viết module đội code viết.

Mã: Chọn hết
if ( ($nv_Request->get_int( 'add', 'post', 0 ) == 1) )
{
if ( $data['hoten'] == "" )
{
$error = "Bạn chưa nhập tên học sinh";
}
elseif ( $data['ngaysinh'] == "" )
{
$error = "Bạn chưa nhập ngày sinh";
}
elseif ( $data['diachi'] == "" )
{
$error = "Bạn chưa nhập địa chỉ";
}

Đoạn này sẽ kiểm tra xem dữ liệu đã được nhập chưa nếu chưa thì gán thông báo lỗi cho biến $error.

Mã: Chọn hết
$sql = "SELECT `stt` FROM `" . NV_PREFIXLANG . "_" . $module_data . "` ORDER BY stt DESC LIMIT 0,1";
$resuilt = $db->sql_query( $sql );
list ( $currentstt ) = $db->sql_fetchrow( $resuilt );
$newstt = $currentstt + 1;

$query = "INSERT INTO `" . NV_PREFIXLANG . "_" . $module_data . "`
(
`id`, `stt`, `hoten`, `ngaysinh`, `diachi`
)
VALUES
(
NULL,
" . $newstt . ",
" . $db->dbescape( $data['hoten'] ) . ",
" . $data['ngaysinh1'] . ",
" . $db->dbescape( $data['diachi'] ) . "
)";
if ( $db->sql_query_insert_id( $query ) )
{
$db->sql_freeresult();
Header( "Location: " . NV_BASE_ADMINURL . "index.php?" . NV_NAME_VARIABLE . "=" . $module_name); die();
}
else
{
$error = "Không thể lưu dữ liệu được";
}


Đoạn này thực hiện việc lấy giá trị stt lớn nhất, tăng giá trị này lên một và ghi dữ liệu vào CSDL.

Mã: Chọn hết
if( $error )
{
$contents .= "<div class=\"quote\" style=\"width: 780px;\">\n
<blockquote class=\"error\">
<span>".$error."</span>
</blockquote>
</div>\n
<div class=\"clear\">
</div>";
}

Đoạn này là xuất ra lỗi (nếu có)

CÒn phần cuối cùng là phần nội dung hiển thị (form).

Hãy sống là chính mình, bình thường nhưng không tầm thường.
#79641 gửi bởi hoaquynhtim99
Ngày 07 Tháng 02 2011 , 21:01
Ta vừa thực hiện xong việc thêm học sinh. Bây giờ ta cần hiển thị danh sách các học sinh. Mở file main.php trong thư mục admin và chỉnh lại như sau:
Mã: Chọn hết
<?php
/**
* @Project NUKEVIET-MUSIC
* @Phan Tan Dung (phantandung92@gmail.com)
* @Copyright (C) 2011
* @Createdate 26-01-2011 14:43
*/

if ( ! defined( 'NV_IS_QUANLY_ADMIN' ) ) die( 'Stop!!!' );
$page_title = "Trang chính";

$contents = "
<table class=\"tab1\">
<thead>
<tr>
<td>
STT
</td>
<td>
Họ và tên
</td>
<td>
Ngày sinh
</td>
<td>
Địa chỉ
</td>
</tr>
</thead>
<tbody>";
$sql = "SELECT * FROM `" . NV_PREFIXLANG . "_" . $module_data . "` ORDER BY stt ASC";
$resuilt = $db->sql_query( $sql );
while ( $row = $db->sql_fetchrow( $resuilt ) )
{
$contents .= "
<tr>
<td>
" . $row['stt'] . "
</td>
<td>
" . $row['hoten'] . "
</td>
<td>
" . date( "d/m/Y", $row['ngaysinh'] ) . "
</td>
<td>
" . $row['diachi'] . "
</td>
</tr>";
}
$contents .= "</tbody></table>";

include (NV_ROOTDIR . "/includes/header.php");
echo nv_admin_theme($contents);
include (NV_ROOTDIR . "/includes/footer.php");
?>

Đoạn code trên thực hiện việc đọc thông tin từ CSDL và xuất ra ngoài site qua vòng lặp while. Riêng phần ngày sinh thì dùng hàm date để định dạng theo ngày/tháng/năm.

Cơ bản xong phần admin. Bây giờ ta đi tiếp bên ngoài site để thể hiện danh sách các học sinh. Chỉnh lại file main.php trong thư mục funcs như sau:
Mã: Chọn hết
<?php
/**
* @Project NUKEVIET-MUSIC
* @Author Phan Tan Dung
* @Copyright (C) 2011
* @Createdate 26/01/2011 10:26 AM
*/

if ( ! defined( 'NV_IS_MOD_QUANLY' ) ) die( 'Stop!!!' );
$page_title = $module_info['custom_title'];
$key_words = $module_info['keywords'];

$contents = '';
$contents = "
<table class=\"tab1\">
<thead>
<tr>
<td>
STT
</td>
<td>
Họ và tên
</td>
<td>
Ngày sinh
</td>
<td>
Địa chỉ
</td>
</tr>
</thead>
<tbody>";
$sql = "SELECT * FROM `" . NV_PREFIXLANG . "_" . $module_data . "` ORDER BY stt ASC";
$resuilt = $db->sql_query( $sql );
while ( $row = $db->sql_fetchrow( $resuilt ) )
{
$contents .= "
<tr>
<td>
" . $row['stt'] . "
</td>
<td>
" . $row['hoten'] . "
</td>
<td>
" . date( "d/m/Y", $row['ngaysinh'] ) . "
</td>
<td>
" . $row['diachi'] . "
</td>
</tr>";
}
$contents .= "</tbody></table>";

include ( NV_ROOTDIR . "/includes/header.php" );
echo nv_site_theme( $contents );
include ( NV_ROOTDIR . "/includes/footer.php" );
?>


Đoạn code trên cũng tương tự như file main.php trong admin, cũng đọc dữ liệu và xuất ra.

Ta vừa hoàn thành xong một module đơn giản để thực hiện việc quản lí học sinh trong lớp
qua hai file main.php ta lại thấy trùng nhau ở doạn này:
Mã: Chọn hết
$sql = "SELECT * FROM `" . NV_PREFIXLANG . "_" . $module_data . "` ORDER BY stt ASC";
$resuilt = $db->sql_query( $sql );
while ( $row = $db->sql_fetchrow( $resuilt ) )

Để tối ưu hóa hơn, bây giờ ta sẽ gộp hai đoạn đó thành một. Như vậy tiết kiệm được một chút tài nguyên (với những module lớn thì tiết kiệm đáng kể). Giải pháp để thực hiện là viết class riêng hoặc dùng function riêng. Mình sẽ giới thiệu cách dùng function đặt trong một file mở rộng ngoài những file bắt buộc. Ta thêm vào một file global.functions.php đặt ngang hàng với file action.php với nội dung như sau:
Mã: Chọn hết
<?php

/**
* @Project NUKEVIET-MUSIC
* @Author Phan Tan Dung (phantandung92@gmail.com)
* @copyright 2011
* @createdate 26/01/2011 09:17 AM
*/
if ( ! defined( 'NV_MAINFILE' ) ) die( 'Stop!!!' );

function getALLstudent( )
{
global $module_data, $db;

$data = array() ;
$result = $db->sql_query( "SELECT `stt`, `hoten`, `ngaysinh`, `diachi` FROM " . NV_PREFIXLANG . "_" . $module_data . " ORDER BY stt ASC" );
while ( list ( $stt, $hoten, $ngaysinh, $diachi ) = $db->sql_fetchrow($result) )
{
$data[] = array (
"stt" => $stt,
"hoten" => $hoten,
"ngaysinh" => date ( "d/m/Y", $ngaysinh ),
"diachi" => $diachi
);
}
return $data ;
}
?>

Đoạn code trên là một function getALLstudent( ). global $module_data, $db là để gọi vào các biến bên ngoài. Ví dụ này gọi vào biến $module_data có giá trị như tên của module, biến $db là class thao tác với CSDL. Tất cả thông tin học sinh sẽ được lưu dưới dạng mảng hai chiều và được trả về ở lệnh return.

Để sử dụng file trên thì ta mở file functions.php và admin.functions.php lên thêm vào dòng cuối cùng (phía trên ?>):
Mã: Chọn hết
require_once NV_ROOTDIR . "/modules/" . $module_name . '/global.functions.php';

Như vậy kể từ bây giờ file global.functions.php trực tiếp tham gia vào admin lẫn bên ngoài site, thiếu file này hoặc viết sai đều xuất hiện trang trăng.

Hãy sống là chính mình, bình thường nhưng không tầm thường.
#79697 gửi bởi hoaquynhtim99
Ngày 08 Tháng 02 2011 , 22:40
Tiếp tục sửa lại hai file main.php cho phù hợp như sau:
Trong admin:
Mã: Chọn hết
<?php
/**
* @Project NUKEVIET-MUSIC
* @Phan Tan Dung (phantandung92@gmail.com)
* @Copyright (C) 2011
* @Createdate 26-01-2011 14:43
*/

if ( ! defined( 'NV_IS_QUANLY_ADMIN' ) ) die( 'Stop!!!' );
$page_title = "Trang chính";

$contents = "
<table class=\"tab1\">
<thead>
<tr>
<td>
STT
</td>
<td>
Họ và tên
</td>
<td>
Ngày sinh
</td>
<td>
Địa chỉ
</td>
</tr>
</thead>
<tbody>";
$allSTD = getALLstudent( );
foreach ( $allSTD as $student )
{
$contents .= "
<tr>
<td>
" . $student['stt'] . "
</td>
<td>
" . $student['hoten'] . "
</td>
<td>
" . $student['ngaysinh'] . "
</td>
<td>
" . $student['diachi'] . "
</td>
</tr>";
}
$contents .= "</tbody></table>";

include (NV_ROOTDIR . "/includes/header.php");
echo nv_admin_theme($contents);
include (NV_ROOTDIR . "/includes/footer.php");
?>

Và bên ngoài site:
Mã: Chọn hết
<?php
/**
* @Project NUKEVIET-MUSIC
* @Author Phan Tan Dung
* @Copyright (C) 2011
* @Createdate 26/01/2011 10:26 AM
*/

if ( ! defined( 'NV_IS_MOD_QUANLY' ) ) die( 'Stop!!!' );
$page_title = $module_info['custom_title'];
$key_words = $module_info['keywords'];

$contents = '';
$contents = "
<table class=\"tab1\">
<thead>
<tr>
<td>
STT
</td>
<td>
Họ và tên
</td>
<td>
Ngày sinh
</td>
<td>
Địa chỉ
</td>
</tr>
</thead>
<tbody>";
$allSTD = getALLstudent( );
foreach ( $allSTD as $student )
{
$contents .= "
<tr>
<td>
" . $student['stt'] . "
</td>
<td>
" . $student['hoten'] . "
</td>
<td>
" . $student['ngaysinh'] . "
</td>
<td>
" . $student['diachi'] . "
</td>
</tr>";
}
$contents .= "</tbody></table>";

include ( NV_ROOTDIR . "/includes/header.php" );
echo nv_site_theme( $contents );
include ( NV_ROOTDIR . "/includes/footer.php" );
?>


Ta vừa hoàn thành xong phần "Sử dụng file php riêng"

Ngoài cấu trúc cở bản (các file, floder) bắt buộc các bạn có thể mở rộng tùy ý, có thể thêm bất kì floder, file nào tùy ý.

Tiếp theo ta sẽ làm việc với file lang (ngôn ngữ) để có thể mở rộng ra nhiều ngôn ngữ khác ngoài tiếng Việt. Tạo thư mục language ngang hàng với thư mục admin. Tạo file admin_vi.php và file vi.php nằm trong thư mục vừa tạo. Đây là fie ngôn ngữ tiếng việt, dùng trong admin thì bắt đầu bằng admin_ còn ngoài site thì tên file là tên của kí tự ngôn ngữ. Các kí tự ngôn ngữ các bạn tham khảo thêm ở module news.
Nội dung file admin_vi.php như sau:
Mã: Chọn hết
<?php
/**
* @Project NUKEVIET-MUSIC
* @Author Phan Tan Dung (phantandung92@gmail.com)
* @Language Vietnamese
* @Createdate Jan 26, 2011 11:30:02 AM
*/

if ( ! defined( 'NV_MAINFILE' ) ) { die( 'Stop!!!' ); }

$lang_translator['author'] = "Phan Tan Dung (phantandung92@gmail.com)";
$lang_translator['createdate'] = "04/03/2010, 15:22";
$lang_translator['copyright'] = "@Copyright (C) 2011";
$lang_translator['info'] = "";
$lang_translator['langtype'] = "lang_module";

$lang_module['main_page'] = "Trang chính";
$lang_module['stt'] = "STT";
$lang_module['name'] = "Họ và tên";
$lang_module['birthdate'] = "Ngày sinh";
$lang_module['address'] = "Địa chỉ";
$lang_module['add_student'] = "Thêm học sinh";
$lang_module['add_student_err_name'] = "Bạn chưa nhập tên học sinh";
$lang_module['add_student_err_bd'] = "Bạn chưa nhập ngày sinh của học sinh";
$lang_module['add_student_err_ar'] = "Bạn chưa nhập địa chỉ";
$lang_module['add_student_err_save'] = "Không thể lưu dữ liệu được";
$lang_module['add_student_info'] = "Thông tin học sinh mới";
$lang_module['save'] = "Lưu";
?>


Ta thấy có hia phần $lang_translator và $lang_module trong đó $lang_module là phần ngôn ngữ dùng cho module còn $lang_translator là thong tin tác giả, bản quyền, ngày dịch, ngôn ngữ dịch.....
Để sử dụng file ngôn ngữ thì sau khi tạo đến bước trên ta cần mở tất cả các file trong thư mục admin lên, thay tất cả các dòng chữ bằng $lang_module tương ứng. Sau khi thay ta được hai file main.php và add.php như sau:

main.php:
Mã: Chọn hết
<?php
/**
* @Project NUKEVIET-MUSIC
* @Phan Tan Dung (phantandung92@gmail.com)
* @Copyright (C) 2011
* @Createdate 26-01-2011 14:43
*/

if ( ! defined( 'NV_IS_QUANLY_ADMIN' ) ) die( 'Stop!!!' );
$page_title = $lang_module['main_page'];

$contents = "
<table class=\"tab1\">
<thead>
<tr>
<td>
" . $lang_module['stt'] . "
</td>
<td>
" . $lang_module['name'] . "
</td>
<td>
" . $lang_module['birthdate'] . "
</td>
<td>
" . $lang_module['address'] . "
</td>
</tr>
</thead>
<tbody>";
$allSTD = getALLstudent( );
foreach ( $allSTD as $student )
{
$contents .= "
<tr>
<td>
" . $student['stt'] . "
</td>
<td>
" . $student['hoten'] . "
</td>
<td>
" . $student['ngaysinh'] . "
</td>
<td>
" . $student['diachi'] . "
</td>
</tr>";
}
$contents .= "</tbody></table>";

include (NV_ROOTDIR . "/includes/header.php");
echo nv_admin_theme($contents);
include (NV_ROOTDIR . "/includes/footer.php");
?>


Add.php:
Mã: Chọn hết
<?php
/**
* @Project NUKEVIET-MUSIC
* @Phan Tan Dung (phantandung92@gmail.com)
* @Copyright (C) 2011
* @Createdate 26-01-2011 14:43
*/

if ( ! defined( 'NV_IS_QUANLY_ADMIN' ) ) die( 'Stop!!!' );
$page_title = $lang_module['add_student'];

$my_head = "<script type=\"text/javascript\" src=\"" . NV_BASE_SITEURL . "js/popcalendar/popcalendar.js\"></script>\n";
$my_head .= "<script type=\"text/javascript\" src=\"" . NV_BASE_SITEURL . "js/shadowbox/shadowbox.js\"></script>\n";
$my_head .= "<link rel=\"stylesheet\" type=\"text/css\" href=\"" . NV_BASE_SITEURL . "js/shadowbox/shadowbox.css\" />\n";
$my_head .= "<script type=\"text/javascript\">\n";
$my_head .= "Shadowbox.init({\n";
$my_head .= "});\n";
$my_head .= "</script>\n";

$contents = "";
$error = "";

$data = array();
$data['hoten'] = filter_text_input( 'hoten', 'post', '' );
$data['ngaysinh'] = filter_text_input( 'ngaysinh', 'post', '', 1, 10 );
unset( $m );
if ( preg_match( "/^([0-9]{1,2})\.([0-9]{1,2})\.([0-9]{4})$/", $data['ngaysinh'], $m ) )
{
$data['ngaysinh1'] = mktime( 0, 0, 0, $m[2], $m[1], $m[3] );
}
else
{
$data['ngaysinh1'] = "";
}

$data['diachi'] = $nv_Request->get_string( 'diachi', 'post', '' );

if ( ($nv_Request->get_int( 'add', 'post', 0 ) == 1) )
{
if ( $data['hoten'] == "" )
{
$error = $lang_module['add_student_err_name'];
}
elseif ( $data['ngaysinh'] == "" )
{
$error = $lang_module['add_student_err_bd'];
}
elseif ( $data['diachi'] == "" )
{
$error = $lang_module['add_student_err_ar'];
}
else
{
$sql = "SELECT `stt` FROM `" . NV_PREFIXLANG . "_" . $module_data . "` ORDER BY stt DESC LIMIT 0,1";
$resuilt = $db->sql_query( $sql );
list ( $currentstt ) = $db->sql_fetchrow( $resuilt );
$newstt = $currentstt + 1;

$query = "INSERT INTO `" . NV_PREFIXLANG . "_" . $module_data . "`
(
`id`, `stt`, `hoten`, `ngaysinh`, `diachi`
)
VALUES
(
NULL,
" . $newstt . ",
" . $db->dbescape( $data['hoten'] ) . ",
" . $data['ngaysinh1'] . ",
" . $db->dbescape( $data['diachi'] ) . "
)";
if ( $db->sql_query_insert_id( $query ) )
{
$db->sql_freeresult();
Header( "Location: " . NV_BASE_ADMINURL . "index.php?" . NV_NAME_VARIABLE . "=" . $module_name); die();
}
else
{
$error = $lang_module['add_student_err_save'];
}

}
}

if( $error )
{
$contents .= "<div class=\"quote\" style=\"width: 780px;\">\n
<blockquote class=\"error\">
<span>".$error."</span>
</blockquote>
</div>\n
<div class=\"clear\">
</div>";
}
$contents .="
<form method=\"post\">
<table class=\"tab1\">
<thead>
<tr>
<td colspan=\"2\">
" . $lang_module['add_student_info'] . "
</td>
</tr>
</thead>
<tbody>
<tr>
<td style=\"width: 150px;\">
" . $lang_module['name'] . "
</td>
<td style=\"background: #eee;\">
<input name=\"hoten\" style=\"width: 470px;\" value=\"" . $data['hoten'] . "\" type=\"text\">
</td>
</tr>
</tbody>
<tbody>
<tr>
<td>
" . $lang_module['birthdate'] . "
</td>
<td>
<input id=\"ngaysinh\" name=\"ngaysinh\" style=\"width: 470px;\" value=\"" . $data['ngaysinh'] . "\" type=\"text\" />
<img src=\"" . NV_BASE_SITEURL . "images/calendar.jpg\" style=\"cursor: pointer; vertical-align: middle;\" onclick=\"popCalendar.show(this, 'ngaysinh', 'dd.mm.yyyy', true);\" alt=\"\" height=\"17\" />
</td>
</tr>
</tbody>
<tbody>
<tr>
<td>
" . $lang_module['address'] . "
</td>
<td>
<input name=\"diachi\" style=\"width: 470px;\" value=\"" . $data['diachi'] . "\" type=\"text\" />
</td>
</tr>
</tbody>
<tr>
<td colspan=\"2\" align=\"center\" style=\"background: #eee;\">\n
<input name=\"confirm\" value=\"" . $lang_module['save'] . "\" type=\"submit\">\n
<input type=\"hidden\" name=\"add\" value=\"1\">\n
</td>\n
</tr>\n
</table>\n
</form>\n";

include (NV_ROOTDIR . "/includes/header.php");
echo nv_admin_theme($contents);
include (NV_ROOTDIR . "/includes/footer.php");
?>

Hãy sống là chính mình, bình thường nhưng không tầm thường.
#79700 gửi bởi hoaquynhtim99
Ngày 08 Tháng 02 2011 , 23:09
Tương tự cho bên ngoài site ta có file vi.php:
Mã: Chọn hết
<?php
/**
* @Project NUKEVIET-MUSIC
* @Author PHAN TAN DUNG (phantandung92@gmail.com)
* @Language Vietnamese
* @Createdate jan 1, 2011 11:30:02 AM
*/

if ( ! defined( 'NV_MAINFILE' ) ) { die( 'Stop!!!' ); }

$lang_translator['author'] = "PHAN TAN DUNG (phantandung92@gmail.com)";
$lang_translator['createdate'] = "01/01/2011, 15:22";
$lang_translator['copyright'] = "@Copyright (C) 2011";
$lang_translator['info'] = "";
$lang_translator['langtype'] = "lang_module";

$lang_module['stt'] = "STT";
$lang_module['name'] = "Họ và tên";
$lang_module['birthdate'] = "Ngày sinh";
$lang_module['address'] = "Địa chỉ";
?>

và sau khi thay ta cũng có file main.php:
Mã: Chọn hết
<?php
/**
* @Project NUKEVIET-MUSIC
* @Author Phan Tan Dung
* @Copyright (C) 2011
* @Createdate 26/01/2011 10:26 AM
*/

if ( ! defined( 'NV_IS_MOD_QUANLY' ) ) die( 'Stop!!!' );
$page_title = $module_info['custom_title'];
$key_words = $module_info['keywords'];

$contents = '';
$contents = "
<table class=\"tab1\">
<thead>
<tr>
<td>
" . $lang_module['stt'] . "
</td>
<td>
" . $lang_module['name'] . "
</td>
<td>
" . $lang_module['birthdate'] . "
</td>
<td>
" . $lang_module['address'] . "
</td>
</tr>
</thead>
<tbody>";
$allSTD = getALLstudent( );
foreach ( $allSTD as $student )
{
$contents .= "
<tr>
<td>
" . $student['stt'] . "
</td>
<td>
" . $student['hoten'] . "
</td>
<td>
" . $student['ngaysinh'] . "
</td>
<td>
" . $student['diachi'] . "
</td>
</tr>";
}
$contents .= "</tbody></table>";

include ( NV_ROOTDIR . "/includes/header.php" );
echo nv_site_theme( $contents );
include ( NV_ROOTDIR . "/includes/footer.php" );
?>

CHúng ta vừa hoàn thành xong phần làm việc với file lang bây giờ ta tiếp tục đến với phần sử dụng xtemplate.

xtemplate thực chất là một lớp (class) được xây dựng sẵn và luôn được tích hợp trong nukeviet. Để sử dụng nó ta cần quan tâm đến 3 phần như sau.
-- Gọi file tpl
-- lệnh $xtpl->assign
-- lệnh $xtpl->parse
-- lẹnh $xtpl->text( 'main' )

Để gọi ra một file tpl ta dùng như sau:
Mã: Chọn hết
$xtpl = new XTemplate( "managersong.tpl", NV_ROOTDIR . "/themes/" . $module_info['template'] . "/modules/" . $module_file );

Ta thấy có hai phần phân cách nhau bởi dấu phảy. phần trước chính là tên của file tpl là phần sau là đường dẫn đến file tpl đó. Các giá trị hằng, biến NV_ROOTDIR, $module_info['template'], $module_file các bạn tham khảo trong file mainfile.php. Hệ thông sẽ gọi ra file tpl ở theme bạn đang dùng nếu không tồn tại file đó thì sẽ tiếp tục tìm đến file đó trong theme default, admin_default nếu không tồn tại thì sẽ báo lỗi.

-> lệnh $xtpl->assign có chức năng gán giá trị cho biến trong xtpl. có thể là biến thông thường cũng có thể là mảng.
-> lệnh $xtpl->parse, $xtpl->text( 'main' ) ta sẽ hiểu thông qua ví dụ cụ thể.

Nhắc đến xtpl ta không thể không nhắc đến file theme.php (ngang hàng với file action.php). File này chứa tất cả cấu trúc xtpl. Nhưng không bắt buộc phải có nó, xtpl ta có thể dùng bất kì nơi nào.
Để cho nhất quán, bài học này chúng ta sẽ dùng đến nó.

Cấu trúc xtpl thông thường sẽ gọi các file có đuôi là tpl nhưng không nhất thiết phảo như thế, trong khi viết, để cho dễ dàng thao tác với chúng ta có thể chuyển lại chúng thành html và dùng các trình soạn thảo HTML để làm việc, sau khi hoàn tất ta sẽ chuyển trở lại thành tpl.

Bây giờ ta sẽ đi vào ví dụ cụ thể. Đầu tiên là phần admin.

Hãy sống là chính mình, bình thường nhưng không tầm thường.
#79706 gửi bởi hoaquynhtim99
Ngày 08 Tháng 02 2011 , 23:53
Tạo thư mục và file như sau:
themes/admin_default/modules/quanlihs/main.tpl. Nội dung file mail.tpl:
Mã: Chọn hết
<!-- BEGIN: main -->
<table class="tab1">
<thead>
<tr>
<td>
{LANG.stt}
</td>
<td>
{LANG.name}
</td>
<td>
{LANG.birthdate}
</td>
<td>
{LANG.address}
</td>
</tr>
</thead>
<tbody>
<!-- BEGIN: loop -->
<tr>
<td>
{DATA.stt}
</td>
<td>
{DATA.hoten}
</td>
<td>
{DATA.ngaysinh}
</td>
<td>
{DATA.diachi}
</td>
</tr>
<!-- END: loop -->
</tbody>
</table>
<!-- END: main -->


Sửa lại file main.php trong thư mục admin như sau:
Mã: Chọn hết
<?php
/**
* @Project NUKEVIET-MUSIC
* @Phan Tan Dung (phantandung92@gmail.com)
* @Copyright (C) 2011
* @Createdate 26-01-2011 14:43
*/

if ( ! defined( 'NV_IS_QUANLY_ADMIN' ) ) die( 'Stop!!!' );
$page_title = $lang_module['main_page'];

$allSTD = getALLstudent( );

$xtpl = new XTemplate("main.tpl", NV_ROOTDIR . "/themes/" . $global_config['module_theme'] . "/modules/" . $module_name);
$xtpl->assign('LANG', $lang_module);

foreach ( $allSTD as $student )
{
$xtpl->assign('DATA', $student);
$xtpl->parse('main.loop');
}
$xtpl->parse('main');
$contents = $xtpl->text('main');

include (NV_ROOTDIR . "/includes/header.php");
echo nv_admin_theme($contents);
include (NV_ROOTDIR . "/includes/footer.php");
?>

Nhìn vào hai đoạn code trên ta thấy rằng:
Cấu trúc file main.tpl không khác gì một file HTML. Cần chú ý đến thẻ <!-- BEGIN: main --> và <!-- END: main --> đây là dấu hiệu cho biết bắt đầu và kết thúc của lệnh $xtpl->parse('main'); đối với những lệnh $xtpl->parse tiếp theo đặt trong main thì ta sẽ sử dụng lệnh $xtpl->parse('main.loop');. Chúng đặt nối tiếp nhau bởi dấu ".". Để trả về nội dung HTML ta sử dụng lệnh $xtpl->text('main').
Lưu ý đối với những nội dung nằm ngoài <!-- BEGIN: main --> và <!-- END: main --> chúng sẽ được bỏ qua. Lợi dụng đặc tính này ta chuyển file tpl sang html và viết tương tự như viết HTML sau khi viết xong ta sẽ cắt bỏ tất cả những phần ngoài hai thẻ này đi còn lại phần cần thiết.

Đối với lệnh $xtpl->assign mà giá trị là biết đơn thì trong tpl chỉ cần gọi ra bằng {ten_bien} còn nếu là mảng thì để tham chiếu đến phần tử ta dùng {ten_bien.phan_tu}.

Vừa rồi là phần admin,tiếo theo tới bên ngoài site. Bên ngoài site ta càn tạo thêm một file theme.php (không nhất thiết phải có) lưu ngang hàng với file action.php với nội dung như sau:
Mã: Chọn hết
<?php

/**
* @Project NUKEVIET-MUSIC
* @Author Phan Tan Dung (phantandung92@gmail.com)
* @copyright 2011
* @createdate 26/01/2011 09:17 AM
*/
if ( ! defined( 'NV_IS_MOD_QUANLY' ) ) die( 'Stop!!!' );

function nv_quanly_main ( $data )
{
global $module_file, $lang_module, $module_info;

$xtpl = new XTemplate( "main.tpl", NV_ROOTDIR . "/themes/" . $module_info['template'] . "/modules/" . $module_file );
$xtpl->assign( 'LANG', $lang_module );

foreach ( $data as $st )
{
$xtpl->assign( 'DATA', $st );
$xtpl->parse( 'main.loop' );
}

$xtpl->parse( 'main' );
return $xtpl->text( 'main' );
}

?>


file theme.php thực chất là các function làm nhiệm vụ thực hiện thao tác với xtpl, nếu không cần file này ta có thển thục hiện ngay trong file main.php.

Tiếp tục sửa lại file main.php như sau:
Mã: Chọn hết
<?php
/**
* @Project NUKEVIET-MUSIC
* @Author Phan Tan Dung
* @Copyright (C) 2011
* @Createdate 26/01/2011 10:26 AM
*/

if ( ! defined( 'NV_IS_MOD_QUANLY' ) ) die( 'Stop!!!' );
$page_title = $module_info['custom_title'];
$key_words = $module_info['keywords'];

$allSTD = getALLstudent( );

$contents = nv_quanly_main( $allSTD );

include ( NV_ROOTDIR . "/includes/header.php" );
echo nv_site_theme( $contents );
include ( NV_ROOTDIR . "/includes/footer.php" );
?>


Làm tới đây ta vào module quanlyhs bên ngoài sile sẽ bị lỗi như sau:
[XTemplate]

* [] (C:/wamp/www/nukeviet3/themes/default/modules/quanlihs\main.tpl) does not exist

* parse: blockname [main.loop] does not exist

* parse: blockname [main.loop] does not exist

* parse: blockname [main.loop] does not exist

* parse: blockname [main] does not exist

Đó là lỗi không tồn tại file main.tpl. Ta cần thêm file main.tpl vào themes/theme_dang_dung/modules/quanlyhs/main.tpl:
Mã: Chọn hết
<!-- BEGIN: main -->
<table class="tab1">
<thead>
<tr>
<td>
{LANG.stt}
</td>
<td>
{LANG.name}
</td>
<td>
{LANG.birthdate}
</td>
<td>
{LANG.address}
</td>
</tr>
</thead>
<tbody>
<!-- BEGIN: loop -->
<tr>
<td>
{DATA.stt}
</td>
<td>
{DATA.hoten}
</td>
<td>
{DATA.ngaysinh}
</td>
<td>
{DATA.diachi}
</td>
</tr>
<!-- END: loop -->
</tbody>
</table>
<!-- END: main -->

Hãy sống là chính mình, bình thường nhưng không tầm thường.
#79713 gửi bởi hoaquynhtim99
Ngày 09 Tháng 02 2011 , 00:27
Vừa rồi ta đã hoàn thành xong phần xtemplate. Với phần như trên ta chỉ đơn giản dùng CSS có sẵn. Nếu muốn tùy chỉnh giao diện cho module bạn hãy tạo file CSS có tên là tên của module và đặt vào thư mục css của theme đang dùng, muốn dùng thêm phần hình ảnh thì các bạn tạo thư mục có tên là tên của module đặt vào thư mục images của theme đang dùng chứa các ảnh. Không nhất thiết phải đặt các ảnh vào thư mục như vậy. Một lý do để đặt các ảnh như vậy là khi đóng gói module hệ thống sẽ đóng gói tất cả các ảnh trong thư mục này luôn. ;)
Tiếp theo ta sẽ tới phần mở rộng thêm thông tin module.

-- Mở rộng thông tin trong admin phần "thông tin từ các module"
Thêm file siteinfo.php đặt ngang hàng với file action.php nội dung như sau:
Mã: Chọn hết
<?php

/**
* @Project NUKEVIET-MUSIC
* @Author Phan Tan Dung (phantandung92@gmail.com)
* @copyright 2011
* @createdate 26/01/2011 10:10 AM
*/

if ( ! defined( 'NV_IS_FILE_SITEINFO' ) ) die( 'Stop!!!' );

$lang_siteinfo = nv_get_lang_module( $mod );

// So hoc sinh
list( $number ) = $db->sql_fetchrow( $db->sql_query( "SELECT COUNT(*) as number FROM `" . NV_PREFIXLANG . "_" . $mod_data . "`" ) );
if ( $number > 0 )
{
$siteinfo[] = array(
'key' => $lang_siteinfo['siteinfo_num_student'] , 'value' => $number
);
}

?>
đoạn code này đơn giản là tính số dòng trong table => số học sinh và gán thêm bào biến $siteinfo[]. Để có các thông tin khác bạn cứ gán vô biến $siteinfo[] là được.
Thêm
Mã: Chọn hết
$lang_module['siteinfo_num_student'] = "Tổng số học sinh";
vào file admin_vi.php để có thêm file ngôn ngữ.

Bây giờ các bạn vào phần quản trị sẽ thấy thêm tại Thông tin từ các module có thêm:
Module Nội dung Giá trị
Quản lí Tổng số học sinh 3
(tùy theo module của bạn)

-- Thêm RSS cho module:
Thêm file rssdata.php đặt cùng cấp với file action.php với nội dung như sau:
Mã: Chọn hết
<?php

/**
* @Project DOCUMENT
* @Author Phan Tan Dung (phantandung92@gmail.com)
* @copyright 2011
* @createdate 01/02/2011 09:47
*/

if ( ! defined( 'NV_IS_MOD_RSS' ) ) die( 'Stop!!!' );

$rssarray = array();

$result2 = $db->sql_query( "SELECT * FROM " . NV_PREFIXLANG . "_" . $module_data . " ORDER BY stt" );
while ( $row = $db->sql_fetchrow( $result2 ) )
{
$rssarray[$row['id']] = array(
'catid' => $row['id'], 'parentid' => 0, 'title' => $row['hoten'], 'link' => NV_BASE_SITEURL . "index.php?" . NV_LANG_VARIABLE . "=" . NV_LANG_DATA . "&amp;" . NV_NAME_VARIABLE . "=" . $module_title . "&amp;" . NV_OP_VARIABLE . "=rss/" . $row['id']
);
}

?>

Code trên lấy thông tin tất cả các học sinh.
Tiếp tục thêm file rss.php đặt vào thư mục funcs với nội dung :
Mã: Chọn hết
<?php

/**
* @Project DOCUMENT
* @Author Phan Tan Dung (phantandung92@gmail.com)
* @copyright 2011
* @createdate 01/02/2011 09:47
*/

if ( ! defined( 'NV_IS_MOD_QUANLY' ) ) die( 'Stop!!!' );

$channel = array();
$items = array();

$channel['title'] = $global_config['site_name'] . ' RSS: ' . $module_info['custom_title'];
$channel['link'] = NV_MY_DOMAIN . NV_BASE_SITEURL . "index.php?" . NV_LANG_VARIABLE . "=" . NV_LANG_DATA . "&amp;" . NV_NAME_VARIABLE . "=" . $module_name;
$channel['atomlink'] = NV_MY_DOMAIN . NV_BASE_SITEURL . "index.php?" . NV_LANG_VARIABLE . "=" . NV_LANG_DATA . "&amp;" . NV_NAME_VARIABLE . "=" . $module_name . "&amp;" . NV_OP_VARIABLE . "=rss";
$channel['description'] = $global_config['site_description'];

$id = isset( $array_op[1] ) ? $array_op[1] : 0;

if ( $id > 0 )
{
$sql = "SELECT * FROM `" . NV_PREFIXLANG . "_" . $module_data . "` WHERE `id`=" . $id;
$result = $db->sql_query( $sql );
$row = $db->sql_fetchrow( $result );

$channel['title'] = $global_config['site_name'] . ' RSS: ' . $module_info['custom_title'] . ' - ' . c;
$channel['link'] = NV_MY_DOMAIN . NV_BASE_SITEURL . "index.php?" . NV_LANG_VARIABLE . "=" . NV_LANG_DATA . "&amp;" . NV_NAME_VARIABLE . "=" . $module_name . "&amp;cat=" . $row['hoten'];
$channel['description'] = $row['hoten'];

}
if ( $module_info['rss'] )
{
$rimages = "";
$items[] = array(
'title' => $row['hoten'],
'link' => NV_MY_DOMAIN . NV_BASE_SITEURL . "index.php?" . NV_LANG_VARIABLE . "=" . NV_LANG_DATA . "&amp;" . NV_NAME_VARIABLE . "=" . $module_name,
'guid' => $module_name . '_' . $id,
'description' => $rimages . $row['diachi'],
'pubdate' => 0
);
}

nv_rss_generate( $channel, $items );
die();

?>

Đây chỉ là cách viết rss cơ bản, vì module này không thích hợp cho rss. Cách viết chi tiết hơn các bạn tham khảo ở module news.
Làm đến đây các bạn cần phải xóa module đi và cài lại để hệ thông nhận ra là module này có chức năng RSS. Để không mất đi dữ liệu mà các bạn nhập thì các bạn đổi tên file action.php rồi cài lại sau đó lại đổi tên trở lại thành action.php.

Ta vừa xog các phần mở rộng RSS, siteinfo

Hãy sống là chính mình, bình thường nhưng không tầm thường.
#79725 gửi bởi hoaquynhtim99
Ngày 09 Tháng 02 2011 , 02:12
Tiếp theo chúng ta sẽ đến phần sửa dụng javascript và ajax cho module. Nukeviet đã tích hợp sẵn cho chúng ta jquery cho nên bạn có thể dùng nó ở bất kì nơi đâu. Để dùng java bạn hãy cho nó vào file admin.js hoặc user.js. admin.js thì dùng trong admin còn user.js thì dùng ngoài site. Mình sẽ ví dụ với các bạn cách dùng trong admin còn ngoài site thì các bạn làm tương tự.
Tạo thêm thư mục js ngang hàng với thư mục funcs. Thêm vào đó file admin.js
Bạn cũng có thể dùng trực tiếp trong file tpl như sau:
Ví dụ này mình sẽ trình bày cách dùng ajax để xóa một học sinh.
Đầu tiên ta cần thêm funcs mới vào thư mục là del.php. ta cần chấp nhận thêm funcs này bằng cách mở file admin.functions.php, tại dòng thứ 14 sửa lại thành :
Mã: Chọn hết
$allow_func = array('main', 'add', 'del');

tiếp tục thêm file del.php với nội dung như sau:
Mã: Chọn hết
<?php
/**
* @Project NUKEVIET-MUSIC
* @Author Phan Tan Dung (phantandung92@gmail.com)
* @Copyright (C) 2011
* @Createdate 26/01/2011 09:05 AM
*/
if(!defined('NV_IS_QUANLY_ADMIN')) { die('Stop!!!'); }

$result = false;
$id = $nv_Request->get_int('id', 'post,get', 0);

if( $id > 0 )
{
$sql = "DELETE FROM `" . NV_PREFIXLANG . "_" . $module_data ."` WHERE `id`=" . $id;
$result = $db->sql_query( $sql );
}

if( $result )
{
echo $lang_module['del_success'];
}
else
{
echo $lang_module['del_error'];
}
?>

funcs này rất đơn giản là lấy id được gửi tới và xóa đi hoc sinh có id này. Nếu xóa thành công thì xuất ra $lang_module['del_success'] ngược lại thì xuất $lang_module['del_error']
Ta thêm hai biến ngôn ngữ mới này cho file ngôn ngữ đồng thời thêm tiếp các biến ngôn ngữ cần dùng về sau. Mở file admin_vi.php thêm vào:
Mã: Chọn hết
$lang_module['del_success'] = "Xóa thành công";
$lang_module['del_error'] = "Xóa thất bại";
$lang_module['del'] = "Xóa";
$lang_module['del_cofirm'] = "Bạn có chắc chắn muốn xóa không?";

Tiếp theo ta khởi tạo link xóa một học sinh bằng cách mở file main.php thêm vào dòng thứ 19:
Mã: Chọn hết

$xtpl->assign('URL_DEL', "index.php?" . NV_NAME_VARIABLE . "=" . $module_name . "&" . NV_OP_VARIABLE . "=del&id=");
$xtpl->assign('URL_DEL_BACK', "index.php?" . NV_NAME_VARIABLE . "=" . $module_name );

Tiếp tục mở file main.php (admin) lên sửa lại thành:
Mã: Chọn hết
<!-- BEGIN: main -->
<table class="tab1">
<thead>
<tr>
<td>
{LANG.stt}
</td>
<td>
{LANG.name}
</td>
<td>
{LANG.birthdate}
</td>
<td>
{LANG.address}
</td>
<td></td>
</tr>
</thead>
<tbody>
<!-- BEGIN: loop -->
<tr>
<td>
{DATA.stt}
</td>
<td>
{DATA.hoten}
</td>
<td>
{DATA.ngaysinh}
</td>
<td>
{DATA.diachi}
</td>
<td align="center">
<span class="delete_icon">
<a class='delfile' href="{URL_DEL}{DATA.id}">{LANG.del}</a>
</span>
</td>
</tr>
<!-- END: loop -->
</tbody>
</table>
<script type='text/javascript'>
$(function()
{
$('a[class="delfile"]').click(function(event)
{
event.preventDefault();
if (confirm("{LANG.del_cofirm}"))
{
var href = $(this).attr('href');
$.ajax(
{
type: 'POST',
url: href,
data: '',
success: function(data)
{
alert(data);
window.location = '{URL_DEL_BACK}';
}
});
}
});
});
</script>

<!-- END: main -->


Nhìn vào hai doạn code trên ta thấy phần function getALLstudent( ) thiếu mất lấy ra id học sinh ta lại mỏ file global.functions.php lên sửa lại thành:
Mã: Chọn hết
<?php

/**
* @Project NUKEVIET-MUSIC
* @Author Phan Tan Dung (phantandung92@gmail.com)
* @copyright 2011
* @createdate 26/01/2011 09:17 AM
*/
if ( ! defined( 'NV_MAINFILE' ) ) die( 'Stop!!!' );

function getALLstudent( )
{
global $module_data, $db;

$data = array() ;
$result = $db->sql_query( "SELECT `id`, `stt`, `hoten`, `ngaysinh`, `diachi` FROM " . NV_PREFIXLANG . "_" . $module_data . " ORDER BY stt ASC" );
while ( list ( $id, $stt, $hoten, $ngaysinh, $diachi ) = $db->sql_fetchrow($result) )
{
$data[] = array (
"id" => $id,
"stt" => $stt,
"hoten" => $hoten,
"ngaysinh" => date ( "d/m/Y", $ngaysinh ),
"diachi" => $diachi
);
}
return $data ;
}
?>

Như vậy ta đã hoàn thành việc sử dụng ajax cho module

Hãy sống là chính mình, bình thường nhưng không tầm thường.
#79729 gửi bởi hoaquynhtim99
Ngày 09 Tháng 02 2011 , 02:59
Tiếp theo ta sẽ đến với một phần nâng cao hơn: Sử dụng các lớp (class) có sẵn. Thư mục chứa class

Class không có gì là quá phức tạp, nó thực chất ra là một tập hợp nhiều function liê kết với nhau để làm một công liệc cụ thể nào đó.
Hiện tại nukeviet3.1 có các class tích hợp sẵn như sau:
- array2xml.class.php: xử lí file xml : đọc, xuất....
- download.class.php: thao tác trong việc download file:
- error.class.php
... tất cả trong thư mục includes/class
Mình chỉ hướng dẫn các bạn dùng một số class thường dùng thôi.
Đầu tiên là :

download.class.php. NẾu mở file này lên bạn sẽ thấy đoạn này:
Mã: Chọn hết
/**
* include("download.class.php"); // load the class file

* $fichier = new download("example.zip"); // use the original file name, disallow resuming, no speed limit
* $fichier = new download("example.zip","My Example.zip") ; // rename the file, disallow resuming, no speed limit
* $fichier = new download("example.zip","My Example.zip",true) ; // rename the file, allow resuming, no speed limit
* $fichier = new download("example.zip","My Example.zip",true,80) ; // rename the file, allow resuming, speed limit 80ko/s

* $fichier->download_file();
*/


Đây chính là phần hướng dẫn dùng nó. Dùng class nào các bạn cũng thực hiện các bước như sau:
- Gọi ra class. Bạn có thể dùng include hoặc require_once
- Nhập các thông số khởi tạo
- Gọi ra function thực hiên.

Ví dụ để download một file demo.zip ta làm như sau:
- Gọi ra class download:
Mã: Chọn hết
require_once ( NV_ROOTDIR . '/includes/class/download.class.php' );

- Nhập thông số:
Mã: Chọn hết
$download = new download( NV_ROOTDIR . "/" . NV_UPLOADS_DIR . "/demo.zip", NV_ROOTDIR . "/" . NV_UPLOADS_DIR , "demo.zip", true);

- và down về $download->download_file();
Trong phần nhập thông sô các bạn chú ý như phần hướng dẫn của class:
* $fichier = new download("example.zip"); // use the original file name, disallow resuming, no speed limit
* $fichier = new download("example.zip","My Example.zip") ; // rename the file, disallow resuming, no speed limit
* $fichier = new download("example.zip","My Example.zip",true) ; // rename the file, allow resuming, no speed limit
* $fichier = new download("example.zip","My Example.zip",true,80) ; // rename the file, allow resuming, speed limit 80ko/s
Chịu khó đọc tiếng anh xí nhé :D

DÙNG CLASS image.class.php
Các bạn mở file này lê cũng sẽ thấy hướng dẫn
Mã: Chọn hết
/**
* if(!file_exists(NV_ROOTDIR."/uploads/1237974658.jpg")) {
* @require_once(NV_ROOTDIR."/includes/class/image.class.php");
* $image = new image(NV_ROOTDIR."/images/logo.png", $max_width,$max_height);
* $image->resizePercent(200);
* $image->cropFromCenter(150,200);
* $image->cropFromLeft(50,50,300,300);
* $image->addstring("nguyenanh tu", 'right', 'bottom', "", 8);
* $image->addlogo(NV_ROOTDIR.'/images/logo.png','left','top');
* $image->resizePercent(30);
* $image->rotate(45);
* $image->reflection();
* $image->show();
* $image->save(NV_ROOTDIR.'/'.NV_TEMP_DIR.'/');
* $image->close();
* print_r($image->create_Image_info);
* exit;
* }
*/

Cách dùng cũng tương tự:
đầu tiên kiểm tra xem file tồn tại hay không: if(!file_exists(NV_ROOTDIR."/uploads/1237974658.jpg")) {
nếu tồn tại thì gọi ra class @require_once(NV_ROOTDIR."/includes/class/image.class.php");
Nhập thông sô : $image = new image(NV_ROOTDIR."/images/logo.png", $max_width,$max_height); gồm đường dẫn tới file ảnh, chiều rộng, cao tối đa.
Tiếp theo là phần thao tác:
* $image->resizePercent(200); Chỉnh sửa kích thước theo thông sô phần trăm
* $image->cropFromCenter(150,200); Cắt ảnh từ chính giữa
* $image->cropFromLeft(50,50,300,300); Cắt từ bên trái
* $image->addstring("nguyenanh tu", 'right', 'bottom', "", 8); Thêm vào ảnh dòng chữ nguyenanhtu. HIHI BÁC ANH TU CHƠI GHÊ QUÁ. class do bác viết nên chơi luôn string là nguyenanh tu :))
* $image->addlogo(NV_ROOTDIR.'/images/logo.png','left','top'); Thêm vào ảnh logo
* $image->resizePercent(30);
* $image->rotate(45); xoay ảnh 45 độ
* $image->reflection();
* $image->show();
* $image->save(NV_ROOTDIR.'/'.NV_TEMP_DIR.'/'); Lưu ảnh lại
* $image->close();
* print_r($image->create_Image_info);

Tương tự với các cách như trên các bạn có thể dùng bất kì class nào.

Hãy sống là chính mình, bình thường nhưng không tầm thường.