phpbb好像用的是模版(不确定)
但是IPB用的一定是模版,而且IPB的代码那叫一个高,90%符合w3c标准,你可以参考一下,个人觉得他要比diciz什么的强多了,要不你拿diciz(是这么写的吧?呵呵)到www.w3.org去校验一下,肯定是50%不符。
但是IPB用的一定是模版,而且IPB的代码那叫一个高,90%符合w3c标准,你可以参考一下,个人觉得他要比diciz什么的强多了,要不你拿diciz(是这么写的吧?呵呵)到www.w3.org去校验一下,肯定是50%不符。
调试欢乐多
权限部分可以单独做一个表,每个用户组的删除,浏览,修改,等权限做为记录
读的时候取得用户组,然后将该组权限存入session,使用时与相关页面的权限进行比较
多风格部分用css来实现应该可以,做成几套CSS,用时只需改变相应风格的CSS路径,
phpbb是一个很完善的论坛程序。搂住所需要的功能里面基本都有。我建议先去看看这个。
可以。phplib可以很好的达到此目的,而Smarty反倒不行用户分组,可分别设置用户组在论坛/分类中的浏览,发表,编辑和删除权限
设置用户组在论坛/分类中权限即可,用户继承用户组的权限支持多风格选择,可按系统,论坛/分类,用户设定风格
因为用模板,所以很容易。不同的风格用不同的模板支持缓存功能
有问题。只能缓存静态页面,即模板的输出结果。IP过滤功能
可以。按段存储要过滤的ip文章,论坛等模块可分别指定是否在内网(局域网)和外网(INTERNET)发布显示
可以。按ip区分论坛支持无限分类版块,并可设置版主
分类版块按贴子方式管理支持精华帖子
可复制帖子到专用表,也可仅在专用表中保存帖子id和版块分类号快速回复/发表主题功能贴图功能及表情图标
最好用ubb
这是phpbb的模板类,与phplib的相似!
<?php
/***************************************************************************
* template.php
* -------------------
* begin : Saturday, Feb 13, 2001
* copyright : (C) 2001 The phpBB Group
* email : [email protected]
*
* $Id: template.php,v 1.10.2.3 2002/12/21 19:09:57 psotfx Exp $
*
*
***************************************************************************//***************************************************************************
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
***************************************************************************//**
* Template class. By Nathan Codding of the phpBB group.
* The interface was originally inspired by PHPLib templates,
* and the template file formats are quite similar.
*
*/class Template {
var $classname = "Template"; // variable that holds all the data we'll be substituting into
// the compiled templates.
// ...
// This will end up being a multi-dimensional array like this:
// $this->_tpldata[block.][iteration#][child.][iteration#][child2.][iteration#][variablename] == value
// if it's a root-level variable, it'll be like this:
// $this->_tpldata[.][0][varname] == value
var $_tpldata = array(); // Hash of filenames for each template handle.
var $files = array(); // Root template directory.
var $root = ""; // this will hash handle names to the compiled code for that handle.
var $compiled_code = array(); // This will hold the uncompiled code for that handle.
var $uncompiled_code = array(); /**
* Constructor. Simply sets the root dir.
*
*/
function Template($root = ".")
{
$this->set_rootdir($root);
} /**
* Destroys this template object. Should be called when you're done with it, in order
* to clear out the template data so you can load/parse a new template set.
*/
function destroy()
{
$this->_tpldata = array();
} /**
* Sets the template root directory for this Template object.
*/
function set_rootdir($dir)
{
if (!is_dir($dir))
{
return false;
} $this->root = $dir;
return true;
} /**
* Sets the template filenames for handles. $filename_array
* should be a hash of handle => filename pairs.
*/
function set_filenames($filename_array)
{
if (!is_array($filename_array))
{
return false;
} reset($filename_array);
while(list($handle, $filename) = each($filename_array))
{
$this->files[$handle] = $this->make_filename($filename);
} return true;
}
/**
* Load the file for the handle, compile the file,
* and run the compiled code. This will print out
* the results of executing the template.
*/
function pparse($handle)
{
if (!$this->loadfile($handle))
{
die("Template->pparse(): Couldn't load template file for handle $handle");
} // actually compile the template now.
if (!isset($this->compiled_code[$handle]) || empty($this->compiled_code[$handle]))
{
// Actually compile the code now.
$this->compiled_code[$handle] = $this->compile($this->uncompiled_code[$handle]);
} // Run the compiled code.
eval($this->compiled_code[$handle]);
return true;
} /**
* Inserts the uncompiled code for $handle as the
* value of $varname in the root-level. This can be used
* to effectively include a template in the middle of another
* template.
* Note that all desired assignments to the variables in $handle should be done
* BEFORE calling this function.
*/
function assign_var_from_handle($varname, $handle)
{
if (!$this->loadfile($handle))
{
die("Template->assign_var_from_handle(): Couldn't load template file for handle $handle");
} // Compile it, with the "no echo statements" option on.
$_str = "";
$code = $this->compile($this->uncompiled_code[$handle], true, '_str'); // evaluate the variable assignment.
eval($code);
// assign the value of the generated variable to the given varname.
$this->assign_var($varname, $_str); return true;
} /**
* Block-level variable assignment. Adds a new block iteration with the given
* variable assignments. Note that this should only be called once per block
* iteration.
*/
function assign_block_vars($blockname, $vararray)
{
if (strstr($blockname, '.'))
{
// Nested block.
$blocks = explode('.', $blockname);
$blockcount = sizeof($blocks) - 1;
$str = '$this->_tpldata';
for ($i = 0; $i < $blockcount; $i++)
{
$str .= '[\'' . $blocks[$i] . '.\']';
eval('$lastiteration = sizeof(' . $str . ') - 1;');
$str .= '[' . $lastiteration . ']';
}
// Now we add the block that we're actually assigning to.
// We're adding a new iteration to this block with the given
// variable assignments.
$str .= '[\'' . $blocks[$blockcount] . '.\'][] = $vararray;'; // Now we evaluate this assignment we've built up.
eval($str);
}
else
{
// Top-level block.
// Add a new iteration to this block with the variable assignments
// we were given.
$this->_tpldata[$blockname . '.'][] = $vararray;
} return true;
} /**
* Root-level variable assignment. Adds to current assignments, overriding
* any existing variable assignment with the same name.
*/
function assign_vars($vararray)
{
reset ($vararray);
while (list($key, $val) = each($vararray))
{
$this->_tpldata['.'][0][$key] = $val;
} return true;
} /**
* Root-level variable assignment. Adds to current assignments, overriding
* any existing variable assignment with the same name.
*/
function assign_var($varname, $varval)
{
$this->_tpldata['.'][0][$varname] = $varval; return true;
}
/**
* Generates a full path+filename for the given filename, which can either
* be an absolute name, or a name relative to the rootdir for this Template
* object.
*/
function make_filename($filename)
{
// Check if it's an absolute or relative path.
if (substr($filename, 0, 1) != '/')
{
$filename = phpbb_realpath($this->root . '/' . $filename);
} if (!file_exists($filename))
{
die("Template->make_filename(): Error - file $filename does not exist");
} return $filename;
}
/**
* If not already done, load the file for the given handle and populate
* the uncompiled_code[] hash with its code. Do not compile.
*/
function loadfile($handle)
{
// If the file for this handle is already loaded and compiled, do nothing.
if (isset($this->uncompiled_code[$handle]) && !empty($this->uncompiled_code[$handle]))
{
return true;
} // If we don't have a file assigned to this handle, die.
if (!isset($this->files[$handle]))
{
die("Template->loadfile(): No file specified for handle $handle");
} $filename = $this->files[$handle]; $str = implode("", @file($filename));
if (empty($str))
{
die("Template->loadfile(): File $filename for handle $handle is empty");
} $this->uncompiled_code[$handle] = $str; return true;
}
* Compiles the given string of code, and returns
* the result in a string.
* If "do_not_echo" is true, the returned code will not be directly
* executable, but can be used as part of a variable assignment
* for use in assign_code_from_handle().
*/
function compile($code, $do_not_echo = false, $retvar = '')
{
// replace \ with \\ and then ' with \'.
$code = str_replace('\\', '\\\\', $code);
$code = str_replace('\'', '\\\'', $code); // change template varrefs into PHP varrefs // This one will handle varrefs WITH namespaces
$varrefs = array();
preg_match_all('#\{(([a-z0-9\-_]+?\.)+?)([a-z0-9\-_]+?)\}#is', $code, $varrefs);
$varcount = sizeof($varrefs[1]);
for ($i = 0; $i < $varcount; $i++)
{
$namespace = $varrefs[1][$i];
$varname = $varrefs[3][$i];
$new = $this->generate_block_varref($namespace, $varname); $code = str_replace($varrefs[0][$i], $new, $code);
} // This will handle the remaining root-level varrefs
$code = preg_replace('#\{([a-z0-9\-_]*?)\}#is', '\' . ( ( isset($this->_tpldata[\'.\'][0][\'\1\']) ) ? $this->_tpldata[\'.\'][0][\'\1\'] : \'\' ) . \'', $code); // Break it up into lines.
$code_lines = explode("\n", $code); $block_nesting_level = 0;
$block_names = array();
$block_names[0] = "."; // Second: prepend echo ', append ' . "\n"; to each line.
$line_count = sizeof($code_lines);
for ($i = 0; $i < $line_count; $i++)
{
$code_lines[$i] = chop($code_lines[$i]);
if (preg_match('#<!-- BEGIN (.*?) -->#', $code_lines[$i], $m))
{
$n[0] = $m[0];
$n[1] = $m[1]; // Added: dougk_ff7-Keeps templates from bombing if begin is on the same line as end.. I think. :)
if ( preg_match('#<!-- END (.*?) -->#', $code_lines[$i], $n) )
{
$block_nesting_level++;
$block_names[$block_nesting_level] = $m[1];
if ($block_nesting_level < 2)
{
// Block is not nested.
$code_lines[$i] = '$_' . $n[1] . '_count = ( isset($this->_tpldata[\'' . $n[1] . '.\']) ) ? sizeof($this->_tpldata[\'' . $n[1] . '.\']) : 0;';
$code_lines[$i] .= "\n" . 'for ($_' . $n[1] . '_i = 0; $_' . $n[1] . '_i < $_' . $n[1] . '_count; $_' . $n[1] . '_i++)';
$code_lines[$i] .= "\n" . '{';
}
else
{
// This block is nested. // Generate a namespace string for this block.
$namespace = implode('.', $block_names);
// strip leading period from root level..
$namespace = substr($namespace, 2);
// Get a reference to the data array for this block that depends on the
// current indices of all parent blocks.
$varref = $this->generate_block_data_ref($namespace, false);
// Create the for loop code to iterate over this block.
$code_lines[$i] = '$_' . $n[1] . '_count = ( isset(' . $varref . ') ) ? sizeof(' . $varref . ') : 0;';
$code_lines[$i] .= "\n" . 'for ($_' . $n[1] . '_i = 0; $_' . $n[1] . '_i < $_' . $n[1] . '_count; $_' . $n[1] . '_i++)';
$code_lines[$i] .= "\n" . '{';
} // We have the end of a block.
unset($block_names[$block_nesting_level]);
$block_nesting_level--;
$code_lines[$i] .= '} // END ' . $n[1];
$m[0] = $n[0];
$m[1] = $n[1];
}
else
{
// We have the start of a block.
$block_nesting_level++;
$block_names[$block_nesting_level] = $m[1];
if ($block_nesting_level < 2)
{
// Block is not nested.
$code_lines[$i] = '$_' . $m[1] . '_count = ( isset($this->_tpldata[\'' . $m[1] . '.\']) ) ? sizeof($this->_tpldata[\'' . $m[1] . '.\']) : 0;';
$code_lines[$i] .= "\n" . 'for ($_' . $m[1] . '_i = 0; $_' . $m[1] . '_i < $_' . $m[1] . '_count; $_' . $m[1] . '_i++)';
$code_lines[$i] .= "\n" . '{';
}
else
{
// This block is nested. // Generate a namespace string for this block.
$namespace = implode('.', $block_names);
// strip leading period from root level..
$namespace = substr($namespace, 2);
// Get a reference to the data array for this block that depends on the
// current indices of all parent blocks.
$varref = $this->generate_block_data_ref($namespace, false);
// Create the for loop code to iterate over this block.
$code_lines[$i] = '$_' . $m[1] . '_count = ( isset(' . $varref . ') ) ? sizeof(' . $varref . ') : 0;';
$code_lines[$i] .= "\n" . 'for ($_' . $m[1] . '_i = 0; $_' . $m[1] . '_i < $_' . $m[1] . '_count; $_' . $m[1] . '_i++)';
$code_lines[$i] .= "\n" . '{';
}
}
}
else if (preg_match('#<!-- END (.*?) -->#', $code_lines[$i], $m))
{
// We have the end of a block.
unset($block_names[$block_nesting_level]);
$block_nesting_level--;
$code_lines[$i] = '} // END ' . $m[1];
}
else
{
// We have an ordinary line of code.
if (!$do_not_echo)
{
$code_lines[$i] = 'echo \'' . $code_lines[$i] . '\' . "\\n";';
}
else
{
$code_lines[$i] = '$' . $retvar . '.= \'' . $code_lines[$i] . '\' . "\\n";';
}
}
} // Bring it back into a single string of lines of code.
$code = implode("\n", $code_lines);
return $code ; }
/**
* Generates a reference to the given variable inside the given (possibly nested)
* block namespace. This is a string of the form:
* ' . $this->_tpldata['parent'][$_parent_i]['$child1'][$_child1_i]['$child2'][$_child2_i]...['varname'] . '
* It's ready to be inserted into an "echo" line in one of the templates.
* NOTE: expects a trailing "." on the namespace.
*/
function generate_block_varref($namespace, $varname)
{
// Strip the trailing period.
$namespace = substr($namespace, 0, strlen($namespace) - 1); // Get a reference to the data block for this namespace.
$varref = $this->generate_block_data_ref($namespace, true);
// Prepend the necessary code to stick this in an echo line. // Append the variable reference.
$varref .= '[\'' . $varname . '\']'; $varref = '\' . ( ( isset(' . $varref . ') ) ? ' . $varref . ' : \'\' ) . \''; return $varref; }
/**
* Generates a reference to the array of data values for the given
* (possibly nested) block namespace. This is a string of the form:
* $this->_tpldata['parent'][$_parent_i]['$child1'][$_child1_i]['$child2'][$_child2_i]...['$childN']
*
* If $include_last_iterator is true, then [$_childN_i] will be appended to the form shown above.
* NOTE: does not expect a trailing "." on the blockname.
*/
function generate_block_data_ref($blockname, $include_last_iterator)
{
// Get an array of the blocks involved.
$blocks = explode(".", $blockname);
$blockcount = sizeof($blocks) - 1;
$varref = '$this->_tpldata';
// Build up the string with everything but the last child.
for ($i = 0; $i < $blockcount; $i++)
{
$varref .= '[\'' . $blocks[$i] . '.\'][$_' . $blocks[$i] . '_i]';
}
// Add the block reference for the last child.
$varref .= '[\'' . $blocks[$blockcount] . '.\']';
// Add the iterator for the last child if requried.
if ($include_last_iterator)
{
$varref .= '[$_' . $blocks[$blockcount] . '_i]';
} return $varref;
}}?>
我一直在研究这个论坛的程序。真是无可挑剔。
我一直没有自己设计过类,所以想老大再展开来说一说.我先说,有什么不对请予以纠正,谢谢了. 数据库类:应该是做一个连接数据库的构造函数,再就是一些基本处理,如发表新帖,回复帖子,更新帖子,删除帖子,转移帖子,帖子置顶等等一些和数据操作有关的函数
模板类:我想的除了PHPLIB中的TEMPLATE类,还有其它的吗??是不是那处理输出页面的也写成一个类?
用户类:处理用户的权限,可能包括在某一版块的权限,及在某些页面栏目中的权限等一些权限管理函数
工具类:如一些文本的处理,还有UBB的处理,还有可能的话,可以弄个发帖积分制,都处理在这个类里. 以上是我的一个粗略理解,不知道是不是正确,希望老大指点,多谢.
我说说我写的时候:
一个Forum类,初始化模板啊路径啊之类的
一个DB类
一个模板类,其实我是直接用PHP的,没有任何模板概念,贴一下我所谓的模板类。
一个Session类
一个Member类
用户权限可以看我的这篇
http://community.csdn.net/Expert/FAQ/FAQ_Index.asp?id=197788我现在使用的模板类:<?php /**
* @author 深空(shenkong) <[email protected]>
* @desc 模板类
* @copyright 深空(shenkong)版权所有,任何人使用和修改都必须保留此版权信息
*/
class Template
{
private $templates;
private $tplPath;
private $defaultTplPath;
private $s;
function __construct()
{
global $session;
$this->s = $session;
$this->templates = array();
$this->tplPath();
}
/**
* @return void
* @param string $templates
* @desc 添加,设置显示所需要的模板
*/
function addTemplate($templates)
{
$templates = explode(",", $templates);
foreach ($templates as $template)
{
$this->templates[] = trim($template);
}
}
function setTplName($tplName)
{
$this->s->set("tplName", $tplName);
}
function tplPath()
{
$this->tplPath = TEMPLATEPATH . $this->s->get("tplName") . DIRECTORY_SEPARATOR;
$this->defaultTplPath = TEMPLATEPATH . "default" . DIRECTORY_SEPARATOR;
}
function execute()
{
reset($this->templates);
foreach ($this->templates as $templeteFile)
{
$this->run($templeteFile);
}
} function run($templeteFile)
{
if (! @ include_once $this->tplPath . $templeteFile . TPL)
{
require_once $this->defaultTplPath . $templeteFile . TPL;
}
}
}?>使用很方便:D:D$template = new Template();
$template->addTemplate("header, main, footer");
$template->execute();另外给出一个我的IP过滤函数-_-b
/**
* @author 深空(shenkong) <[email protected]>
* @return bool
* @param string $ip
* @desc 根据拒绝 IP 列表文件,判断 $ip 是否在拒绝列表中
* @copyright 深空(shenkong)版权所有,任何人使用和修改都必须保留此版权信息
*/
function banned($ip)
{
// 被禁止的 IP 文件,每个禁止 IP 一行,比如
// 192.168.0.*
// 192.168.1.5
$filename = DATAPATH . "banned.ips"; // 看看文件在不在
if ($bannedIPs = @ file($filename))
{
// 读出所有行数组
if (is_array($bannedIPs))
{
foreach ($bannedIPs as $bannedIP)
{
// 去掉换行等空白,没有这句不行的
$bannedIP = trim($bannedIP); // 如果找到匹配,跳出 foreach 循环
if (preg_match("/$bannedIP/", $ip))
{
return true;
break;
}
}
}
}
}
大多数集成工具包中都含有此类(data source),没有必要自行开发。而是使用自己最熟悉的作为基类派生出数据层(data set)。诸如发表新帖,回复帖子,更新帖子,删除帖子,转移帖子,帖子置顶等等就集成在这里。 模板类:我想的除了PHPLIB中的TEMPLATE类,还有其它的吗??是不是那处理输出页面的也写成一个类?
是的。TEMPLATE类只提供了填写模板的功能(即怎么做),但没有解决“做什么”。所以我们需要在data set和template间建立一个通道,用以实现我们的目的 用户类:处理用户的权限,可能包括在某一版块的权限,及在某些页面栏目中的权限等一些权限管理函数
这实际上是模板类的一个特例。 工具类:如一些文本的处理,还有UBB的处理,还有可能的话,可以弄个发帖积分制,都处理在这个类里.
这实际上是一个函数库。如果封装成类,一般也无须实例化(class::method)。使用“面向对象”的方法来开发系统的一个好处是:最初,你只需书写简单的代码甚至不书写代码而只提供空方法,就构建出整个框架。这样你就可以在开发初期就发现系统的缺陷,而避免日后的返工
置顶(时间限制)
回帖匿名
帖子对回帖人进行限制,对看贴人也进行限制
帖子标题用彩色
道具(类似mop里的道具)
最好能和ftp帐号连起来
附加功能接口(银行,股票等)
真是不研究不知道,一研究原来其中还有这么多的东东在里头.同时谢谢深空的那两个类, 我觉得老大的思路特别棒,特别适合我的口胃,
因为我一直用别人的类,没有做过自己的类,现在很想趁这个机会好好体验一下自己的东西.
另外一方面,我想做的这个论坛功能比较齐全,而且要留下可扩展的空间.陈辉还觉得老大说的长了,不晓得是不是我水平不够呢?
我有点儿得寸进尺,还想知道更多更好多详尽的关于这些类的信息.引用老大之言:
1.大多数集成工具包中都含有此类(data source),没有必要自行开发。而是使用自己最熟悉的作为基类派生出数据层(data set)。
2.这实际上是模板类的一个特例老大说的工具包是不是就是PHPLIB中的数据库类啊?
你说的最最熟悉的基类派生出数据层,这里的数据层是什么呀?
不太明白老大所说的模版类的特例,能详细点吗?不好意思,麻烦老大了.
但是分离又有一个问题,php应该完全和html分开,php中避免出现html代码,那我那些html链接代码在循环中应该怎么放?
另外,我看discuz好像是用的eval来转换的,那不是phplib模板,不知道哪个好。
1.大多数集成工具包中都含有此类(data source),没有必要自行开发。而是使用自己最熟悉的作为基类派生出数据层(data set)。
2.这实际上是模板类的一个特例老大说的工具包是不是就是PHPLIB中的数据库类啊?
是的,当然还有pear db、adodb等等,不一定拘泥拿一个。这些数据库类把具体的数据库操作抽象成了一个虚拟的数据库,所以当你用他们来操作数据库时,并不需要关心你操作的是mysql还是sql server还是其他的什么。你说的最最熟悉的基类派生出数据层,这里的数据层是什么呀?
上面说到,数据库类提供了数据库无关。在实际的项目中,你可能要用到几张甚至几十张表。可以设想,当你的项目进行调整时或你想把一个成功的项目用于其他的项目时,实际具体的表操作的修改将是巨大的。而数据层就可以较好的解决这个问题。数据层把具体的表操作掩盖了起来,而以同一的格式向其他模块提供数据。不知说清楚了没有?不太明白老大所说的模版类的特例,能详细点吗?
我说“用户类”是模板类的特例是基于以下理由的:
1、用户类包含的功能很多,绝不仅是login文件
2、用户类包含了一个可与用户交互的网站的几乎所有元素,数据库操作、输入、输出、修改、浏览...
可以说“用户类”是一个bbs的缩影
其它的PEAR,DB和ADODB之类的,我都不太知道耶,
那我是不是很难完成这项开发了呢?你说的最最熟悉的基类派生出数据层,这里的数据层是什么呀?
上面说到,数据库类提供了数据库无关。在实际的项目中,你可能要用到几张甚至几十张表。可以设想,当你的项目进行调整时或你想把一个成功的项目用于其他的项目时,实际具体的表操作的修改将是巨大的。而数据层就可以较好的解决这个问题。数据层把具体的表操作掩盖了起来,而以同一的格式向其他模块提供数据。不知说清楚了没有?这一点我想我是明白了一点,你说的操作数据库的类其实只做方法,而不是加入具体数据操作语句,这样子功能模块移植的时候就方便许多了,对吧.
数据操作一块应该交由业务层来完成,这里如用户类和forum类
完成相关框架定义后,主体部分应该好理解一些//伪码类似如下
$forum = new forum ();
$forum->addThread($title,$content,$postTime);
$forum->replyThread($title,$content,$postTime,$threadId);
------------------------------
$member = new member();
$member->login();
$mmember->sendMessage();
--------------------------------
而这些类和方法的定义应在业务层来实现,
做论坛比较合适。