【UCHome二次开发】资料整理<中>
【UCHome二次开发】 不同于Manyou的开发模式
注意:此文和UCHome的Manyou开发模式不同,Manyou是利用Discuz的开放平台MYOP开发公共插件,可供所有基于UCHome的网站使用;而此文涉及的开发模式与Manyou不同,是在本地开发,以插件的形式扩展UCHome原有功能。
UCHome是Discuz的一款SNS程序,能让每个网站都用拥有自己的Facebook/校内。Discuz也提供了MYOP开发者平台,所有开发者都可以在此平台上开发自己的应用程序供其他UCHome网站使用,不但可以为自己的网站增加功能,同时也能将自己网站的功能推广到数以万计的UCHome网站中,可谓一举两得。
有时候,开发者并不一定希望使用MYOP开发应用,一是由于产品的需要,并不希望开发出来的应用被其他网站使用;二者MYOP的开发,必须处理联网模式,不能本地开发,较为繁琐。因此,很多有能力的站长会在UCHome的基础之上,以修改UCHome代码的方式增加功能。
但UCHome发展速度很快,经常会有版本更新,往往这个时候,修改了UCHome源码的站长就会面临一个两难的问题:是升级程序?还是为了保留以往的修改,而不升级?在我看来,如果前期做好开发规范,是完全可以避免这个问题的。下面介绍一下我在UCHome Apps开发过程中的一些经验。
想要能够随着官方的程序发布实现平滑的代码升级,无非一点:尽量的少改UCHome原有代码。
少改,但不是不改。一点不改程序的源代码是不可能的。但如何能实现少改呢?我定制了了下面的一些规则:
基本原则
除template目录下的模板文件,其余uchome原有文件尽量不要改动。如需要改动,需汇报项目管理人员记录后才可实施修改。
即使需要对系统原有文件进行修改,尽量不要在文件中增加逻辑代码,也不要修改原有逻辑,使用include的方式来增加逻辑。
例如,需要在系统首页增加growth的表单,设计到两个系统原有文件的修改:
source/space_feed.php
template/space_feed.htm
但请不要直接在这两个文件中增加逻辑代码,对于模板文件,可以使用<!-{template apps/growth/tpl/widget/form.htm}–>的方式加载一个外部文件;同样,针对程序文件,也可以使用include ‘apps/growth/widget/form.php’的方式。
采用这样的方式,即使以后程序文件被覆盖,也不会增加太多工作量。
文件结构

