众所周知的事情,discuz的产品是被广泛使用的,大部分论坛都是使用discuz的,而uchome也作为discuz在sns领域的产品被广泛使用,充分扩展了论坛用户的联系,从一个论坛变为一个社区。而且关键是源代码公开的,也就是说你可以看它的代码并根据自己需要加入自己的代码与二次开发,或者二次开发discuz的产品能被作为php程序员的基本技能之一。

最近,也不能说是最近了……近一个月……paperen研究了uchome,虽然也并没有把所有功能都看完,但是整体的模式还是明白了,有MVC的味道。paperen主要看了cp.php与space.php的代码,还有它是如何处理ajax的请求的。而paperen发的这篇博文的主题就是一个很简单ajax的运用。

20101007104820

paperen在个人主页cp.php中添加了一个新页面的链接,作为自己来随便测试,当然你需要去更改一下它的模板文件,况且叫模板吧(就是template文件夹中的default里面的space_index.htm)。

cp.php最后会

include_once(S_ROOT.'./source/cp_'.$ac.'.php'); 

也就是说根据cp.php?ac=mymod这个ac参数决定调入哪个模型文件,您还需要更改一下cp.php中的$acs数组,里面已经固定了所有允许的模型名称,你加入你那个相应功能的名称就可以(paperen这里就是mymod),在source里面也创建一个新模型文件(paperen这里就是cp_mymod.php),里面很简单放一句

include_once template("cp_mymod");

您再查看一下template这个函数,位于source里面的function_common.php中

function template($name) {
global $_SCONFIG, $_SGLOBAL;

if($_SGLOBAL['mobile']) {
$objfile = S_ROOT.'./api/mobile/tpl_'.$name.'.php';
if (!file_exists($objfile)) {
showmessage('m_function_is_disable_on_wap');
}
} else {
if(strexists($name,'/')) {
$tpl = $name;
} else {
$tpl = "template/$_SCONFIG[template]/$name";
}
$objfile = S_ROOT.'./data/tpl_cache/'.str_replace('/','_',$tpl).'.php';
if(!file_exists($objfile)) {
include_once(S_ROOT.'./source/function_template.php');
parse_template($tpl);
}
}
return $objfile;
}

$_SGLOBAL['mobile']这个是判断是不是手机访问网站的,是就调用专用的文件显示,这里无视掉,因为不是paperen说的话题。else中的一大段其实做的功能很简单,判断该模板文件是否已经转换成缓存文件,已经生成了缓存文件就直接将路径返回,引入。而uchome中有自己一套模板语言,你可以看看template/default中的一些htm文件,里面貌似是没有任何php的代码,但是随处可见

<!--{template header}-->

<!--{if $topic}-->
<!--{template cp_topic_menu}-->
<!--{else}-->

这样一些代码,并不是没有意思的,这些代码需要经过编译才有意义,parse_template函数就是uchome自定义模板编译功能的函数。有兴趣可以看看,有大量正则。编译完后就会存放在data/tpl_cache路径下,你可以到这里看看,随便打开一个文件看看就已经很熟悉了,里面加入了php标志<?php ?>并将模板中的一些代码转变为php的代码,但是你不要直接在这个缓存文件中改因为一旦更新缓存你的改动又得白费,你应该去编辑template中的文件。

继续说关于提示框的调用……在研究这个前端功能时你可以从uchome中的默认功能开始,比如我的状态那

20101007105102

当你更新状态后就会有一个提示框,提示您获得的奖励。

查看其代码,涉及了ajaxpost,reloadMood,showreward……还有不少,ajaxpost这个纯属是ajax引擎的,动态地在页面插入一个iframe,将form的target指向这个iframe,然后启动onload动作,在网速慢的时候你会发觉在右上方会有一个loading...的提示,代码不少所以就补贴上来了,ajaxpost位于source/script_ajax.js中,重点来看看reloadMood与showreward。

function reloadMood(showid, result) {
var x = new Ajax();
x.get('cp.php?ac=doing&op=getmood', function(s){
$('mood_mystatus').innerHTML = s;
});
//提示获得积分
showreward();
hiddenstatus();
}

reloadMood向cp.php发出一个请求,获得当前的状态并更改页面上的状态。之后调用showreward提示积分情况,最后的hiddenstatus应该就是将更新状态时出现的表情隐藏并初始化一些html。

showreward位于source/script_common.js中。

function showreward() {
if(Cookie.get('reward_notice_disable')) {
return false;
}
var x = new Ajax();
x.get('do.php?ac=ajax&op=getreward', function(s){
if(s) {
msgwin(s, 2000);
}
});
}

判断一下cookie中是不是存在一个叫reward_notice_disable的键值并返回其数据(cookie的js处理在source/script_cookie.js中),而向do.php发出一个请求,并带上ac与op参数,其实还有一个参数inajax会被默认加上的。那么就很明确了直接去看do.php这个文件。

include_once(S_ROOT.'./source/do_'.$ac.'.php');

还是与cp.php的做法一样,根据ac导入相应的模型文件,这里固定为ajax所以就是do_ajax.php,继续看这个文件,额~~很好~~就是这样。

$op = empty($_GET['op'])?'':$_GET['op'];
if($op == 'comment') {...}else if($op == 'other'){...}else if(...){...}
include template('do_ajax');

再根据op决定执行某个动作,这里自己随便加入一个elseif ($op == 'getmytip')里面什么都不写就行,然后会根据缓存情况对template/default中的do_ajax.htm文件进行编译,paperen也随便加入了一段。

<!--{elseif $op == 'getmytip'}-->
<div class="popupmenu_layer">
<p>友情提示</p>
<p class="btn_line">
仅供测试之用,没有任何意义
</p>
<p><strong>囧rz</strong></p>
</div>
<!--{/if}-->

更新一下缓存,之后就可以试了。在自己新加入的模板文件中加入。

<script>
function showmytip() {
var x = new Ajax();
x.get('do.php?ac=ajax&op=getmytip', function(s){
if(s) {
msgwin(s, 4000);
}
});
}
showmytip();
</script>

然后打开您那个自定义页面就会看到一个提示框出现,并4秒后自动消失,msgwin这个函数就是将s的内容进行一下填充与设置定时消失动作效果而已,位于script_common.js中。就是这么简单~~

可能一开始会有点乱但是整个代码思路还是挺不错的,各模块之间划分得很清晰。老实说看看这种好的代码也是一种提高自身水平的途径,不过您自己也要动动手,光看真的没意思。