Xoops模块开发应用实例1
导航: 上一页 | 首页 | DedeCMS | 帝国CMS | Drupal | PHPCMS | PHP168 | Joomla | PowerEasy | SupeSite
xoops_version.php[ ]
xoops_version.php是XOOPS模块的基本要素,XOOPS系统依据/modules文件夹中的每个子文件夹是否包含xoops_version.php文件来判断该文件夹是否是XOOPS模块。
本例的文件夹结构如下:
/modules/moddevversion /images /logo.png /xoops_version.php
这个子文件夹中包含xoops_version.php,内容如下所示:
/modules/moddevversion/xoops_version.php <?php $modversion['name'] = "模块开发 - xoops_version.php"; $modversion['version'] = 0.01; $modversion['description'] = "演示xoops_version.php的基本要素"; $modversion['author'] = <<<AUTHOR 胡争辉 QQ: 443089607 QQMail: hu_zhenghui@qq.com GTalk: huzhengh GMail: huzhengh@gmail.com Skype: huzhenghui" AUTHOR; $modversion['credits'] = ""; $modversion['license'] = "版权所有"; $modversion['image'] = "images/logo.png"; $modversion['dirname'] = "moddevversion"; ?>
在访问“系统管理”的“模块管理”页面时,将看到出现一个未安装模块,如图 1-1 未安装模块所示。
虽然这个模块仅有一个xoops_version.php文件,但也能被XOOPS系统识别,能够查看模块信息、安装、更新、卸载该模块。单击查看模块信息按钮,将弹出查看模块信息窗口,如图1-2模块信息所示。
单击安装按钮,出现如图1-3点击按钮安装此模块所示确认界面。
单击“安装”按钮后,XOOPS系统将安装该模块,并显示安装过程,如图1-3模块安装过程所示。
单击“回到模块管理页面”链接,将看到该模块已被安装在系统中,如图1-5模块被成功安装所示。
如果需要卸载该模块,则首先需要停止使用该模块,取消该模块的“激活”复选框,然后单击“提交”按钮,如图1-6确认停止使用所示。
单击“提交”按钮,将解除该模块的启动状态,并显示相应的提示信息,如图1-7解除启动状态所示。
单击“回到模块管理页面”链接,可以看到模块已停用,如图1-8模块已停用所示。
模块被停用后,可以看到在操作列中新出现了卸载按钮,单击卸载按钮,出现如图1-9确认卸载信息对话框。
单击“是”按钮即可卸载该模块,并出现卸载成功信息,如图1-10卸载成功所示。
卸载成功单击“回到模块管理页面”链接,又将回到如图1-1未安装模块状态。
下面详细讲解本例中xoops_version.php文件各行代码的含义。
<?php $modversion['name'] = "模块开发 - xoops_version.php"; //这行代码用于声明模块的名称。 $modversion['version'] = 0.01; //这行代码用于声明模块的版本,XOOPS中模块的版本采用十进制浮点数表示。 说明:XOOPS模块的版本号格式与PHP标准的版本号格式不同,PHP标准的版本号请参考http://www.php.net/manual/zh/function.version-compare.php $modversion['description'] = "演示xoops_version.php的基本要素"; //这行代码是模块的描述信息。 $modversion['author'] = <<<AUTHOR 胡争辉 QQ: 443089607 QQMail: hu_zhenghui@qq.com GTalk: huzhengh GMail: huzhengh@gmail.com Skype: huzhenghui" AUTHOR; //这几行代码是模块的作者信息。 说明:模块的作者信息不支持HTML标记。 $modversion['credits'] = ""; //这行代码是模块的相关贡献人员信息。 $modversion['license'] = "版权所有"; //这行代码是模块的版权说明。 $modversion['image'] = "images/logo.png"; //这行代码是模块的图标路径,其中路径是相对于模块目录的路径,在本例中,模块目录的路径为/modules/moddevversion/,图标的相对路径为images/logo.png,图标 相对于XOOPS系统的路径即是/modules/moddevversion/images/logo.png。 注意:XOOPS系统的部分后台功能会判断是否设置了图标,因此应保证设置该项,并且存在该图片。 $modversion['dirname'] = "moddevversion"; //这行代码是模块的目录名,在本例中,模块目录的路径为/modules/moddevversion/,所以目录名就是moddevversion。 ?>
模块普通页面[ ]
网站通过页面与访问者交互,XOOPS系统支持两种页面--普通页面和管理页面,在XOOPS管理区,管理员可以为每个模块的普通页面和管理页面分别设置权限。如果设置显示系统导航区块,在系统导航区块中,还会显示在xoops_version.php文件中定义的子菜单。接下来,本例讲解普通页面的制作。
本例的文件夹结构如下:
/modules/moddevpage /images /logo.png /index.php /subpage1.php /subpage2.php /xoops_version.php
其中xoops_version.php的内容如下:
/modules/moddevpage/xoops_version.php <?php $modversion['name'] = "模块开发 - 模块普通页面"; $modversion['version'] = 0.01; $modversion['description'] = "演示普通页面的制作"; $modversion['author'] = <<<AUTHOR 胡争辉 QQ: 443089607 QQMail: hu_zhenghui@qq.com GTalk: huzhengh GMail: huzhengh@gmail.com Skype: huzhenghui" AUTHOR; $modversion['credits'] = ""; $modversion['license'] = "版权所有"; $modversion['image'] = "images/logo.png"; $modversion['dirname'] = "moddevpage"; $modversion["hasMain"] = 1; $modversion["sub"][0]["name"] = "子页面 1"; $modversion["sub"][0]["url"] = "subpage1.php"; $modversion["sub"][1]["name"] = "子页面 2"; $modversion["sub"][1]["url"] = "subpage2.php"; ?>
在这个文件中增加了hasMain参数。
$modversion["hasMain"] = 1;
这个参数代表该模块包括普通页面,因此在安装该模块后,系统导航区块中会显示相应的菜单项,如图1-11导航菜单中的菜单项所示。
同时在管理区的群组管理中,可以为每个群组分别设置是否能访问该模块。如1-12模块使用权限所示。
为了支持XOOPS系统管理模块使用权限,需要在页面中包含/mainfile.php这个文件,例如本例中的index.php文件的内容如下。
/modules/moddevpage/index.php <?php require_once dirname(__FILE__)."/../../mainfile.php"; include XOOPS_ROOT_PATH."/header.php"; ?> Index <?php include XOOPS_ROOT_PATH."/footer.php"; ?>
mainfile.php文件是模块普通页面必要的包含文件,后面所包含的header.php和footer.php用于显示页面,包括显示区块等相关功能。如果普通页面不需要借助XOOPS系统来处理页面显示内容,那么只需要包含mainfile.php,不需要包含header.php和 footer.php,在header.php和footer.php中间的内容将显示为页面的主体部分,如图1-13模块普通页面所示。
XOOPS系统将自动处理页面的页眉、页脚以及区块,并把header.php和footer.php中间输出的内容自动组合在页面的主体部分。
在图1-13模块普通页面中,"模块开发 -> 模块普通页面"的下面出现了两个缩进的菜单项“子页面1”和“子页面 2”,这两个菜单项是XOOPS系统支持的子菜单功能,定义在xoops_version.php文件中。
<?php $modversion["sub"][0]["name"] = "子页面 1"; $modversion["sub"][0]["url"] = "subpage1.php"; $modversion["sub"][1]["name"] = "子页面 2"; $modversion["sub"][1]["url"] = "subpage2.php"; ?>
键值“sub”代表子菜单,下面的每一项都代表一个菜单项,菜单项的索引从0开始,每个菜单项包括两个键值“name”和“url”,其中“name”的值为菜单项显示的文字,“url”的值为菜单项的地址,其中地址是相对于模块目录的地址。
菜单项页面的代码格式与index.php相同,例如“子页面 1”的代码为。
/modules/moddevpage/subpage1.php <?php require_once dirname(__FILE__)."/../../mainfile.php"; include XOOPS_ROOT_PATH."/header.php"; ?> Sub Page 1 <?php include XOOPS_ROOT_PATH."/footer.php"; ?>
输出效果与图1-13模块普通页面类似,也会显示本模块的子菜单项。如图1-14子页面1所示。
模块管理页面[ ]
除了普通页面,XOOPS系统还支持模块管理页面,模块管理页面与模块普通页面类似,也支持子菜单。下面本例讲解管理页面的制作。
本例的文件夹结构如下:
/modules/moddevadmin /admin /admin1.php /admin2.php /index.php /menu.php /images /xoops_version.php
其中xoops_version.php的内容如下:
/modules/moddevadmin/xoops_version.php <?php $modversion['name'] = "模块开发 - 模块管理页面"; $modversion['version'] = 0.01; $modversion['description'] = "演示管理页面的制作"; $modversion['author'] = <<<AUTHOR 胡争辉 QQ: 443089607 QQMail: hu_zhenghui@qq.com GTalk: huzhengh GMail: huzhengh@gmail.com Skype: huzhenghui" AUTHOR; $modversion['credits'] = ""; $modversion['license'] = "版权所有"; $modversion['image'] = "images/logo.png"; $modversion['dirname'] = "moddevadmin"; $modversion["hasAdmin"] = 1; $modversion["adminindex"] = "admin/index.php"; $modversion["adminmenu"] = "admin/menu.php"; ?>
其中hasAdmin参数表示该模块包括管理页面。
$modversion["hasAdmin"] = 1;
adminindex参数表示该模块管理页面的首页地址,该地址为相对于模块根目录的地址。
$modversion["adminindex"] = "admin/index.php";
安装该模块后,在管理区的左侧会显示该模块的图标,表示该模块具有管理页面,如图1-15模块管理图标所示。
在管理区的群组管理中,可以为每个群组分别设置是否能管理该模块。如图1-16模块管理权限所示。
为了支持XOOPS系统管理模块管理权限,需要在页面中包含/include/cp_header.php这个文件,例如本例中的admin/index.php文件的内容如下。
/modules/moddevadmin/admin/index.php <?php require_once dirname(__FILE__)."/../../../include/cp_header.php"; xoops_cp_header(); ?> Admin Index <?php xoops_cp_footer(); ?>
/include/cp_header.php是模块管理页面必要的包含文件,提供后面所调用的xoops_cp_header()和 xoops_cp_footer()等函数。xoops_cp_header()和xoops_cp_footer()用于显示管理区页面,包括页眉、页脚、模块菜单等相关功能。如果管理页面不需要显示内容,那么只需要包含/include/cp_header.php,不需要调用 xoops_cp_header()和xoops_cp_footer()。在xoops_cp_header()和xoops_cp_footer() 中间的内容将显示为管理页面的主体部分,如图1-17模块管理首页所示。
XOOPS系统将自动处理管理区页面的页眉、页脚以及模块菜单,并把xoops_cp_header()和xoops_cp_footer()中间输出的内容自动组合在管理区页面的主体部分。
当鼠标移动到模块图标上的时候,页面将自动出现一个该模块管理区的子菜单,如图1-18模块管理子菜单所示。
其中包括了三个菜单项“模块管理页面 -> 首页”、“模块管理页面 -> 管理页面 1”和“模块管理页面 -> 管理页面 2”,这三个菜单项是XOOPS系统支持的管理区子菜单功能。为了显示管理区子菜单,首先需要在xoops_version.php文件中定义管理区子菜单的描述文件。
$modversion["adminmenu"] = "admin/menu.php";
该文件的内容如下。
/modules/moddevadmin/admin/menu.php <?php $adminmenu[0]['title'] = "模块管理页面 - 首页"; $adminmenu[0]['link'] = "admin/index.php"; $adminmenu[1]['title'] = "模块管理页面 - 管理页面 1"; $adminmenu[1]['link'] = "admin/admin1.php"; $adminmenu[2]['title'] = "模块管理页面 - 管理页面 2"; $adminmenu[2]['link'] = "admin/admin2.php"; ?>
变量$adminmenu代表管理区子菜单,下面的每一项都代表一个菜单项,菜单项的索引从0开始,每个菜单项包括两个键值“title”和“link”,其中“title”的值为菜单项显示的文字,“link”的值为菜单项的地址,其中地址是相对于模块目录的地址。
管理区菜单项页面的代码格式与admin/index.php相同,例如“模块管理页面-管理页面1”的代码为。
/modules/moddevadmin/admin/admin1.php <?php require_once dirname(__FILE__)."/../../../include/cp_header.php"; xoops_cp_header(); ?> Admin 1 <?php xoops_cp_footer(); ?>
输出效果与图1-17模块管理首页类似,当鼠标停留在模块图标上方时,也会显示模块的管理菜单,如图1-19模块管理页面1所示。
数据表[ ]
模块除了包含页面,通常还会包含保存在数据库中的数据表,在XOOPS系统中,为模块的数据库访问提供方便的封装,安装模块时将自动创建指定的数据表以及记录,在卸载模块时将自动删除指定的数据表。在安装的过程中,XOOPS为数据表自动添加表前缀。为了便于访问数据表,XOOPS还提供了相应的类。接下来本例将讲解数据表的安装、卸载以及访问。
本例的文件夹结构如下:
/modules/moddevsql /images /logo.png /sql /mysql.sql /index.php /xoops_version.php
其中xoops_version.php的内容如下:
/modules/moddevsql/xoops_version.php <?php $modversion['name'] = "模块开发 - 数据库"; $modversion['version'] = 0.01; $modversion['description'] = "演示数据库的使用"; $modversion['author'] = <<<AUTHOR 胡争辉 QQ: 443089607 QQMail: hu_zhenghui@qq.com GTalk: huzhengh GMail: huzhengh@gmail.com Skype: huzhenghui" AUTHOR; $modversion['credits'] = ""; $modversion['license'] = "版权所有"; $modversion['image'] = "images/logo.png"; $modversion['dirname'] = "moddevsql"; $modversion["hasMain"] = 1; $modversion["sqlfile"]["mysql"] = "sql/mysql.sql"; $modversion["tables"][] = "moddevsql_contact"; ?> <pre> 其中sqlfile参数表示该模块包括创建数据表的脚本,键值[[mysql]]表示当前的XOOPS系统采用mysql数据库时所使用的创建数据表脚本的路径,该路径为相对于模块根目录的路径。 <pre> $modversion["sqlfile"]["mysql"] = "sql/mysql.sql";
本例中的创建数据表脚本的内容如下。
/modules/moddevsql/sql/mysql.sql CREATE TABLE `moddevsql_contact` ( `id` int(10) unsigned NOT NULL auto_increment, `firstname` text NOT NULL, `lastname` text NOT NULL, `QQ` text NOT NULL, `QQMail` text NOT NULL, `GTalk` text NOT NULL, `GMail` text NOT NULL, `Skype` text NOT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=2 ; INSERT INTO `moddevsql_contact` (`id`, `firstname`, `lastname`, `QQ`, `QQMail`, `GTalk`, `GMail`, `Skype`) VALUES (1, '争辉', '胡', '443089607', 'hu_zhenghui@qq.com', 'huzhengh', 'huzhengh@gmail.com', 'huzhenghui');
安装该模块时,XOOPS系统会自动解析该脚本,并为表名增加相应的前缀,从安装过程中可以看到创建的表以及插入的数据,如图1-20安装数据库模块所示。
在安装带数据库的模块时,首先会查找数据库安装脚本。
SQL file found at D:/wamp/www/xoopstutorial/modules/moddevsql/sql/mysql.sql.
然后解析脚本并执行,如果脚本中包含创建表的脚本,XOOPS系统将自动为建表脚本的表名加上前缀,然后创建数据库,如果数据表创建成功,则输出相应的信息。
Table xoops_moddevsql_contact created.
如果脚本中包含向数据表插入数据的脚本,XOOPS系统将自动为插入脚本世纪末表名加上前缀,然后插入数据,如果插入数据成功,则输出相应的信息。
Data inserted to table xoops_moddevsql_contact.
模块成功安装后,模块中的程序就可以访问该数据表了,本例中的index.php文件的功能就是访问moddevsql_contact数据表,代码如下。
/modules/moddevsql/index.php <?php require_once dirname(__FILE__)."/../../mainfile.php"; /* @var $xoopsDB XoopsMySQLDatabaseProxy */ $sql = "SELECT * FROM ".$xoopsDB->prefix("moddevsql_contact"); $result = $xoopsDB->query($sql); include XOOPS_ROOT_PATH."/header.php"; ?> <table> <tr> <th> id </th> <th> first name </th> <th> last name </th> <th> QQ </th> <th> QQ Mail </th> <th> Google Talk </th> <th> Google Mail </th> <th> Skype </th> </tr> <?php while (false !== ($data = $xoopsDB->fetchArray($result))) { ?> <tr> <td> <?php echo htmlspecialchars($data["id"]); ?> </td> <td> <?php echo htmlspecialchars($data["firstname"]); ?> </td> <td> <?php echo htmlspecialchars($data["lastname"]); ?> </td> <td> <?php echo htmlspecialchars($data["QQ"]); ?> </td> <td> <a href="mailto:<?php echo htmlspecialchars($data["QQMail"]); ?>"> <?php echo htmlspecialchars($data["QQMail"]); ?> </a> </td> <td> <?php echo htmlspecialchars($data["GTalk"]); ?> </td> <td> <a href="mailto:<?php echo htmlspecialchars($data["GMail"]); ?>"> <?php echo htmlspecialchars($data["GMail"]); ?> </a> </td> <td> <?php echo htmlspecialchars($data["Skype"]); ?> </td> </tr> <?php } ?> </table> <?php include XOOPS_ROOT_PATH."/footer.php"; ?>
为了获取数据,首先要构造SQL,代码如下。
$sql = "SELECT * FROM ".$xoopsDB->prefix("moddevsql_contact");
这里用到了$xoopsDB类的prefix函数。$xoopsDB是XOOPS系统提供的数据库访问类,其中封装了与数据库交互的基本函数。由于 XOOPS系统自动为表增加前缀,因此在模块中使用表名时,需要调用$xoopsDB类的prefix函数为表增加前缀,prefix函数的定义如下。
/class/database/database.php function prefix($tablename='') {}
构造了SQL之后,就可以查询数据库并获得结果集。
$result = $xoopsDB->query($sql);
这里用到了$xoopsDB类的query函数,该函数用于在数据库执行查询,query函数的定义如下。
/class/database/mysqldatabase.php function query($sql, $limit=0, $start=0) {}
query函数是对mysql_query函数的简单封装。获取了结果集后,就可以循环访问该结果集获取数据行了。
while (false !== ($data = $xoopsDB->fetchArray($result))) {
这里用到了$xoopsDB类的fetchArray函数,该函数用于获取结果集中的数据行。fetchArray函数的定义如下。
/class/database/mysqldatabase.php function fetchArray($result) {}
fetchArray函数是对mysql_fetch_assoc函数的简单封装,获取的数据也是一个关联数组。该页面的运行效果如图1-21显示查询数据库的结果所示。
由于XOOPS系统中既可以安装模块,还可以卸载模块,所以为安装模块的过程设置了脚本之外,还需要为卸载模块的过程设置所需要删除的数据表。相关信息也是定义在xoops_version.php文件中。
$modversion["tables"][] = "moddevsql_contact";
其中键值tables代表在卸载时需要删除的数据表,该键值下面的每一项都是一个在卸载时需要删除的数据表的名称,在卸载过程中,XOOPS系统会自动为表名增加相应的前缀。并且会输出相应的信息,如图1-22卸载数据库模块所示。
如果在xoops_version.php设置了tables键值,则XOOPS系统在卸载模块时会执行删除数据表的过程,并输出相应的信息。
Deleting module tables...
删除每个表也会输出相应的信息。
Table xoops_moddevsql_contact dropped.
数据对象[ ]
XOOPS系统不仅提供了数据库访问的封装类变量,还提供面向对象的访问方式,可以将数据表中的一条记录封装成一个对象,下面本例将讲解面向对象的访问方式。本例的文件夹结构如下:
/modules/moddevclass /class /contact.php /images /logo.png /sql /mysql.sql /index.php /xoops_version.php
其中xoops_version.php的内容如下:
/modules/moddevclass/xoops_version.php <?php $modversion['name'] = "模块开发 - 数据类"; $modversion['version'] = 0.01; $modversion['description'] = "演示数据类的使用"; $modversion['author'] = <<<AUTHOR 胡争辉 QQ: 443089607 QQMail: hu_zhenghui@qq.com GTalk: huzhengh GMail: huzhengh@gmail.com Skype: huzhenghui" AUTHOR; $modversion['credits'] = ""; $modversion['license'] = "版权所有"; $modversion['image'] = "images/logo.png"; $modversion['dirname'] = "moddevclass"; $modversion["hasMain"] = 1; $modversion["sqlfile"]["mysql"] = "sql/mysql.sql"; $modversion["tables"][] = "moddevclass_contact"; ?>
为便于对照学习,数据结构与上例类似。mysql.sql的内容如下:
/modules/moddevclass/sql/mysql.sql CREATE TABLE `moddevclass_contact` ( /* 详见源文件 */ ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=2 ; INSERT INTO `moddevclass_contact` (`id`, `firstname`, `lastname`, `QQ`, `QQMail`, `GTalk`, `GMail`, `Skype`) VALUES (1, '争辉', '胡', '443089607', 'hu_zhenghui@qq.com', 'huzhengh', 'huzhengh@gmail.com', 'huzhenghui');
本例中使用数据对象封装访问数据的过程。数据访问对象的源代码如下:
/modules/moddevclass/class/contact.php <?php class ModdevclassContact extends XoopsObject { function ModdevclassContact() { $this->initVar("id", XOBJ_DTYPE_INT); $this->initVar("firstname", XOBJ_DTYPE_TXTBOX); $this->initVar("lastname", XOBJ_DTYPE_TXTBOX); $this->initVar("QQ", XOBJ_DTYPE_TXTBOX); $this->initVar("QQMail", XOBJ_DTYPE_EMAIL); $this->initVar("GTalk", XOBJ_DTYPE_TXTBOX); $this->initVar("GMail", XOBJ_DTYPE_EMAIL); $this->initVar("Skype", XOBJ_DTYPE_TXTBOX); return; } } class ModdevclassContactHandler extends XoopsObjectHandler { function getAll () { $ret = array(); $sql = "SELECT * FROM ".$this->db->prefix("moddevclass_contact"); $result = $this->db->query($sql); if (false === $result) { return $ret; } while (false !== ($row = $this->db->fetchArray($result))) { $contact = new ModdevclassContact(); $contact->assignVars($row); $ret[$row["id"]] = $contact; unset($contact); } return $ret; } } ?>
其中ModdevclassContact是数据对象,继承自XoopsObject。
class ModdevclassContact extends XoopsObject {}
XoopsObject是XOOPS提供的数据对象基础类,所有的数据对象都应当继承自XoopsObject。这个类是XOOPS系统的核心类。
/kernel/object.php class XoopsObject {}
继承自XoopsObject的数据对象都需要初始化数据变量,这项工作应当在子类的构造函数中完成。对于访问数据库的数据对象来说,一般需要初始化所有的字段。本例中就初始化了所有的字段。
function ModdevclassContact() { $this->initVar("id", XOBJ_DTYPE_INT); $this->initVar("firstname", XOBJ_DTYPE_TXTBOX); $this->initVar("lastname", XOBJ_DTYPE_TXTBOX); $this->initVar("QQ", XOBJ_DTYPE_TXTBOX); $this->initVar("QQMail", XOBJ_DTYPE_ EMAIL); $this->initVar("GTalk", XOBJ_DTYPE_TXTBOX); $this->initVar("GMail", XOBJ_DTYPE_ EMAIL); $this->initVar("Skype", XOBJ_DTYPE_TXTBOX); return; }
初始化数据变量需要调用initVar函数,该函数是XoopsObject类的成员,定义如下。
/kernel/object.php function initVar($key, $data_type, $value = null, $required = false, $maxlength = null, $options = '') {}
其中$key是数据变量的名称,对于访问数据库的数据对象来说,使用字段名称;$data_type是数据变量的类型。XOOPS系统中使用常量来指示数据变量的类型,如表1-1数据变量类型所示。
本例中的ModdevclassContactHandler是数据访问句柄,继承自XoopsObjectHandler。
class ModdevclassContactHandler extends XoopsObjectHandler {}
XoopsObjectHandler是XOOPS系统提供的数据访问句柄基础类,所有的数据访问句柄都应当继承自XoopsObjectHandler,这个类是XOOPS系统的核心类。
/kernel/object.php class XoopsObjectHandler {}
继承自XoopsObjectHandler的数据访问句柄类都应当按需要实现相应的数据访问函数。本例中为获取所有的数据实现了函数getAll。
function getAll () { $ret = array(); $sql = "SELECT * FROM ".$this->db->prefix("moddevclass_contact"); $result = $this->db->query($sql); if (false === $result) { return $ret; } while (false !== ($row = $this->db->fetchArray($result))) { $contact = new ModdevclassContact(); $contact->assignVars($row); $ret[$row["id"]] = $contact; unset($contact); } return $ret; }
这段程序的工作流程与上例相同,区别在于,上例直接输出数据库的结果,而本例中将数据库的结果保存在数据访问类中。
$contact->assignVars($row);
assignVars函数提供将fetchArray获取的记录值直接保存在数据访问对象的功能。这个函数在XoopsObject中定义。
/kernel/object.php function assignVars($var_arr) {}
将所有的记录数据都转换成数据访问类并保存为数组后,getAll函数返回这个数组。相应的,页面也只需要获取对象数组并显示,不再需要直接访问数据库,index.php页面代码如下。
/modules/moddevclass/index.php <?php require_once dirname(__FILE__)."/../../mainfile.php"; $contacthandler = xoops_getmodulehandler("contact", "moddevclass"); /* @var $contacthandler ModdevclassContactHandler */ include XOOPS_ROOT_PATH."/header.php"; ?> <table> <tr> <!-- 详见源文件 --> </tr> <?php foreach ($contacthandler->getAll() as $contact) { /* @var $contact ModdevclassContact */ ?> <tr> <td> <?php echo $contact->getVar("id"); ?> </td> <td> <?php echo $contact->getVar("firstname"); ?> </td> <td> <?php echo $contact->getVar("lastname"); ?> </td> <td> <?php echo $contact->getVar("QQ"); ?> </td> <td> <a href="mailto:<?php echo $contact->getVar("QQMail"); ?>"> <?php echo $contact->getVar("QQMail"); ?> </a> </td> <td> <?php echo $contact->getVar("GTalk"); ?> </td> <td> <a href="mailto:<?php echo $contact->getVar("GMail"); ?>"> <?php echo $contact->getVar("GMail"); ?> </a> </td> <td> <?php echo $contact->getVar("Skype"); ?> </td> </tr> <?php } ?> </table> <?php include XOOPS_ROOT_PATH."/footer.php"; ?>
为了获取数据访问对象,首先需要获取数据访问句柄。
$contacthandler = xoops_getmodulehandler("contact", "moddevclass");
获取数据访问句柄时,不需要包含相应的文件,也不需要创建类实例。XOOPS系统提供了xoops_getmodulehandler用于直接获取数据访问句柄。
/include/functions.php function &xoops_getmodulehandler($name = null, $module_dir = null, $optional = false) {}
第一个参数$name是模块中数据访问句柄的名称,该名称是模块中class文件夹的文件名,本例中数据访问句柄的文件名是 contact.php,所以参数$name的值是contact。
第二个参数$module_dir是模块的文件夹名称,本例中模块的文件夹是 moddevclass。
注意:由于Windows文件系统不分区大小写,UNIX文件系统区分大小写,因此$name应该和文件名的大小写相同,文件名的后缀应当是小写的php;$module_dir应该和文件夹的大小写相同。
虽然PHP的类名不区分大小写,但是xoops_getmodulehandler函数对数据访问句柄的类名有额外的约定。数据访问句柄的类名包括三部分,模块名,类名和Handler,其中模块名应该仅有首字母大写,其余字母小写。类名的首字母大写。相关的代码如下。
ucfirst(strtolower($module_dir)).ucfirst($name).'Handler';
获取了数据访问句柄后,就可以访问其中定义的成员函数。
foreach ($contacthandler->getAll() as $contact) {
这个foreach循环将枚举所有的数据访问对象,每个数据访问对象的类型都是ModdevclassContact,数据访问对象可以调用getVar函数获取保存在其中的值。
<?php echo $contact->getVar("id"); ?>
getVar函数定义在XoopsObject中,用于获取由initVar初始化后的数据值。
/kernel/object.php function getVar($key, $format = 's') {}
其中$key参数应当是调用initVar初始化的数据变量名称。通过以上的修改,就把直接操作数据库变成了面向对象的数据访问。通过把数据访问封装成对象,不仅能独立的修改数据访问和页面展现,还能在不同的页面展现中使用相同的数据访问。页面效果如图 1 21 显示查询数据库的结果所示。
说明:使用基于XOOPS系统的Frameworks库,能够更方便的实现面向对象数据访问,因此本节仅介绍 XoopsObject和XoopsObjectHandler的基本原理,在实际模块中应优先选择基于Frameworks库,而不是直接继承自 XoopsObject和XoopsObjectHandler。
条件对象[ ]
XOOPS不仅能将数据库访问封装成对象,还提供将数据库的查询封装成对象。接下来本例讲解如何将查询封装成对象。
本例的文件夹结构如下:
/modules/moddevcriteria /class /contact.php /images /logo.png /sql /mysql.sql /index.php /xoops_version.php
其中xoops_version.php的内容如下:
/modules/moddevcriteria/xoops_version.php <?php $modversion['name'] = "模块开发 - 查询"; $modversion['version'] = 0.01; $modversion['description'] = "演示查询对象的使用"; $modversion['author'] = <<<AUTHOR 胡争辉 QQ: 443089607 QQMail: hu_zhenghui@qq.com GTalk: huzhengh GMail: huzhengh@gmail.com Skype: huzhenghui" AUTHOR; $modversion['credits'] = ""; $modversion['license'] = "版权所有"; $modversion['image'] = "images/logo.png"; $modversion['dirname'] = "moddevcriteria"; $modversion["hasMain"] = 1; $modversion["sqlfile"]["mysql"] = "sql/mysql.sql"; $modversion["tables"][] = "moddevcriteria_contact"; ?>
为便于对照学习,数据结构与上例类似。mysql.sql的内容如下:
/modules/moddevcriteria/sql/mysql.sql CREATE TABLE `moddevcriteria_contact` ( /* 详见源文件 */ ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=2 ; INSERT INTO `moddevcriteria_contact` (`id`, `firstname`, `lastname`, `QQ`, `QQMail`, `GTalk`, `GMail`, `Skype`) VALUES (1, '争辉', '胡', '443089607', 'hu_zhenghui@qq.com', 'huzhengh', 'huzhengh@gmail.com', 'huzhenghui');
本例中的数据访问句柄增加了对查询对象的支持,源代码如下:
/modules/moddevcriteria/class/contact.php <?php class ModdevcriteriaContact extends XoopsObject { function ModdevcriteriaContact() { /* 详见源文件 */ } } class ModdevcriteriaContactHandler extends XoopsObjectHandler { function getAll ($criteria = null) { /* @var $criteria Criteria */ $ret = array(); if (true === isset($criteria)) { $sql = "SELECT * FROM ".$this->db->prefix("moddevcriteria_contact"). " ".$criteria->renderWhere(); } else { $sql = "SELECT * FROM ".$this->db->prefix("moddevcriteria_contact"); } $result = $this->db->query($sql); if (false === $result) { return $ret; } while (false !== ($row = $this->db->fetchArray($result))) { $contact = new ModdevcriteriaContact(); $contact->assignVars($row); $ret[$row["id"]] = $contact; unset($contact); } return $ret; } } ?>
本例中的getAll函数增加了一个可选的$criteria参数,该参数用于传入一个条件对象,如果未设置该参数,则和上例相同,返回全部的数据。
function getAll ($criteria = null) {
因为设置查询条件和查询全部数据会影响SQL语句,所以引用了中间变量$sql,在查询时仅查询$sql。
$result = $this->db->query($sql);
当未传入条件对象$criteria时,$sql的取值与上例相同。
$sql = "SELECT * FROM ".$this->db->prefix("moddevcriteria_contact");
当传入了条件对象$criteria时,$sql只需要连接条件对象生成的WHERE语句即可。
$sql = "SELECT * FROM ".$this->db->prefix("moddevcriteria_contact"). " ".$criteria->renderWhere();
可以看出,条件对象在使用时非常简单。本例的index.php页面相应的增加了查询表单,代码如下。
/modules/moddevcriteria/index.php <?php require_once dirname(__FILE__)."/../../mainfile.php"; $contacthandler = xoops_getmodulehandler("contact", "moddevcriteria"); /* @var $contacthandler ModdevcriteriaContactHandler */ include XOOPS_ROOT_PATH."/header.php"; ?> <form> first name: <input name="firstname" /> <input type="submit" /> </form> <table> <tr> <!-- 详见源文件 --> </tr> <?php if (true === isset($_GET["firstname"])) { $myts =& MyTextSanitizer::getInstance(); $criteria = new Criteria("firstname", $myts->addSlashes($_GET["firstname"])); $contacts = $contacthandler->getAll($criteria); } else { $contacts = $contacthandler->getAll(); } foreach ($contacts as $contact) { /* @var $contact ModdevcriteriaContact */ ?> <tr> <!-- 详见源文件 --> </tr> <?php } ?> </table> <?php include XOOPS_ROOT_PATH."/footer.php"; ?>
效果如图1-23查询表单所示。
与上例不同的时,为了区别全面查询和按first name查询两种不同的情况,引入了中间变量$contacts保存查询结果。
foreach ($contacts as $contact) {
页面中依据是否设置了查询条件参数选择相应的处理过程。
if (true === isset($_GET["firstname"])) {
如果没有设置查询条件,则采用和上例相同的调用方式获取全部的数据访问对象。
$contacts = $contacthandler->getAll();
如果设置了查询条件,则需要创建相应的条件对象,因为PHP依赖设置的不同,会对参数中的字符进行转义,因此先获取文本修饰对象。
$myts =& MyTextSanitizer::getInstance();
然后用文本修饰对象自动对参数转义后创建条件对象。
$criteria = new Criteria("firstname", $myts->addSlashes($_GET["firstname"]));
接下来将条件对象传入getAll函数获取查询结果。
$contacts = $contacthandler->getAll($criteria);
通过上述这些修改,就实现了用条件对象查询数据,不需要在SQL语句中写WHERE子句,全部由Criteria类自动处理。