Composer PHP Fatal error:Allowed memory size of 536870912 bytes exhausted

今天在运行composer update时遇到的,详细的错误消息如下:

$ composer update
Loading composer repositories with package information
Updating dependencies (including require-dev)
PHP Fatal error:  Allowed memory size of 536870912 bytes exhausted 
(tried to allocate 32 bytes) in phar:///usr/local/Cellar/composer/
1.0.0-alpha8/libexec/composer.phar/src/Composer/DependencyResolver/
Rule.php on line 62
 
Fatal error: Allowed memory size of 536870912 bytes exhausted
(tried to allocate 32 bytes) in phar:///usr/local/Cellar/composer/
1.0.0-alpha8/libexec/composer.phar/src/Composer/DependencyResolver/
Rule.php on line 62

一直以为是网络原因,最近连接国外的网络不是很稳定,后来根据报错的信息Allowed memory size of 536870912 bytes exhausted提示知道可能是内存分配不够,大家知道在PHP的配置文件php.ini中有限制脚本运行内存的设置memory_limit把这个值调大一些就可以解决这个问题了。

继续阅读

PHPWord解决中文乱码并导出生成Word2007(docx)格式文档

最近一个项目开发要用到PHP技术导出Word文档,比较了几种方案,首先是使用Microsoft Office自带的ActiveX/COM组件,比如Word.Application,这种方式的优点是格式兼容度高,可以生成纯doc的Word2003格式文档,缺点一是比较占资源(调用会启动一个WINWORD.EXE进程),不适合Web多用户访问使用;二是PHP这种Web开发技术大多数是跑在Linux服务器上,当然也就无法使用Windows下的技术了,平台可移植和兼容性不好。第二种生成Word的方案是生成Word兼容的网页格式,然后以Word方式打开,这种方案总体上感觉怪怪的,毕竟文件格式是HTML的,而且格式兼容度不好,不过这种方式的优点是节省服务器资源,能够快速生成;最后一种方案也就是今天的主角,采用PHPWord生成Word2007(docx)格式的文档,现在基本上微软Office Word 2003以后的版本均兼容这种格式了,对于2003版本来说,仅需要下载安装个兼容格式包(下载地址),也能正常打开这类文件,当然如果你使用的是最新版本的Office(包括但不限于Office 2007、Office 2010)则不需要安装此格式包。

继续阅读

PHP设置会话(Session)超时过期时间实现登录时间限制

最近某个PHP项目用到了限制登录时间的功能,比如用户登录系统60分钟后如果没有操作就自动退出,我搜索了网络收集了有以下方法可供参考。

第一种方法即设置php.ini配置文件,设置session.gc_maxlifetimesession.cookie_lifetime节点属性值,当然也可以使用ini_set函数改变当前上下文环境的属性值:

ini_set('session.gc_maxlifetime', "3600"); // 秒
ini_set("session.cookie_lifetime","3600"); // 秒

第二种方法即设置Session时间戳,比如下面的办法。

继续阅读

解决Smarty模板register_block、register_function的SmartyException问题

今天手痒将一个旧的PHP项目的Smarty模板引擎进行了升级,到Smarty官方网站下载最新版本3.1.8,本来以为妥妥的,但结果杯具了,PHP报错如下:

Fatal error: Uncaught exception 'SmartyException'
with message 'Call of unknown method 'register_block'.'
in E:\Smarty-3.1.8\libs\sysplugins\smarty_internal_templatebase.php:806

好吧,我承认我又手贱了一回,根据错误信息:“Call of unknown method ‘register_block’.”知道是找不到类的register_block方法,这怎么可能呢?原来这个函数可是妥妥的,难道Smarty3做了改变?

继续阅读

解决WordPress中文附件attachment以及tag URL导致的404找不到页面问题

之前从Typecho转换到WordPress的,结果使用网上的转换程序勉强转换成功,没想到却带来了一堆后遗症,其中比较明显的就是中文url导致的404找不到页面的问题。

