插件作者的标准出来了!Manyou诚邀开发者加盟!
“互联网平台开发者”特刊 有奖征集开发者
立即免费下载 Discuz!6.1.0正式版
Discuz! 6.1.0 使用说明
Discuz!NT2.5正式版发布
开放源码下载
UCenter Home 1.2 正式版发布
官方站 | 帮助文档
基于ECShop的网店托管-卖否
PHP就业培训直通车 | LAMP培训大连
Discuz!收费服务内容及价格
“感谢有你同行”手握手2008年数万元重奖志愿者
Discuz!/ECShop 专用官方虚拟主机
亿声传媒(Insenz)中秋祝福发送中
Comsenz 招聘信息
网店系统ECShop v2.6.0正式版火热发布
基于Discuz!的免费论坛空间5D6D
参与有奖社区调查 赢取台湾5日游
发新话题
打印

[教程] 插件编写规范和流程[12.13日更新]

请LZ继续更新吧
难啊!!!!!看看我的签名 看看我的签名QQ395648512
http://5i58.58ct.net,58互动垂直网赚,网上兼职的最佳选择!
超级菜鸟一名,想偷师,但怎么看都学不会。。。
楼主 好久没更新了……
支持这样的帖子 支持技术交流
有源码下载吗?
想要完整代码
  看了Maple-x的这篇贴子,深受启发,以前都是编写那种功能增强型的插件,将插件作为独立的文件存放。这几天,慢慢地按照贴子的步骤熟悉了一下开发的流程,发现不算难,但也碰到了一些问题,下面详细地说一下。
  看到前面一些朋友对代码的质疑,我在编写的时候,综合了一下意见,进行了改进。

  下面是apply.inc.php的代码:
复制内容到剪贴板
代码:
<?php
if(!defined('IN_DISCUZ'))
{
exit('Access Deined');
}
//建议:在每个插件程序的开头加上上面的代码.这是为了防止禁止直接外部访问文件


@include_once DISCUZ_ROOT.'./forumdata/cache/plugin_apply.php';
/*
调用DISCUZ生成的插件参数的缓存文件.调用缓存文件以后,就可以调用里面的变量了.
Discuz生成的插件参数的配置文件是保存在一个二维的数组里的。$_DPLUGIN[‘apply’][‘vars’];
这里我们为了美观,对这个二维数组进行一下简化
*/
$applycount = $_DPLUGIN['apply']['vars']['applycount'];
$lowestregdates = $_DPLUGIN['apply']['vars']['lowestregdates'];
$integral = $_DPLUGIN['apply']['vars']['integral'];
$extcredit = $_DPLUGIN['apply']['vars']['extcredit'];
$lowestposts = $_DPLUGIN['apply']['vars']['lowestposts'];


/*
这里需要强调的一点:
Discuz是对提交过来的变量的值进行了转义,我们可以认为他过来的值就是一个字符串,那么在使用他的时候,要尽量放在一个不会解析变量的单引号内.这样无论是安全还是效率都会有所提高.尤其是在SQL语句中.一定要把变量放在单引号呢。例如
$db->query("SELECT * FROM {$tablepre}members WHERE uid='$discuz_uid'");
*/


@include_once DISCUZ_ROOT.'./forumdata/cache/plugin_apply.php';
@include language('apply');
if(!$discuz_uid) {
        showmessage('not_loggedin','logging.php?action=login');
}


$applys = $apply = '';
$applylist = array();
//注意:记得对变量初始化,这是一个好的习惯,也可以避免安全问题。


$page = !ispage($page) ? 1 : $page;
$start_limit = ($page - 1) * 10;


