Fixed NextGenGallery 0 images were uploaded error

Nggallery 0 images were uploaded
Nggallery 0 images were uploaded

不知从何版本起,NextGenGallery 插件在我的 WordPress 上就不工作了,主要症状是:

  • 后台无法在 Gallery 里上传图片,显示 “Upload complete. 0 images were uploaded.”(WordPress 自身的 Media 上传正常)。
  • 后台无法批量导入图片,服务器的文件夹根本就不显示。
  • 已有的 Gallery 在前台只能显示第一张图,点下一张图就是 404 错误。

这个问题困扰了我约有半年。期间发现把 Permalinks 改为 Default 模式能让 NextGenGallery 恢复正常,但我不可能为了 NextGenGallery 修改 Permalinks 啊,只好任由这个问题存在。所幸迄今为止只有 5 galleries,而且都不怎么重要,所以这个问题不突出。

上个周末突然犟了一下,我觉得不该卡在这个问题无从下手啊,调用 google N 多次,终于在一个角落里给我找到一点端倪,再做了 N 多次试验,得出的结论是此问题在 PHP installed as an Apache module 时不存在,我恰用的是 Nginx,罪魁祸首是 fastcgi_param 没弄好。

出现此类问题是小概率事件,即使是一个不完善的 fastcgi_param 配置,我的 Nginx 也让大部分 PHP 跑了多年没出其他问题。NextGenGallery 也有一定责任,使用了一种不推荐的环境变量,在 PHP installed as an Apache module 下不会激发这个 bug,但在 Ngnix + 不完善的 fastcgi_param 会。而我用的不完善的 fastcgi_param,我相信很多人都在用,所以有一定的普遍性。

言归正传,怎么改?

有人说把 NextGenGallery 的 class.router.php 的 function get_request_uri 的 if (isset($_SERVER[‘PATH_INFO’])) 改为 if (empty($_SERVER[‘PATH_INFO’])),确实能奏效,但我认为不理想。因为:

  • NextGenGallery 虽有错,但大错不在它,而在 Nginx 没配好。
  • 这个问题被反应到 NextGenGallery 开发者很久了,期间 NextGenGallery 升级了无数次,也没见他修正此 bug,可能他认为此 bug 非 bug。

我认为解决问题的根本办法是在 fastcgi_param 文件里,把通常人用的

fastcgi_param  PATH_INFO          $fastcgi_path_info;

改为

fastcgi_param  PATH_INFO          $fastcgi_path_info if_not_empty;

Favicon Controller in Msdk

昨晚在 Magento 里写了个 FaviconController.php,是为了解决 Magento 根目录下的 favicon.ico 静态文件无法根据多网店不同的 favicon.ico 而变化。

Magento 有支持多网店多 favicon.ico,但直接访问 example1.com/favicon.ico 和 example2.com/favicon.ico 怎么回应不同的 favicon.ico?我是把静态文件删了,由 FaviconController.php 读取 SystemConfig 从 media 或 skin 目录里读出相应的 favicon.ico,响应 /favicon.ico 的请求。

逻辑很简单,我调试好了以后决定把这个功能归于我的 Msdk 模块,可是天黑眼花,竟然塞错进了另一个不相干的 Misc 模块,于是怎么看 /favicon.ico 都是 404 Error。这事折腾了有2个小时才发现错误所在。我痛下决心,要把 Misc 模块改个名。

P.S. Msdk 模块是免费的。下次发布新版大家就会看到 FaviconController.php 了。

No deplicate posts any more in WordPress

刚用上WordPress后,我发现WordPress一个不足之处——同一个post_id的post,可以用不同的url来访问。

以此blog为例,我设置permanent link structure为/%post_id%/%postname%/。我认为post_id查询最快,postname又是meaningful string,最有利seo,所以我把两者结合起来了(后来据说顶层目录的文件最利于seo,所以我更喜欢设置permanent link structure为/%postname%_%post_id%.html,但据说Google不吃这一套,那我就没必要为一些小引擎去劳师动众修改现有的blog,扯远了)。

当permanent link structure存在post_id和postname两个参数时,post_id起决定作用。早期版本会完全忽略postname,造成只要post_id是正确的,任何杜撰的postname都会被承认。设想一下,如果我发布了一个post以后修改了postname,搜索引擎读到不同url上的相同内容,肯定会降低对此blog的评价。

所以,当时我想改一下WordPress程序逻辑,当post_id存在但url中的postname不等于数据库中的postname时,返回404页。但是我还没来得及做这个修改,今天惊喜发现WordPress 2.6 (可能更早的版本已经实现了这个修改) 已经会把/(post_id)/(incorrect_postname) 301跳转到 /(post_id)/(postname),这应该比我设计的方案更完好,我非常喜欢WordPress的体贴。

发现一个wordpress不够体贴的地方

熟悉以后才知道它/他/她的缺点,这就是为什么离婚总是发生在结婚后。

我在了解wordpress的过程遇到这么点小麻烦:custom permalink structure为/%post_id%/%postname%/(其实seo并非非得这么设置,但这个设置是我们价值£750每月的引擎优化专家推荐的,姑且采用)。

我事先知道这个blog所在的服务器目前没加载mod_rewrite,因为这不是我的独立服务器,所以我并不能想加载什么模块就可以加载的。但我暂时不想为了贪图mod_rewrite就把blog转移到另一个服务器,至少在这个blog正式上市之前不想。保持一个主服务器在美国,一个大副服务器在德国,以后再弄一个二副服务器在英国当地,或者把大副二副换一换,这是我理想中的格局,不把鸡蛋放一个篮子里嘛。

但我有个毛病,明知不可为而为之,就是想看看什么后果。结果我知道了:后果很严重。一旦修改了permalink,wordpress就自动生成一个.htaccess,不管服务器是否支持,也不管blog是否真的需要这个.htaccess。由于服务器没有加载mod_rewrite,所以发生500 server error。于是我删掉了.htaccess,然后在后台想把permalink改回Default,wordpress不够体贴的地方就暴露出来了:只要一提交permalink的值,不管这个新值是什么,wordpress就自动生成.htaccess,这样我的服务器马上就500,php肯定就中止执行了,数据库就无法更新了。这个鸡先生蛋、还是蛋先生鸡的问题,我最后是直接操纵数据库才解决的(wordpress的数据库结构还是挺清晰的,我没看什么资料,凭着直觉找到wp_options table,再找到permalink_structure,删掉option_value就可以了)。

说了一个wordpress的缺点,作为补偿,我再说一个我感觉到的体贴,总是在细致之处。当初安装wordpress,ftp原码以后,installation要求把wp-config-smaple.php改名为wp-config.php,虽然改名不算麻烦,我还嘀咕它为什么不直接替我做了这件事。最近一次升级才让我理解它的良苦用心——升级时只要一股脑ftp所有文件,不用担心设置文件的备份恢复等等。我以前一直都不太愿意升级,就是怕备份恢复这些琐事,所以wordpress新版本出了很久了,可能新版本的新版本都已经出了n多个了,我才折腾了一下。有了这次无痛升级的过程,我以后一定会升级得很勤快的。

题外话:wordpress的permalink基于url rewrite,要求服务器服务器是apache+mod_rewrite,适用性小。要是谁能开发一个plugin,基于404错误捕获做permalink,一定会在广大小空间业主群里有市场。不过我不会想着去做这件事,从基于url rewrite到基于404,技术上是种倒退。要向前看,不是向钱看。