PHPCMS 的模块安装是通过后台管理面板 系统设置->模块管理->安装模块 来实现的,其对应的地址是 admin.php?mod=phpcms&file=module&action=install

   接下来我先简单分析g根目录下的 admin.php 文件
admin.php 前面的一系列是一些权限的判断,这里我暂且不予关心。这里我们所关心的主要是下面这2行代码:
if($mod != 'phpcms' && !@include PHPCMS_ROOT.$M['path'].'admin/admin.inc.php') showmessage('The file ./'.$M['path'].'admin.inc.php is not exists!');
// 上面的意思是如果当前模块不是 phpcms 则引入 phpcms跟目录/模块路径/admin/admin.inc.php 文件,如果找不到则提示错误信息。
// 由上面我们可以看到新开发一个模块 新模块/admin/admin.inc.php 文件是必不可少的。
if(!@include PHPCMS_ROOT.(isset($M['path']) ? $M['path'] : '').'admin/'.$file.'.inc.php') showmessage("The file ./{$M['path']}admin/{$file}.inc.php is not exists!");
// 上面的意思是 引入当前模块下的 $file 文件($file 通过 admin.php?mod=phpcms&file=module&action=install 得到,$_GET['file']), 如果找不到文件则提示错误信息。


从上面2行代码我们可以很容易根据 admin.php?mod=phpcms&file=module&action=install 定位到 phpcms跟目录/admin/module.inc.php。

分析 module.inc.php 可以根据 admin.php?mod=phpcms&file=module&action=install 的 action=install 部分我们可以大致确认实际进行模块安装的文件大概从 第10行 到第65行。

由下面我们开始以 vote 为例分析一模块安装。
首先我们来到第72行 include admin_tpl('module_install'); // 在一行的作用就是点后台 安装模块 后默认显示的输入表单。

假设 vote 是我们新开发的一模块,其所在目录为 phpcms根目录/vote/,因此安装模块时,模块安装目录中要填写 vote,submit 提交后
代码转到:
            if(isset($confirm) && $confirm==1)
            {
                // 判断安装目录是否存在,其实就是判断是否有 phpcms根目录/vote/install/ 目录,
                // 如果没有则提示错误信息。
                // 因此如果我们要开发一个可以对外发布发新模块,一定要保证新模块下的 install 目录存在。
                if(!is_dir(PHPCMS_ROOT.$installdir."/install/"))
                {
                    showmessage($LANG['module_install_dir_not_exist']);
                }
               
                // 引入 vote/install/config.inc.php 文件
                // 此文件里包含了模块的部分信息,如:模块名、描述、作者 等信息。
                require_once PHPCMS_ROOT.$installdir."/install/config.inc.php";

                // 如果新开发的模块和已有模块冲突(名称相同),则提示错误信息。
                if(array_key_exists($module, $MODULE)) showmessage($LANG['installed_module_unstall_it_then_continue']);
               
                // 模块确认提示信息
                include admin_tpl('module_install_confirm');
            }

在确认模块信息并 submit 提交后,代码跳转到:

        if(isset($confirminstall) && $confirminstall)
        {
            // 引入 vote/install/config.inc.php 文件
            // 此文件里包含了模块的部分信息,如:模块名、描述、作者 等信息。
            require_once PHPCMS_ROOT.$installdir."/install/config.inc.php";
            
            // 查询数据 phpcms_module 表,检查新安装的模块是否已经存在?如果存在给出错误提示信息。
            // 由此可以看出所有系统模块都记录在 phpcms_module 表里。
            $r = $db->get_one("SELECT module From ".DB_PRE."module WHERE module='$installdir'");
            if($r) showmessage($LANG['installed_module_unstall_it_then_continue']);                    
            
            // 如果新开发模块 instal 目录下存在 mysql.sql 则执行这个sql 文件
            // 因此对于我们新开发的模块需要建立的一些数据表以及一些数据库初始设置,我们可以写到 mysql.sql 文件
            if(file_exists(PHPCMS_ROOT.$installdir."/install/mysql.sql"))
            {
                $sql = file_get_contents(PHPCMS_ROOT.$installdir."/install/mysql.sql");
                sql_execute($sql);
            }

            // 如果新开发模块 instal 目录下存在 extention.inc.php 进行 menu 的设置
            // 这里主要进行模块后台的管理菜单设置
            if(file_exists(PHPCMS_ROOT.$installdir."/install/extention.inc.php"))
            {
                @extract($db->get_one("SELECT menuid AS member_0 FROM ".DB_PRE."menu WHERE keyid='member_0'"));
                @extract($db->get_one("SELECT menuid AS member_1 FROM ".DB_PRE."menu WHERE keyid='member_1'"));
                @include (PHPCMS_ROOT.$installdir."/install/extention.inc.php");
            }

            // 用 FTP 进行 目录权限设置。
            if(FTP_ENABLE)
            {
                require_once PHPCMS_ROOT.'include/ftp.class.php';
                $ftp = new ftp(FTP_HOST, FTP_PORT, FTP_USER, FTP_PW, FTP_PATH);
                if(file_exists(PHPCMS_ROOT.$installdir."/install/chmod.txt"))
                {
                    $files = file(PHPCMS_ROOT.$installdir."/install/chmod.txt");
                    $files = array_filter($files);
                    foreach($files as $file)
                    {
                        $ftp->dir_chmod(PHPCMS_ROOT.$file);
                    }
                }
            }
            
            // 复制 模板目录 到系统模板目录下
            if(file_exists(PHPCMS_ROOT.$installdir."/install/templates/"))
            {
                dir_copy(PHPCMS_ROOT.$installdir."/install/templates/", PHPCMS_ROOT.'templates/'.TPL_NAME.'/'.$module.'/');
            }

            // 复制 语言文件 到系统 语言文件下
            if(file_exists(PHPCMS_ROOT.$installdir."/install/languages/"))
            {
                dir_copy(PHPCMS_ROOT.$installdir.'/install/languages/', PHPCMS_ROOT.'languages/'.LANG.'/');
            }
            cache_all(); //更新全部缓存
            tags_update(); // 更新 tags
            showmessage($LANG['module_install_success'], "?mod=".$mod."&file=module&action=updatecache"); // 提示模块安装成功信息。
        }

虽然说是以 vote 为例讲模块的开发,但是几乎没多少具体涉及到 vote,再此谨以抛砖引玉,希望能或多或少得到益处。