提交数据时提示:表单令牌错误。奶奶的,找了半天发现这个令牌是用来防止远程提交的。也不知道这编辑哪里和他冲突了。
在显示页面里 View类会替换一些公共的,特殊的变量,在View.clss.php 第311行定义了: 
protected function templateContentReplace($content) {
        // 系统默认的特殊变量替换
        $replace =  array(
            ‘../Public’   => APP_PUBLIC_PATH,// 项目公共目录
            ‘__PUBLIC__’  => WEB_PUBLIC_PATH,// 站点公共目录
            ‘__TMPL__’    => APP_TMPL_PATH,  // 项目模板目录
            ‘__ROOT__’    => __ROOT__,       // 当前网站地址
            ‘__APP__’     => __APP__,        // 当前项目地址
            ‘__URL__’     => __URL__,        // 当前模块地址
            ‘__ACTION__’  => __ACTION__,     // 当前操作地址
            ‘__SELF__’    => __SELF__,       // 当前页面地址
        );
        if(C(‘TOKEN_ON’)) {
            if(strpos($content,'{__TOKEN__}’)) {
                // 指定表单令牌隐藏域位置
                $replace[‘{__TOKEN__}’] =  $this->buildFormToken();
            }elseif(strpos($content,'{__NOTOKEN__}’)){
                // 标记为不需要令牌验证
                $replace[‘{__NOTOKEN__}’] =  ”;
            }elseif(preg_match(‘/</form(s*)>/is’,$content,$match)) {
                // 智能生成表单令牌隐藏域
                $replace[$match[0]] = $this->buildFormToken().$match[0];
            }
        }
        // 允许用户自定义模板的字符串替换
        if(is_array(C(‘TMPL_PARSE_STRING’)) )
            $replace =  array_merge($replace,C(‘TMPL_PARSE_STRING’));
        $content = str_replace(array_keys($replace),array_values($replace),$content);
        return $content;
    }
就是替换__PUBLIC__之类的变量,323行 if(C(‘TOKEN_ON’)) 这里就是如果开启了令牌验证,则进行相应的操作。需要验证的话就调用 buildFormToken()方法,357行 $_SESSION[$tokenName]  =  $tokenValue; 其实就是给$_SESSION[__hash__] 赋值。
如果要解决这问题,只要在页面的</from>之前加入 {__NOTOKEN__}就行了,从上面代码也可看出,如果有这个变量,则把它替换成了空。我在页面上也加了这个,可是仍然出现表单令牌错误。顺便提一下display这个函数:
public function display($templateFile=”,$charset=”,$contentType=’text/html’)
    {
        $this->fetch($templateFile,$charset,$contentType,true);
    }
调用了fetch(),fetch()里又调用了templateContentReplace()就是上面那个函数。
问题没解决,继续找,于是找到了 create()在数据添加时都会调用这个函数,这个函数在Model类里的,有如下内容:
if(C(‘TOKEN_ON’) && !$this->autoCheckToken($data)) {
            $this->error = L(‘_TOKEN_ERROR_’);
            return false;
        }
调用了:
// 自动表单令牌验证
    public function autoCheckToken($data) {
        $name   = C(‘TOKEN_NAME’);
        if(isset($_SESSION[$name])) {
            // 当前需要令牌验证
            if(empty($data[$name]) || $_SESSION[$name] != $data[$name]) {
                // 非法提交
                return false;
            }
            // 验证完成销毁session
            unset($_SESSION[$name]);
        }
        return true;
    }
这里面有句:if(isset($_SESSION[$name])) 就是前面开启令牌验证后,有一个session 赋值。
$_SESSION[$tokenName]  =  $tokenValue;
我在if(isset($_SESSION[$name]))前面把$_SESSION[$name])的值赋为空也不行。后来发现必须要在前面 unset($_SESSION[$name]))一下,才有效果。我之前所做的什么赋空格,清缓存都没用。必须把这变量清掉。由于这是session变量,所以在第一次出错后,$_SESSION[$name])有值了。后面怎么做都出错。因为一起没有执行到unset()。所以随便在哪里加一下,运行一下就没问题了。如果实在不行,就在 $replace[‘{__NOTOKEN__}’] = ”;后面加 unset($_SESSION[C(‘TOKEN_NAME]));
       要关闭表单令牌验证,只要在配置里将TOKEN_ON’=false就行了。这样就关闭所有的验证了,感觉不是太好,不安全。我那个只是关闭某一个具体表单的验证。手册里有,见:5.3.13

 Chinese
Chinese				 English
English