今天测试动易、帝国、DEDE,实在懒得转换了。大概看了一下PHPCMS的程序,现在知道为啥PHPCMS会总是出现缓存文件无法打开的问题了。

第一次Troubleshooting:
 
function template_compile($module,$template)
{
global $CONFIG;
$content = file_get_contents(PHPCMS_ROOT.'/templates/'.$CONFIG['defaulttemplate'].'/'.$module.'/'.$template.'.html');
$content = template_parse($content);
$compiledtplfile = $CONFIG['templatescachedir'].$module.'_'.$template.'.tpl.php';
$strlen = file_put_contents($compiledtplfile, $content);
@chmod($compiledtplfile, 0777);
return $strlen;
}

红色标记处, @chmod 这个函数在PHP中是用来修改文件权限的,修改成0777,在UNIX系统中表示完全控制但不能执行的权限。

在安全的Windows下,网站目录一般谁会给完全控制权限呢?我们一般只赋予读写权限,最多最多就是再加上修改权限。实际上光读写权限就足以让一般的PHP网站正常运行了。但是你们的这个公用函数在写入缓存的时候,非要加这么一句话,就等于每次写入一个缓存文件就要给这个文件赋予一次777权限....但是在Windows主机下,网站的权限是继承的,根本不需要这么做的。而且正式因为安全主机下最多只能给到修改权限,而特殊权限是没有的,所以这个修改文件权限的动作是无法运行的。因此这次我认为就出现了缓存文件无法打开的问题了。
修改所有Include文件中的这段语句,无效。

第二次Troubleshooting:
如我在之前提的问题中所说的。[url]http://bbs.phpcms.cn/thread-53128-1-1.html[/url] 可能与系统的某种写入文件的机制有关系。再次仔细查看了一遍Install.php所包含的所有文件。
发现PHPCMS所有写入文件的函数是:
 
function file_put_contents($file, $string, $append = '')
{
  $mode = $append == '' ? 'wb' : 'ab';
  $fp = @fopen($file, $mode) or exit("Can not open file $file !");
  flock($fp, LOCK_EX);
  $stringlen = @fwrite($fp, $string);
  flock($fp, LOCK_UN);
  @fclose($fp);
  return $stringlen;
}

在缓存写入函数中都会调用以上函数进行写入操作,而PHPCMS的缓存写入函数均是foreach循环,而且缓存的写入是会将内容一段一段写入某一个文件的,也就是说每一次Windows系统都会打开这个缓存文件,写入一段数据,保存关闭,再打开它,再写入数据,直到完全写完毕为止。而在一台速度很快的服务器上,这种一段段的写入操作之间的间隔几乎可以忽略,再加上PHPCMS的写入动作使用foreach循环,这样的连续循环加重复写入某一个缓存文件的动作几乎是在同一时刻完成(相当于同一时刻有N次对某一文件的写入操作),这违背了Windows系统文件写入机制,Windows系统采用独占方式对文件进行写操作。因此需要将此函数进行减速。修改如下

function file_put_contents($file, $string, $append = '')
{
  $mode = $append == '' ? 'wb' : 'ab';
  $fp = @fopen($file, $mode) or exit("Can not open file $file !");
  flock($fp, LOCK_EX);
  sleep(1);
  $stringlen = @fwrite($fp, $string);
  sleep(1);
  flock($fp, LOCK_UN);
  @fclose($fp);
  return $stringlen;
}

此函数在include\Global.func.php 中,此办法应该可以解决所有的Can't not open file......的问题。

缺陷,使用此方法后,更新文件时可能会造成速度降低,可以将sleep(1);移动至缓存读写函数中,谁有时间测试一下发出来吧。我没空高了。