if($action == 'apply') {                //申请斑竹
    $query = $db->query("SELECT COUNT(appid) FROM {$tablepre}plugin_apply WHERE uid='$discuz_uid'");  //查看申请用户的申请次数
    $applys = $db->result($query,0);                //$db->result($query,0)可以用来取得一个记录值
    if($applys >= $applycount) {                        //判断是否申请次数
            showmessage($language['applys_max'], 'plugin.php?identifier=apply&module=apply');
    } else {
            require_once DISCUZ_ROOT.'./include/forum.func.php';        //包含相关与论坛帖子相关的文件。这里因为下面的forumselect()函数需要用到
            require_once DISCUZ_ROOT.'./forumdata/cache/cache_forums.php';
            $forumselect = "<select name=\"fid\">\n<option value=\"\">  >请选择版块</option><option value=\"\"> </option>".str_replace('%', '%%', forumselect()).'</select>';                //这里是生成下拉采单式的版块选择,你可以看看DZ的操作方式
            include_once DISCUZ_ROOT . './plugins/apply/apply/apply.php';        //到apply目录下用对应的程序来处理申请的过程
    }
} elseif ($action == 'del') {                //这里是删除用户申请的过程
    if(($discuz_uid == $uid || $adminid == 1) && $formhash == FORMHASH) {        //只有用户和管理员才有权限删除
            $db->query("DELETE FROM {$tablepre}plugin_apply WHERE uid='$discuz_uid' AND fid='$fid'");
            showmessage($language['operate_success'], 'plugin.php?identifier=apply&module=apply');
    } else  {
            showmessage($language['operate_invalid']);
    }
} else {
    $action = "view";
$query = $db->query("SELECT * FROM {$tablepre}plugin_apply LIMIT $start_limit,10"); //取得记录,并格式化时间
    while($apply = $db->fetch_array($query)) {
            $apply['dateline'] = gmdate("$dateformat $timeformat", $apply['dateline'] + $timeoffset * 3600);
            $applylist[] = $apply;
    }
    $query = $db->query("SELECT COUNT(*) FROM {$tablepre}plugin_apply");        //分页显示
    $applynum = $db->result($query,0);
    $multipage = multi($applynum, 10, $page, "plugin.php?identifier=apply&module=apply");


    include template('apply');
}
?>
代码改进的说明:(按照代码出现的顺序)
1.将cdb_用{$tablepre}来代替——这样具有更好的通用性,如果表前缀不一样,只要在建表的sql语句修改一下即可。(在apply.php的改进中也是如此)
2.增加了@include language('apply');语句——使用语言包来规定提示信息
3.将$applylist = '';改为$applylist = array();——虽然效果一样,但意义比较明了
4.在showmessage函数中,使用$language['applys_max']这样的语句来从语言包中导入提示信息,并且将原来语句中javascript:history.go(-1)实现返回上级的方式,改成直接在提示信息中包含“返回”字样,从而实现显示回到上一级的方式。(在apply.php的改进中也是如此)
5.对$action == 'del'这段处理代码,有比较多的疑惑:
$discuz_uid == $uid || $admin == 1 && $formhash == FORMHASH
说实话,这里$discuz_uid == $uid有点怪,没有体现它的用处,不过,到后面可以跟模板网页中的传值结合起来用,可以说这是一个加强保险的语句。
这个语句有问题,因为按照运算符的俦顺序它相当于:$discuz_uid == $uid || ($admin == 1 && $formhash == FORMHASH)应改为:($discuz_uid == $uid || $admin == 1) && $formhash == FORMHASH 比较符合逻辑。这个语句中$admin有问题,实际上应该是$adminid,$adminid为1时,该用户就是管理员,所以这里正确应该是:($discuz_uid == $uid || $adminid == 1) && $formhash == FORMHASH
另外,这里应该改进一下,因为从道理上来说管理员应该能删除其他人发的申请,但作为一个范例,为免过于复杂,还是保留原样。
6.$action = "view";——新增这个语句,是与模板结合使用的,意思是如果没有明确的$action动作,那么就将用户带到查看申请的页面。


  接下来是apply.php的代码:
复制内容到剪贴板
代码:
<?php
if(!defined('IN_DISCUZ')) {
exit('ACCESS Diened');
}


$userinfo = '';


$query = $db->query("SELECT posts,$extcredit,regdate FROM {$tablepre}members WHERE uid='$discuz_uid'");
$userinfo = $db->fetch_array($query);
$userinfo['regdate'] = $timestamp - $userinfo['regdate'];
$userinfo['regdate'] = ceil($userinfo['regdate'] / (3600*24));