<!--[if !supportLists]-->· <!--[endif]-->以apps.php作为入口文件,所有应用都使用类似apps.php?do=growth&ac=list这样的URL访问应用程序。其中do为应用名称,ac为动作(执行的脚本名)。例如上面的例子,实际是以apps.php为入口,再加载apps/growth/list.php。
<!--[if !supportLists]-->· <!--[endif]-->应用程序统一放在apps目录之下,以应用的名称创建文件夹。例如,成长曲线的名称为growth,则创建apps/growth/目录,所有成长曲线的应用程序都放在此文件夹下。其中tpl文件夹存放模板文件,image文件夹存放图片,可根据应用需求安排apps/growth/内的文件结构。
<!--[if !supportLists]-->· <!--[endif]-->growth/doc 目录用于存放当前应用的文档,例如开发文档、api手册、数据库脚本等。
<!--[if !supportLists]-->· <!--[endif]-->growth/api.php为growth为外部程序提供的接口。文件内的代码是一个类,命名为AppsGrowthApi,类中方法均为静态方法,方法名采用驼峰格式,例如getGrowthPointByUid,方法名称要足以描述其功能。
<!--[if !supportLists]-->· <!--[endif]-->apps/common文件存放一些应用程序公用的文件,例如公用的js库,function库,类库等。
命名规范
程序命名规范
<!--[if !supportLists]-->· <!--[endif]-->文件名一律小写,单词间以下划线分隔
<!--[if !supportLists]-->· <!--[endif]-->类名采用首字母大写的驼峰命名方式
<!--[if !supportLists]-->· <!--[endif]-->类中的方法名采用首字母小写的驼峰方式命名
<!--[if !supportLists]-->· <!--[endif]-->类中的私有方法和私有变量以下划线开头
<!--[if !supportLists]-->· <!--[endif]-->函数名全小写,单词间以下划线分隔
<!--[if !supportLists]-->· <!--[endif]-->变量名同函数名
数据库命名规范
<!--[if !supportLists]-->· <!--[endif]-->数据表以uchome_app_作为前缀,例如uchome_app_growth_point
<!--[if !supportLists]-->· <!--[endif]-->字段名全为小写,以下划线分隔单词
<!--[if !supportLists]-->· <!--[endif]-->建议在建表时注明备注,方便理解字段用处
<!--[if !supportLists]-->· <!--[endif]-->对数据表结构的更改,请在当前应用的doc/sql目录下以日期为单位新建文件,记录更改。
【UCHome二次开发】模板机制
首先告诉大家一个小技巧,就是如何让系统每次自动更新缓存,免去每次修改模板后都要到后台更新缓存操作,记住,在解决完所有问题后,要在改回来,否则会大幅度提高服务器负担.
打开source/function_common.php文件,找到:
if(!file_exists($objfile)) {
include_once(S_ROOT.’./source/function_template.php’);
parse_template($tpl);
}
修改成:
//if(!file_exists($objfile)) {
include_once(S_ROOT.’./source/function_template.php’);
parse_template($tpl);
//}
这样修改模板后就不用到后台更新缓存了,改成这样的意思是无论是否存在缓存文件都将包含模板文件并生成新的缓存文件。
下面开始讲一下模板中常用的标签及变量输出。
一、变量:
如我们在PHP文件中定义了一个变量并赋值了,如:
$siteUrl=’http://www.demi.cn’;
$siteName=’祝君成功网站建设’;
那么如何在模板中输出呢?其实这个很简单:
站点地址:$siteUrl
站点名称:$siteName
就可以输出结果:
站点地址:http://www.demi.cn
站点名称:祝君成功网站建设
二、标签
UCHOME模板中一般含有以下标签
if标签,else标签,loop标签 ,eval标签
1、if标签和 else标签主要是判断标签,格式如下
<!—{if 条件}–>
//Your code here…
<!—{/if}–>
和
<!—{if 条件}–>
//Your code here…
<!—{else}–>
//Your code here…
<!—{/if}–>
以上的条件可以是变量及合法的PHP函数及自定义函数。
2、 loop标签
loop标签是循环输出数组的,如果你不懂数组,那么请自行参考相关资料。
格式一:
<!–{loop $s $key $value}–>
$value
<!–{/loop}–>
相当于PHP代码中
foreach($s as $key=>$value){
echo $value
}
格式二:
<!–{loop $s $value}–>
$value
<!–{/loop}–>
相当于PHP代码中
//住$s必须是二维数组。
foreach($s as $value){
echo $value
}
3、eval标签
eval标签主要是用来在模板中执行php语法,在eval后必须紧跟合法的PHP语法,如:
<!–{eval echo ‘这是PHP语法’;}–>
基本上UCHOME模板中的标签就这么几个,也是最常用的几个了
【UCHome二次开发】数据字典|数据库结构
数据字典即数据库中的表和字段的说明。找了好久才找到的,共享一下。
此版本的UCHome数据字典是基于UCenter Home 2.0beta,最后修订日期为2009.08.08。
uchome 2.0数据字典
数据字典形式为word文档,点击 UCHome 2.0 数据字典下载。
【UCHome二次开发】模板解析
UCHome模板文件位于/template文件夹下,每个模板文件单独一个文件夹,默认模板文件夹为default。
1、模板的使用配置
在根目录下的config.php中进行配
$_SC['template'] = 'default'; //选择模板目录
2、模板的处理
程序中使用到模板文件时,先去模板缓存目录/data/tpl_cache/下查找是否存储模板缓存文件。模板缓存文件命名合适为“template_模板目录名_模板文件名.php”。如存在则直接使用该缓存的模板文件;如不存在,则先解析对应的模板文件,生成模板缓存文件再进行使用。
3、模板的解析
模板解析是调用/source目录下的function_template.php文件中的parse_template函数来实现的。
解析过程并不复杂,主要是读取模板文件(.htm),用正则表达式替换标记为对应的PHP代码,最终生成一个标准的PHP文件,保存到模板缓存目录/data/tpl_cache/供后续使用。
具体的模板解析过程不做说明,直接查看代码即可。
置,确定系统使用的模板,如下:
function parse_template($tpl) {
global $_SGLOBAL;
//包含模板
$_SGLOBAL['sub_tpls'] = array($tpl);
$tplfile = S_ROOT.'./'.$tpl.'.htm';
$objfile = S_ROOT.'./data/tpl_cache/'.str_replace('/','_',$tpl).'.php';
//read
$template = sreadfile($tplfile);
if(empty($template)) {
exit("Template file : $tplfile Not found or have no access!");
}
//模板
$template = preg_replace("/\<\!\-\-\{template\s+([a-z0-9_\/]+)\}\-\-\>/ie", "readtemplate('\\1')", $template);
//处理子页面中的代码
$template = preg_replace("/\<\!\-\-\{template\s+([a-z0-9_\/]+)\}\-\-\>/ie", "readtemplate('\\1')", $template);
//解析模块调用
$template = preg_replace("/\<\!\-\-\{block\/(.+?)\}\-\-\>/ie", "blocktags('\\1')", $template);
//解析广告
$template = preg_replace("/\<\!\-\-\{ad\/(.+?)\}\-\-\>/ie", "adtags('\\1')", $template);
//时间处理
$template = preg_replace("/\<\!\-\-\{date\((.+?)\)\}\-\-\>/ie", "datetags('\\1')", $template);
//头像处理
$template = preg_replace("/\<\!\-\-\{avatar\((.+?)\)\}\-\-\>/ie", "avatartags('\\1')", $template);
//PHP代码
$template = preg_replace("/\<\!\-\-\{eval\s+(.+?)\s*\}\-\-\>/ies", "evaltags('\\1')", $template);
//开始处理
//变量
$var_regexp = "((\\\$[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)(\[[a-zA-Z0-9_\-\.\"\'\[\]\$\x7f-\xff]+\])*)";
$template = preg_replace("/\<\!\-\-\{(.+?)\}\-\-\>/s", "{\\1}", $template);
$template = preg_replace("/([\n\r]+)\t+/s", "\\1", $template);
$template = preg_replace("/(\\\$[a-zA-Z0-9_\[\]\'\"\$\x7f-\xff]+)\.([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)/s", "\\1['\\2']", $template);
$template = preg_replace("/\{(\\\$[a-zA-Z0-9_\[\]\'\"\$\.\x7f-\xff]+)\}/s", "<?=\\1?>", $template);
$template = preg_replace("/$var_regexp/es", "addquote('<?=\\1?>')", $template);
$template = preg_replace("/\<\?\=\<\?\=$var_regexp\?\>\?\>/es", "addquote('<?=\\1?>')", $template);
//逻辑
$template = preg_replace("/\{elseif\s+(.+?)\}/ies", "stripvtags('<?php } elseif(\\1) { ?>','')", $template);
$template = preg_replace("/\{else\}/is", "<?php } else { ?>", $template);
//循环
for($i = 0; $i < 5; $i++) {
$template = preg_replace("/\{loop\s+(\S+)\s+(\S+)\}(.+?)\{\/loop\}/ies", "stripvtags('<?php if(is_array(\\1)) { foreach(\\1 as \\2) { ?>','\\3<?php } } ?>')", $template);
$template = preg_replace("/\{loop\s+(\S+)\s+(\S+)\s+(\S+)\}(.+?)\{\/loop\}/ies", "stripvtags('<?php if(is_array(\\1)) { foreach(\\1 as \\2 => \\3) { ?>','\\4<?php } } ?>')", $template);
$template = preg_replace("/\{if\s+(.+?)\}(.+?)\{\/if\}/ies", "stripvtags('<?php if(\\1) { ?>','\\2<?php } ?>')", $template);
}
//常量
$template = preg_replace("/\{([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)\}/s", "<?=\\1?>", $template);
//替换
if(!empty($_SGLOBAL['block_search'])) {
$template = str_replace($_SGLOBAL['block_search'], $_SGLOBAL['block_replace'], $template);
}
//换行
$template = preg_replace("/ \?\>[\n\r]*\<\? /s", " ", $template);
//附加处理
$template = "<?php if(!defined('IN_UCHOME')) exit('Access Denied');?><?php subtplcheck('".implode('|', $_SGLOBAL['sub_tpls'])."', '$_SGLOBAL[timestamp]', '$tpl');?>$template<?php ob_out();?>";
//write
if(!swritefile($objfile, $template)) {
exit("File: $objfile can not be write!");
}
}
【UCHome二次开发】缓存机制解析
UCHome中的常用数据皆通过调用缓存来实现读取,包括系统配置、用户组、群组栏目、用户栏目、词语屏蔽、积分规则、广告、用户向导任务、模块、MYOP默认应用等信息。其中模板缓存的使用前面单独介绍过,见《【UCHome二次开发】模板解析》。
UCHome中常用数据是作为全局变量来使用的,具体用法可参考《【UCHome二次开发】全局变量》。以下着重介绍缓存机制的具体实现。
1、缓存数据文件的生成
UCHome生成的缓存数据文件位于/data/目录下。
缓存生成的相关函数位于/source/function_cache.php文件中,生成缓存的函数罗列如下:
- config_cache() 更新配置信息缓存,生成缓存文件data_config.php
- usergroup_cache() 更新用户组缓存,生成缓存文件data_usergroup.php
- profilefield_cache() 更新用户栏目缓存,生成缓存文件data_profilefield.php
- profield_cache() 更新群组栏目缓存,生成缓存文件data_profield.php
- censor_cache() 更新词语屏蔽缓存,生成缓存文件data_censor.php
- creditrule_cache() 更新积分规则,生成缓存文件data_creditrule.php
- ad_cache() 更新广告缓存,生成缓存文件data_ad.php
- task_cache() 更新用户向导任务,生成缓存文件data_task.php
- block_cache() 更新模块,生成缓存文件data_block.php
- tpl_cache() 更新模板缓存,清空模板缓存文件夹/data/tpl_cache/下所有文件使模板缓存重新生成
- block_data_cache() 更新模块缓存,清空模板缓存数据使缓存重新生成
- userapp_cache() 更新MYOP默认应用,生成缓存文件data_userapp.php
- app_cache() 更新应用名,生成缓存文件data_app.php
除了模板和模块数据外,其他的只需调用对应的函数就可生成对应的缓存数据文件。具体缓存生成的数据格式可查看对应文件。
2、缓存数据文件的分析
我们来看一下其中一个缓存文件,群组栏目缓存data_profield.php文件,如下:
<?php
if(!defined('IN_UCHOME')) exit('Access Denied');
$_SGLOBAL['profield']=Array
(
1 =>Array
(
'fieldid' => 1,
'title' => '班级',
'formtype' => 'multi',
'inputnum' => 100,
'mtagminnum' => 0,
'manualmoderator' => 1,
'manualmember' => 1
)
2 =>Array
(
'fieldid' => 2,
'title' => '实践活动',
'formtype' => 'text',
'inputnum' => 100,
'mtagminnum' => 0,
'manualmoderator' => 1,
'manualmember' => 1
)
)
?>
第二行代码保证了缓冲数据无法被直接调用,而要求在UCHome中才有效。当然这是君子协定,只要在调用代码前define一下IN_UCHOME即可绕过验证。
之后的代码其实只是做了变量赋值,将群组栏目数据赋值到$_SGLOBAL['profield']中,因为之前$_SGLOBAL以被定义为global全局变量,因为群组栏目数据便能全局访问了。
3、缓存数据文件的使用
从上面分析可看出,缓存数据文件其实就是php代码文件,直接引入执行。因而我们的缓存使用也就很方便了,只需将缓存文件使用include/include_once/require/require_once等函数引入进来即可使用,调用对应的变量来获取缓存的数据。
但为了保证缓存的存在,使用时最好加一个检测;如果缓存数据不存在,则先生成一遍缓存数据。综合起来,缓存的代码参考如下:
if(!@include_once(S_ROOT.'./data/data_usergroup.php')) {
include_once(S_ROOT.'./source/function_cache.php');
usergroup_cache();
}
调用不同的缓存请更换对应的缓存文件和缓冲函数。
4、缓存数据文件的手动更新
在管理员成员的后台高级管理里有一项是缓存更新,可用户手动更新缓存,在系统全局配置变动后建议手动做一次缓存更新。
【UCHome二次开发】模板语法说明
UCHome二次开发时,了解模板的语法是必须的,下面对其中的语法做一一介绍。至于模板的解析过程请参考《UCHome二次开发之模板解析》。
1、调用其他模板
<!--{template header}-->
说明:将以模板header.htm来替换此处的代码
2、调用头像
模板代码:
<!--{avatar($value[uid],small)}-->
解析后的代码:
<?php echo avatar($value[uid],small); ?>
3、调用广告
模板代码:
<!--{ad/header}-->
解析后的代码:
<?php adshow('header'); ?>
4、调用时间
模板代码:
<!--{date('Y-m-d H:i', $value[dateline], 1)}-->
解析后的代码:
<?php echo sgmdate('Y-m-d H:i', $value[dateline], 1); ?>
5、输出PHP代码
模板代码:
<!--{eval echo formhash();}-->
解析后的代码:
<?php echo formhash(); ?>
说明:<!–{eval和}–>之间的是需要执行的PHP代码,要求语句完整。
6、调用变量
模板代码:
<a href="space.php?uid=$value[uid]">{$_SN[$value[uid]]}</a>
解析后的代码:
<a href="space.php?uid=<?=$value['uid']?>"><?=$_SN[$value['uid']]?></a>
说明:{和}之间的是需要输出的变量。
7、选择输出逻辑
模板代码:
<!--{if empty($mtag['ismember']) && $mtag['joinperm'] < 2}-->
<li><a href="cp.php?ac=mtag&op=join&tagid=$mtag[tagid]" id="a_mtag_join_$mtag[tagid]" onclick="ajaxmenu(event, this.id, 99999)">加入群组</a></li>
<!--{elseif $mtag['allowpost']}-->
<li><a href="cp.php?ac=thread&tagid=$mtag[tagid]">发起话题</a></li>
<!--{/if}-->
解析后的代码:
<?php if(empty($mtag['ismember']) && $mtag['joinperm'] < 2) { ?>
<li><a href="cp.php?ac=mtag&op=join&tagid=<?=$mtag['tagid']?>" id="a_mtag_join_<?=$mtag['tagid']?>" onclick="ajaxmenu(event, this.id, 99999)">加入群组</a></li>
<?php } elseif($mtag['allowpost']) { ?>
<li><a href="cp.php?ac=thread&tagid=<?=$mtag['tagid']?>">发起话题</a></li>
<?php } ?>
说明:当然这里可以没有elseif,其语法有点类似VB,需要有结尾符。
8、循环输出逻辑
模板代码 1:
<!--{loop $list $key $value}-->
<tr <!--{if $key%2==1}--><!--{/if}-->>
<td>
<!--{if $value[displayorder]}--> [顶] <!--{/if}-->
<!--{if $value[digest]}--> [精] <!--{/if}-->
<a href="space.php?uid=$value[uid]&do=thread&id=$value[tid]">$value[subject]</a></td>
<td><a href="space.php?uid=$value[uid]">{$_SN[$value[uid]]}</a><br>$value[replynum]/$value[viewnum]</td>
<td><a href="space.php?uid=$value[lastauthorid]" title="{$_SN[$value[lastauthorid]]}">{$_SN[$value[lastauthorid]]}</a><br><!--{date('m-d H:i',$value[lastpost],1)}--></td>
</tr>
<!--{/loop}-->
解析后的代码 1:
<?php if(is_array($list)) { foreach($list as $key => $value) { ?>
<tr <?php if($key%2==1) { ?><?php } ?>>
<td>
<?php if($value['displayorder']) { ?> [顶] <?php } ?>
<?php if($value['digest']) { ?> [精] <?php } ?>
<a href="space.php?uid=<?=$value['uid']?>&do=thread&id=<?=$value['tid']?>"><?=$value['subject']?></a></td>
<td><a href="space.php?uid=<?=$value['uid']?>"><?=$_SN[$value['uid']]?></a><br><?=$value['replynum']?>/<?=$value['viewnum']?></td>
<td><a href="space.php?uid=<?=$value['lastauthorid']?>" title="<?=$_SN[$value['lastauthorid']]?>"><?=$_SN[$value['lastauthorid']]?></a><br><?php echo sgmdate('m-d H:i',$value[lastpost],1); ?></td>
</tr>
<?php } } ?>
说明:loop后跟三个参数时,第一个参数是用于循环的数组,第二个和第三个参数分别是对数组中每一项循环时项的键名和值。
模板代码 2:
<!--{loop $memberlist $value}-->
<li>
<div><a href="space.php?uid=$value[uid]"><img src="<!--{avatar($value[uid],small)}-->" alt="{$_SN[$value[uid]]}" /></a></div>
<p><a href="space.php?uid=$value[uid]">{$_SN[$value[uid]]}</a></p></li>
<!--{/loop}-->
解析后的代码 2:
<?php if(is_array($memberlist)) { foreach($memberlist as $value) { ?>
<li>
<div><a href="space.php?uid=<?=$value['uid']?>"><img src="<?php echo avatar($value[uid],small); ?>" alt="<?=$_SN[$value['uid']]?>" /></a></div>
<p><a href="space.php?uid=<?=$value['uid']?>"><?=$_SN[$value['uid']]?></a></p></li>
<?php } } ?>
说明:loop后跟两个参数时,第一个参数是用于循环的数组,第二个参数是对数组中每一项循环时项的值。
注:以上所有实例皆摘录自UCHome 1.5默认模板。对比一下模板代码和解析后的代码便可知语法的效果,所以文中不多解释。个人自习结果,如有不对之处欢迎拍砖。
【UCHome二次开发】模板页面说明
UCHome默认模板为default,位于/template/下。以下依次对各模板页面做简要说明,便于修改模板时查找。
cp_advance.htm 操作 高级管理 ,说明:个人设置-》高级管理
cp_album.htm 操作 相册,说明: 相册-》我的相册-》管理相册主界面,包括编辑相册、编辑图片、删除相册、删除图片
cp_application.htm 操作 群组申请表单
cp_apply.htm 操作 群组申请
cp_avatar.htm 操作 头像,说明: 个人设置-》我的头像
cp_blog.htm 操作 日志,说明: 日志-》我的日志-》发表新日志、编辑日志等操作
cp_class.htm 操作 分类,说明: 日志分类操作,日志-我的日志-右侧日志分类的编辑和删除
cp_comment.htm 操作 评论,说明: 评论的操作,包括编辑、删除、以及对别人评论的回复
cp_common.htm 操作 管理操作/举报违规/屏蔽指定通知
cp_credit.htm 操作 积分,说明: 个人设置-》积分
cp_doing.htm 操作 记录,说明: 心情记录-》回复或者删除
cp_domain.htm 操作 空间域名,说明: 设置个人二级域名-现在不用管
cp_feed.htm 操作 动态,说明: 删除某个动态以及,消息-》通知 某个通知后面图标表示的“屏蔽”
cp_friend.htm 操作 好友,说明: 对好友的所有操作 ,如列表、查找、批准等等
cp_header.htm 操作 页首导航,说明: 个人设置页面的头部 ,如我的头像、个人资料、主页风格等
cp_import.htm 操作 日志导入,说明: 日志-》发表日志-》导入
cp_invite.htm 操作 邮件邀请,说明: 页面最顶部-》“邀请”
cp_mtag.htm 操作 群组管理,说明: 群组的操作页面,包括新建、删除、修改等
cp_password.htm 操作 邮箱与密码设置,说明: 设置-》账号设置
cp_pm.htm 操作 短消息,说明: 最顶部-》消息 包括发 删
cp_poke.htm 操作 打招呼,说明: 打招呼 包括向别人打招呼 管理别人的招呼
cp_privacy.htm 操作 个人隐私设置,说明: 顶部-》隐私 (个人隐私设置)
cp_profile.htm 操作 个人资料,说明: 设置-》个人资料
cp_sendmail.htm 操作 邮件提醒设置,说明: 邮件相关
cp_share.htm 操作 分享,说明: 处理“分享”操作 例如在博客列表标题后点击分享弹出的界面
cp_space.htm 操作 隐藏应用
cp_task.htm 操作 有奖活动,说明: 参与活动 例如进入首页的 “更新个人头像”,等等。。
cp_theme.htm 操作 个人主页风格-CSS,说明: 设置-》主页风格
cp_thread.htm 操作 话题操作,说明: 群组中 “话题”的相关操作页面
cp_upload.htm 操作 图片上传,说明: 左侧 “相册”的上传链接
cp_userapp.htm 操作 管理应用,说明: 管理用户app应用 ,暂时不管
do_ajax.htm 说明: 一些ajax操作的结果界面
do_inputpwd.htm 密码验证
do_login.htm 登录界面,说明: 登陆 退出后 点击最顶部的“登录”
do_lostpasswd.htm 取回/重设密码,说明: 忘记密码
do_register.htm 注册帐号,说明: 退出后 点击最顶部的“注册”
do_swfupload.htm 上传头像,说明: 相册上传的 “批量操作”
footer.htm 页脚代码
header.htm 页首代码
help.htm 帮助
iframe.htm 框架页
index.htm 首页,说明: 首页—未登录状态的欢迎页面,聚合了blog、相册等
invite.htm 好友邀请,说明: 点击别人发过来的邀请链接后出现的界面
network_album.htm 随便看看 相片
network_blog.htm 随便看看 日志,博客
network_class.htm 随便看看 班级
network_doing.htm 随便看看 记录
network_header.htm 随便看看 页首,说明: 随便看看-顶部那几个链接
network_index.htm 随便看看,说明: 随便看看-全部
network_mtag.htm 随便看看 群组
network_share.htm 随便看看 分享
network_space.htm 随便看看 成员
network_thread.htm 随便看看 话题
sendmail.htm 系统邮件内容
showmessage.htm 信息提示
space_album_list.htm 相册 列表
space_album_pic.htm 相册 图片,说明: 查看某个照片的页面
space_album_view.htm 相册 查看,说明: 点击相册,列出该相册的照片(注:区分album和pic)
space_blog_list.htm 日志 列表
space_blog_view.htm 日志 查看,说明: 查看某博客内容
space_comment_li.htm 日志 评论,说明: 显示评论列表某条(这个在很多有评论功能的页面都引用了,用循环这个“小小”模板的方式列出所有评论)
space_doing.htm 记录,说明: 心情记录
space_feed.htm 好友动态,说明: 个人动态页面
space_feed_li.htm 好友动态 单条,说明: 个人动态列表(被包含在space_feed.htm里,用循环方式引用)
space_friend.htm 好友,说明: 点击顶部“好友”
space_guide.htm 空间启用向导,说明: 用户刚开通空间时候的向导页面,提示上传头像等
space_index.htm 个人首页,说明: 点击顶部“个人主页”
space_list.htm 说明: 用户列表(被network_space.htm包含)
space_menu.htm 说明: 个人空间顶部的链接菜单
space_mood.htm 同心情,说明: 个人主页-同心情的朋友
space_mtag.htm 群组首页,说明: 群组-我的群组
space_mtag_field.htm 群组分类,说明: 群组-热门群组(有群组分类)
space_mtag_index.htm 单个群组首页,说明:群组-进入某个群组
space_mtag_list.htm 群组 讨论区,说明: 群组-进入某个群组-讨论区
space_mtag_member.htm 群组 成员,说明: 群组-进入某个群组-成员列表
space_notice.htm 通知,说明:顶部-通知
space_pm.htm 私信,说明:顶部-通知-消息
space_post_li.htm 说明: 被space_thread_view.htm文件引用(被循环调用显示帖子)
space_privacy.htm 由于XX的隐私设置,你不能访问当前内容
space_rank.htm 排行榜
space_rss.htm RSS, 说明: 订阅的,不用管
space_share_li.htm 分享 单条, 说明: 分享-查看某条项目(被下面的space_share_list列表页循环引用)
space_share_list.htm 分享 列表
space_share_view.htm 分享 查看,说明: 查看某条分享的内容,在分享列表点评论的时候会出现
space_tag_list.htm 标签列表,说明: 打开某篇日志——标题下如果有标签——点击标签——标签列表
space_tag_view.htm 标签查看,说明: 查看某个标签
space_thread_list.htm 群组 话题列表,说明: 群组话题列表 点左侧的群组默认页面
space_thread_view.htm 群组 话题查看,说明: 查看某个主题
space_wall.htm 留言板,说明: 包括给自己留言给别人留言
userapp.htm 页面加载中提示,说明:用户添加应用或管理应用操作,不用管
【UCHome二次开发】主要文件说明
1、系统首页 /index.php
显示页面为/template/模板文件夹名/index.htm。
2、个人页面 /space.php
不带参数时显示个人首页;带uid参数(用户编号)为显示其他人的首页;do参数指示调用的模块,如/space.php?do=blog将显示日志内容。
带do参数页面的处理:/space.php?do=xxx将调用/source/space_xxx.php(其中xxx为相关模块或操作,下同)进行数据和逻辑处理,最终的页面是显示对应的模板页,为/template/模板文件夹名/space_xxx.htm。具体模板的解析请参考《【UCHome二次开发】模板解析》,下同。
3、随便看看页面 /network.php
不带参数时显示随便看看首页;带ac参数时显示某个模块的随便看看页面,如/network.php?ac=space为随便看看现有的成员。
带ac参数页面的处理:/network.php?ac=xxx将调用/source/network_xxx.php进行数据和逻辑处理,最终的页面是显示对应的模板页,为/template/模板文件夹名/network_xxx.htm。
4、操作页面 /cp.php
不带参数时显示个人设置页;带ac参数时显示某个操作的页面,如/cp.php?ac=profile为设置个人资料。
带ac参数页面的处理:/cp.php?ac=xxx将调用/source/cp_xxx.php进行数据和逻辑处理,最终的页面是显示对应的模板页,为/template/模板文件夹名/cp_xxx.htm。
5、动作页面 /do.php
不带参数时会被跳转到个人首页或系统首页(看是否已登录);带ac参数时为进行某项动作,不一定有显示的界面。
带ac参数页面的处理:/do.php?ac=xxx将调用/source/do_xxx.php进行数据和逻辑处理,最终的页面是显示对应的模板页,为/template/模板文件夹名/do_xxx.htm(不是所有的动作需要页面显示结果,所以不一定存在对应的模板文件)。为防止注册机等外挂软件的攻击,程序对于login和register做了单独处理,直接加在ac参数后是无效的,而是通过一串标识符来指示login或register动作。
6、高级管理页面 /admincp.php
不带参数时显示管理平台首页;带ac参数时显示某项功能的管理页面,如/admincp.php?ac=ad为广告设置页。
带ac参数页面的处理:/admincp.php?ac=xxx将调用/admin/admincp_xxx.php进行数据和逻辑处理,最终的页面是显示对应的模板页,为/admin/tpl/xxx.htm。
7、应用页面 /app.php
显示页面为/template/模板文件夹名/iframe.htm。
8、个人应用页面 /userapp.php
显示页面为/template/模板文件夹名/userapp.htm。
9、邀请加入页面 /invite.php
显示页面为/template/模板文件夹名/invite.htm。
10、RSS页面 /rss.php
显示页面为/template/模板文件夹名/space_rss.htm。
11、帮助页面 /help.php
显示页面为/template/模板文件夹名/help.htm。
12、通用代码 /common.php
缓存、Cookie、用户状态验证、各种状态初始化等通用处理。
13、配置文件 /config.php
数据库连接、系统编码、站点网址等全局性配置。
14、富文本编辑器 /editor.php
15、模块载入代码 /js.php
未发现使用的地方,所以不做解释。
16、连接显示页 /link.php
未发现使用的地方,所以不做解释。
17、xmlrpc服务 /xmlrpc.php
调用/source/class_xmlrpc.php来处理。关于XML-RPC的规范可看
【UCHome二次开发】模板修改
前一阵在做UCHome的一些修改以满足具体的应用,来做一点总结。涉及的修改都是些小功能或是界面的调整,所以主要涉及的是对于模板的修改,以下归纳一下过程和经验。
1、模板文件定位
确定要修改的模板文件这是第一步。
方法一:URL分析法。查看/config.php,$_SC['template']参数指示的是当前使用的模板文件夹。关于通过URL参数定位模板文件名的方法请参考《【UCHome二次开发】主要文件说明》。
方法二:模板缓存查看法。首先在浏览器中打开想要确定模板的页面,然后把模板缓存文件夹/data/tpl_cache/中的.php模板缓存文件全删掉,刷性浏览器,再次查看模板缓存文件夹便可看到新生产的页面模板缓存文件。根据模板缓存文件的命名规则“template_模板文件夹名_模板文件名.php”,可分析知模板文件名,从而定位到模板文件。至于此方法的缘由请参考《【UCHome二次开发】模板解析》。
方法三:查表法。确定页面的功能,通过查阅《【UCHome二次开发】模板页面说明》来确定页面对应的模板文件。
2、模板文件生效
特别强调,模板文件修改后,需要将模板缓存文件夹/data/tpl_cache/中对应的.php模板缓存文件删除后,才能生效;否则页面生成仍将使用先前缓存的模板文件,而无法看到修改后的结果。
这里提供一种方法,可以使修改模板文件后,不用手动删除缓存的模板文件就能直接看到修改结果。方法为修改/source/function_common.php中的代码
if(!file_exists($objfile)) {
改为
if(!file_exists($objfile)||filemtime($objfile)<filemtime(S_ROOT.'./'.$tpl.'.htm')) {
即可。
因为此方法增加了一次对文件系统的访问,一定程度上会影响性能,所以此处的修改只建议运用在调试服务器上。
3、模板文件修改
在不是很确定修改内容的前提下,建议通过修改缓存的模板文件来调试。因为模板缓存文件是php代码,对我们来说比较熟悉,调试起来相对方便,比如不知道某个变量的值,可以直接用print_r或var_dump打印出来查看。
通过对模板缓存文件的调试我们可以较快地定位我们要修改的地方,后面的修改就是根据UCHome模板语法对模板文件进行修改和测试了。相关的模板语法可参考《【UCHome二次开发】模板语法说明》。
【UCHome二次开发】功能修改
有些功能的修改涉及到了流程或数据需求的变动,这时候简单的修改模板文件已经无法解决问题,而是需要修改对应的流程和数据处理代码来完成。一般处理程序文件位于/source文件夹下,具体的定位请参考《【UCHome二次开发】主要文件说明》。具体的代码修改就是根据功能逻辑来调整php代码或是sql语句,这里就不展开了。下面举两个例子说明一下。
1、修改群组列表页面分页的每页显示条数
定位群组数据处理页面为/source/space_mtag.php,找到如下代码:
$perpage = 20
修改中间的数据为希望显示的条数即可。
2、修改群组列表页面单个群组提示
默认情况下,群组列表页面每个群组链接下方只提示有多少人参加了群组。如下图:

群组列表修改前界面
现在希望没有加入的群组显示 申请加入 链接,且显示已申请人数;已申请未通过的群组给出已申请,等待审核 提示;已加入的群组按原来的提示,显示已加入的人数。
打印原来的数组数据,发现数据中没有申请中的人数和是否已加入群组的状态信息。于是便需要修改sql语句来获取想要的数据。在/source/space_mtag.php文件中,修改代码
$query = $_SGLOBAL['db']->query("SELECT * FROM ".$tablemtag." WHERE fieldid='$id' ORDER BY membernum DESC LIMIT $start,$perpage");
改为
$query = $_SGLOBAL['db']->query("SELECT mtag.*, x.applynum, y.grade FROM ".tname('mtag')." mtag LEFT JOIN ( SELECT count( uid ) AS applynum, tagid FROM `".tname('tagspace')."` WHERE grade = '-2' GROUP BY tagid ) AS x ON x.tagid = mtag.tagid LEFT JOIN ( SELECT * FROM uch_tagspace WHERE uid = ".$_SGLOBAL['session']['uid']." )y ON y.tagid = mtag.tagid WHERE mtag.fieldid = '$id' ORDER BY y.grade DESC, membernum DESC LIMIT $start,$perpage");
通过以上修改,使SQL查询的返回结果增加了各个群组的申请中人数和当前用户在各个群组中的状态。
有了数据,再需要通过修改模板页面来改变显示内容。
找到群组分类的显示模板为space_mtag_field.htm,修改模板中群组列表的显示代码,如下:
<div class="box">
<!--{if $list}-->
<ul class="thread_list">
<!--{loop $list $value}-->
<li>
<div class="threadimg60"><a href="space.php?do=mtag&tagid=$value[tagid]"><img src="$value[pic]" style="width:60px;"></a></div>
<a href="space.php?do=mtag&tagid=$value[tagid]">$value[tagname]</a><br />
已有 <span class="num">$value[membernum]</span> 人加入
</li>
<!--{/loop}-->
</ul>
<div class="page">$multi</div>
<!--{else}-->
<p>还没有群组。</p>
<!--{/if}-->
</div>
修改为
<div class="box">
<!--{if $list}-->
<ul class="thread_list">
<!--{loop $list $value}-->
<li>
<div class="threadimg60"><a href="space.php?do=mtag&tagid=$value[tagid]"><img src="$value[pic]" style="width:60px;"></a></div>
<a href="space.php?do=mtag&tagid=$value[tagid]">$value[tagname]</a>
<!--{if in_array($value[fieldid], $_FD[conf][veri_fieldids])}-->
<!--{if ($value[fieldid] == 4 || $value[fieldid] == 5) }-->
<!--{if isset($value[grade]) }-->
<!--{if $value[grade] == -2}-->
<br /><span class="num">已提交申请,正等待审核</span>
<!--{else}-->
<br />已有 <span class="num">$value[membernum]</span> 人加入
<!--{/if}-->
<!--{else}-->
<!--{if $value[applynum]}-->
<br />已有 <span class="num">$value[applynum]</span> 人申请
<!--{else}-->
<br />暂时无人申请
<!--{/if}-->
<br /><a href="cp.php?ac=apply&tagid=$value[tagid]">申请加入</a>
<!--{/if}-->
<!--{/if}-->
<!--{else}-->
<br />已有 <span class="num">$value[membernum]</span> 人加入
<!--{/if}-->
</li>
<!--{/loop}-->
</ul>
<div class="page">$multi</div>
<!--{else}-->
<p>还没有群组。</p>
<!--{/if}-->
</div>
修改完成后,效果如下:

群组列表修改后界面
3、增加某些分类的群组申请个数限制
由于项目需求,需要限定读书小组限报一个群组,启航计划限报两个群组,需要做群组加入流程的改动。
找到群组申请相关代码,位于/source/space_mtag.php,如下代码块:
elseif($_GET['op'] == 'join') {
$tagid = empty($_GET['tagid'])?0:intval($_GET['tagid']);
if(submitcheck('joinsubmit')) {
$mtag = mtag_join('tagid', $tagid);
if(empty($mtag)) {
showmessage('mtag_join_error');
} else {
showmessage('join_success', "space.php?uid=$_SGLOBAL[supe_uid]&do=mtag&tagid=$mtag[tagid]", 0);
}
}
}
需要插入一段代码来改变处理流程,具体为在加入群组前增加已申请群组个数的检验,修改后代码如下:
elseif($_GET['op'] == 'join') {
$tagid = empty($_GET['tagid'])?0:intval($_GET['tagid']);
// 获取$fieldid
$wheresql = "main.tagid='$tagid'";
$query = $_SGLOBAL['db']->query("SELECT * FROM ".tname('mtag')." main WHERE $wheresql");
if($mtag = $_SGLOBAL['db']->fetch_array($query)) {
$fieldid = $mtag['fieldid'];
}
// 限定读书小组(fieldid=4, num=1)与启航行动(fieldid=5, num=2)的人数
$t_tagspace = tname('tagspace');
$t_mtag = tname('mtag');
$count = $_SGLOBAL['db']->result($_SGLOBAL['db']->query("SELECT count(*) FROM $t_tagspace inner join $t_mtag on $t_tagspace.`tagid` = $t_mtag.`tagid` WHERE $t_tagspace.uid = ".$_SGLOBAL['session']['uid']." and $t_mtag.`fieldid` = $fieldid"),0);
if ($fieldid == 4 && $count >= 1){
showmessage('读书小组只能申请或参加 1 个');
}
else if ($fieldid == 5 && $count >= 2){
showmessage('启航行动只能申请或参加 2 个');
}
if(submitcheck('joinsubmit')) {
$mtag = mtag_join('tagid', $tagid);
if(empty($mtag)) {
showmessage('mtag_join_error');
} else {
showmessage('join_success', "space.php?uid=$_SGLOBAL[supe_uid]&do=mtag&tagid=$mtag[tagid]", 0);
}
}
}
4、修改群组分类下的分类名称和显示分类个数
默认安装完后,群组分类中显示的是自由联盟、区域联盟、兴趣联盟,即使我们通过管理系统修改了群组分类的名称,页面上的群组分类页不改变。如下图所示:

默认情况下的群组分类
通过调试代码发现群组分类的显示内容是写到数据文件里的,对应为/data/data_profield.php文件,文件内容(默认情况)如下:
<?php
if(!defined('IN_UCHOME')) exit('Access Denied');
$_SGLOBAL['profield']=Array
(
1 => Array
(
'fieldid' => 1,
'title' => '自由联盟',
'formtype' => 'text',
'inputnum' => 100,
'mtagminnum' => 0,
'manualmoderator' => 0,
'manualmember' => 1
),
2 => Array
(
'fieldid' => 2,
'title' => '地区联盟',
'formtype' => 'text',
'inputnum' => 100,
'mtagminnum' => 0,
'manualmoderator' => 0,
'manualmember' => 1
),
3 => Array
(
'fieldid' => 3,
'title' => '兴趣联盟',
'formtype' => 'text',
'inputnum' => 100,
'mtagminnum' => 0,
'manualmoderator' => 0,
'manualmember' => 1
)
)
?>
直接修改代码即可。改完的效果见前面的图。
以上举了4个列子来说明对UCHome功能进行修改的思路。其他的小改动相信也类似,同理类推。
本文链接:http://witmax.cn/uchome-function-modify.html
http://wyoojune.blog.163.com/blog/static/5709332520107245941477/