其实搜索“Wordpress 中文 tag 404”关键字词就可以找到大量关于这类问题以及解决方案的信息,这些解决方案无非是要求修改WordPress的wp-include/classes.php(3.1之前版本)或wp-include/class-wp.php(3.1+之后版本)的源代码,增加UTF-8与GBK的一个转换;或是修改rewrite.php改变重写规则。这些我没有去尝试,我感觉修改官方代码的做法不是很妥当的,即使修改了,以后升级什么的,原先修改的内容仍然会被替换,或者修改有可能会导致新的问题等等,所以我不建议修改官方源代码。

如果默认官方表前缀wp_的话,导致这个问题的中文tag在MySQL的位置为表wp_terms的列slug,中文附件attachment所在MySQL的位置为表wp_posts的列post_name。这次转换前我尝试着发布了一篇带有中文tag或者attachment中文名称的文章,并且访问这个tag或者附件正常,然后再查看MySQL数据库。发现其中attachment的post_name以及tag所在的slug均被改写成类似%E8%A7%A3%E6%9E%90这样的字符串,其实这类字符串是符合URL编码标准的,一般我们的输入的字符串在提交URL前均会被编码成形如这样的编码;再看看出问题的编码形式,直接是中文未经过任何编码,所以需要访问这类资源需要进行编码转换才能正常访问,否则就会出现404找不到页面的问题。

其实我们可以通过PHP内置的urlencode对attachment的post_name以及tag所在的slug进行一次编码然后再写入数据库,以避免出现这类问题,这里我对所有附件attachment的post_name进行了一次urlenocde编码,代码如下(测试前请备份数据库)

继续阅读

解决Smarty模板中CSS导致的SmartyCompilerException问题

今天在项目中应用Smarty模板引擎时遇到的问题,PHP解析出错,主要定位在CSS部分,错误形如“Uncaught exception ‘SmartyCompilerException’ with message ‘Syntax Error in template”。仔细分析了下,发现是嵌入HTML的CSS {}花括号与Smarty的界定符号{}花括号冲突,如果简单地将CSS标记嵌入到HTML文档首部,将导致“不可识别标记”错误,经过搜索得到三种办法以解决这个问题:

1. 外链CSS文件。利用link外链层叠样式表文件。例如:

1
<link href="style.css" type="text/css" rel="stylesheet" />

2. 使用literal标记。利用Smarty独有的literal标记区分不需要解析的区域,用标记{literal}和{/literal}包含起来的区域Smarty将跳过分析直接输出,这样就不会导致冲突了。

1
2
3
4
5
6
7
{literal}
<style type="text/css">
body {
 color:#FFF;
}
</style>
{/literal}

3. 修改Smarty的默认定界符。通过设置left_delimiter和right_delimiter属性来实现这一目的。

1
2
3
4
require("Smarty.class.php");
$template = new Smarty;
$template->left_delimiter = '<{';
$template->right_delimiter = '}>';

第3种方法的缺点就是要改原有模板的解析标签,比较麻烦,推荐第1种和第2种灵活搭配使用。

主机域名www的自适应301重定向方法

一般来说Web网站都是喜欢带www的,但是我觉得我的网站带www前缀有些略显不雅,所以我决定把www转向到不带www的域名上来,通常情况下使用301重定向

以前自己用ASP写过个转向的代码片段,供大家参考:

1
2
3
4
5
6
7
8
9
10
11
12
<%
Dim g_ReqServer
g_ReqServer = Request.ServerVariables("SERVER_NAME")
If InStr(1, g_ReqServer, "www.", 1)<>0 Then
    Response.Status="301 Moved Permanently" 
    Response.AddHeader "Location", "http://" &_
        Replace(LCase(g_ReqServer), "www.", "") &_
             Request.ServerVariables("PATH_INFO") & "?" &_
                    Request.QueryString()
    Response.End
End If
%>