if(submitcheck('forumsubmit')) {
        if($userinfo['regdate'] < $lowestregdates || $userinfo[$extcredit] < $integral || $userinfo['posts'] < $lowestposts) {
                showmessage($language['condition_invalid'],'plugin.php?identifier=apply&module=apply&action=apply');
        }
        
        $query = $db->query("SELECT name FROM {$tablepre}forums WHERE fid='$fid'");
        $fname = $db->result($query,0);
        if(empty($fname)){
                showmessage($language['forum_invalid']);
        } else {
                $query = $db->query("SELECT COUNT(*) FROM {$tablepre}plugin_apply WHERE uid='$discuz_uid' AND fid='$fid'");
                if($db->result($query,0)) {
                        showmessage($language['forum_repeat']);
                }
        }
        
        if(empty($nettime)) {
                showmessage($language['nettime_invalid']);
        } else {
                $nettime = intval($nettime);
        }
        
        if(!empty($description) && strlen($description) >= 16) {
                $description = nl2br(dhtmlspecialchars($description));
        } else {
                showmessage($language['description_invalid']);
        }
        
        if(!(empty($suggest) && strlen($suggest) >= 16)) {
                $suggest = nl2br(dhtmlspecialchars($suggest));
        } else {
                showmessage($language['suggest_invalid']);
        }
        if (!isset($agreeapply)) {
          showmessage($language['$agreeapply_invalid']);
        }
        $db->query("INSERT INTO {$tablepre}plugin_apply (`uid`,`username`,`fid`,`fname`,`suggest`,`description`,`nettime`,`dateline`,`agreeapply`)
                VALUES ('$discuz_uid','$discuz_user','$fid','$fname','$suggest','$description','$nettime','$timestamp','$agreeapply')");
        showmessage($language['apply_success'],'plugin.php?identifier=apply&module=apply');
}


include template('apply');
?>
代码改进的说明:(按照代码出现的顺序)
1.去掉$total的定义和如下两句代码:
$query = $db->query("SELECT count(uid) FROM cdb_plugin_apply WHERE uid='$discuz_uid'");
$total = $db->result($query,0);
从整个代码来看,这两句代码没什么用处,申请最大次数已经在apply.inc.php中处理了。
2.增加是否同意版主章程的判断($agreeapply)


从整个代码流程来看,觉得有些地方需要改进,列举如下:
1.判断该用户是否已经是所申请的版块的版主了
2.每页显示数目,版主章程(这个是我自己加的^-^)等都可以放到后台插件设置里
3.投票功能——对参加申请的会员进行投票选举。
4.一次同时申请多个版块


  这个教程看起来还没有写完(没有看到adminapply这个模块的编写),看到前面有人要源码和相关文件,我就把我自己做出来(有相关的模板,建表的SQL语句和导出的discuz_plugin_apply.txt插件信息文件)的贡献给大家。这个做的还是比较一般,有不少需要改进的地方,望大家多多指教。
压缩包使用说明:
1.将整个apply文件夹拷贝到bbs目录下的plugins
2.apply\images目录下的图片拷贝到bbs目录下的images\common
3.apply\templates目录下的所有文件拷贝到bbs目录下的templates\default
4.在后台导入apply目录下的discuz_plugin_apply.txt文件,并更新缓存即可使用(如果要直接使用此插件就进行这个步骤)
  插件下载及界面截图:

附件

apply.rar (47.2 KB)

2007-2-2 14:29, 下载次数: 121

pic1.gif (19.13 KB)

2007-2-2 14:29

pic1.gif

pic2.gif (20.47 KB)

2007-2-2 14:29

pic2.gif

请问一下,在apply.htm文件中有一个变量$applist是怎么来的,谢谢!
学习,学习,再学习!
目前写得最接近完成的教程,和袍哥的帖子搭配看,很是不错!
唉~不要个个高手是搞得虎头蛇尾哪。来来来继续搞定它。
感激!
发新话题
版块跳转