这里解释下,首先Request.ServerVariables(“SERVER_NAME”)获取访问所使用的主机域名,然后通过InStr判断是不是包含www.,如果包含则返回301状态。紧接着拼接出新的网址,新的网址必定由http:// + 去掉www.的主机域名(这里调用Replace函数替换) + 所请求文件的路径信息PATH_INFO + ‘?’ + 所请求的字符串,之所以称为“自适应”是因为对于任何的URL,都只是单纯的去掉www.,原路径不变,所以问号和请求字符串就尤显重要了,如果省掉就可能导致查询字符串的丢失。

后来初学PHP,也照样子写过一段代码,如下:

1
2
3
4
5
6
7
8
9
<?php
$server_name = $_SERVER['SERVER_NAME'];
if(!stristr($server_name, 'www.')) {
 $pathinfo = parse_url($_SERVER['REQUEST_URI']);
 header("HTTP/1.1 301 Moved Permanently");
 header("Location: http://www." . $server_name . 
    $_SERVER['PHP_SELF']."?".$pathinfo['query']);
}
?>

基本原理是一样的,只不过要获得?后面的一大串查询字符串需要调用parse_url。

值得注意的是上述两段代码片段必须加在访问的页面代码顶端,也就是在任何Response或者echo输出之前,否则就失效了。

后来通过网上查询获得了个更好的方法,那就是.htaccess,在.htaccess的 里面添加下面的代码:

1
2
3
RewriteEngine on
RewriteCond %{HTTP_HOST} ^www\.wangye\.org$
RewriteRule ^(.*)$   http://wangye.org/$1 [L,R=301]

初学.htaccess,感觉有点正则表达式的味道,首先匹配主机域名,如果是www.wangye.org就进行R=301的重定向。

2011年3月10日更新

Aaron Saray的博客上看到了个比较好的写法,包含了两种情况,分别是有带www的转向不带www的和不带www的转向带www,特别记录下来。

1
2
3
4
5
6
7
8
9
10
11
12
RewriteEngine On
RewriteBase /
 
#require WWW
RewriteCond %{HTTP_HOST} !^www\.(.+)$ [NC]
RewriteRule ^(.*)$ http://www.%1/$1 [R=301,L] 
 
#OR
 
#do not require www
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^(.*)$ http://%1/$1 [R=301,L]

2011年7月3日更新

根据未来往事所反映的关于PHP代码实现跳转,在处理URL重写(URL Rewrite)的情况下会丢失重写,回到原始带查询参数的链接地址,为此我将相关代码修改如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?php
// 定义你自己的URL路由表
// 比如下面的路由表将会把
// read.php?paramA=1&paramB=2&paramC=3
// 变成
// /post/1/2/3/
$router = array(
  'read.php'=>'/post/'
);
$server_name = $_SERVER['SERVER_NAME'];
if(!stristr($server_name, 'www.')) {
  $fn = explode('/', strtolower($_SERVER['PHP_SELF']));
  if (array_key_exists($fn[0], $router)) {
    $path = $router[$fn[0]] .
      implode('/',
        array_filter($_REQUEST,
           create_function('$v','return !empty($v);')));
  } else {
    $pathinfo = parse_url($_SERVER['REQUEST_URI']);
    $path = $_SERVER['PHP_SELF']."?".$pathinfo['query'];
  }
  header("HTTP/1.1 301 Moved Permanently");
  header("Location: http://www." . $server_name . $path);
}
?>

总结最后,还是建议大家在条件允许的情况下尝试采用301的DNS转向,目前有些DNS服务商已经免费提供这项功能。

  1. 301重定向 : 301代表永久性转移(Permanently Moved),301重定向是网页更改地址后对搜索引擎友好的最好方法,只要不是暂时搬移的情况,都建议使用301来做转址。[更多]
  2. .htaccess : Apache服务器中的一个配置文件,它负责相关目录下的网页配置。通过.htaccess文件,可以帮我们实现:网页301重定向、自定义404错误页面、改变文件扩展名、允许/阻止特定的用户或者目录的访问、禁止目录列表、配置默认文档等功能。 [更多]