情報科学屋さんを目指す人のメモ

方法・手順・解説を書き残すブログ。私と同じことを繰り返さずに済むように。

WordPress Popular Posts でサムネイルが表示されない原因と TimThumb.php のエラーについて

PHP (25) WordPress (76) WordPressプラグイン (25)

WordPress Popular Posts でサムネイルが表示されなくなってしまいました。その原因がプラグイン内部で使っているTimThumb.phpにあったようなので、メモしておきます。

サムネイルが表示されない

WordPress Popular Postsというプラグインを使って人気の記事を表示していたのですが、サーバの変更後、サムネイルを表示できなくなってしまいました。

TimThumbを利用したサムネイル生成&表示

Popular Postsでは、imgタグのsrcに画像URLを直接指定するのではなく、TimThumb.phpに、画像URLと、縦横のサイズを渡していました。

そして、その.phpが画像ではなく、エラーページを返していたのです。

TimThumb.phpのエラーメッセージ

そのエラーページがこちら(400 Bad Request)

A TimThumb error has occured

The following error(s) occured:
Could not find the internal image you specified.


Query String : src=http://did2memo.net/wp-content/uploads/....png&h=110&w=110
TimThumb version : 2.8.10

ただし、これだけでは直接的な原因はよくわかりません。

バージョンを落としてみた

いろいろ調べてみたところ、TimThumb.phpを書き換えて修正している方法なども見つかったのですが、それでは何も変わりませんでした。

また、バージョンを2.8.2まで落とすという対策をしてみても変化がありませんでした。

本格的に原因を探してみた

そこで、本腰を入れて原因を探してみることにしました。

まず「define ('DEBUG_ON', false)」を「true」に、「define ('DEBUG_LEVEL', 1);」で定義されているデバッグレベルを「3」しました。これで、「/var/log/nginx/error.log」に、デバッグ用メッセージが出力されるようになりました。

そのデバッグ用メッセージで気になったところがこの部分でした。

PHP message: TimThumb Debug line 1076 [0.000339 : 0.000134]: Trying file as: /usr/share/nginx/html/wp-content/uploads/2013/02/line-backup-open-talk-settings.png

「/usr/share/nginx/html」という全く関係ないディレクトリを探してしまっています。このおかしなディレクトリ内を探している部分が次のコードです。

                $base = $this->docRoot;
                foreach (explode('/', str_replace($this->docRoot, '', $_SERVER['SCRIPT_FILENAME'])) as $sub){
                        $base .= $sub . '/';
                        $this->debug(3, "Trying file as: " . $base . $src);
                        if(file_exists($base . $src)){
                                $this->debug(3, "Found file as: " . $base . $src);
                                $real = realpath($base . $src);
                                if(strpos($real, $realDocRoot) === 0){
                                        return $real;
                                } else {
                                        $this->debug(1, "Security block: The file specified occurs outside the document root.");
                                        //And continue search
                                }
                        }
                }

ここから、「$base($this->docRoot)」がおかしいことがわかりました。

対策

このdocRootは、calcDocRoot関数の「$_SERVER['DOCUMENT_ROOT']」で取得されており、今回の場合は、$baseにWordPressのインストールディレクトリの絶対パスが入ればよい、ということで、「calcDocRoot関数の「$docRoot = @$_SERVER['DOCUMENT_ROOT'];」を「$docRoot = '/var/www/did2memo.net/wp/';」と変更しました。

これで、無事サムネイルが表示されるようになりました

$_SERVER{'DOCUMENT_ROOT']

$_SERVER['DOCUMENT_ROOT']は、マルチサイトの設定にしていると、うまく取得できない(デフォルト値になってしまう)そうです。この件についてはApacheでそうなる、という話が多いのですが、今はNginxを使っていて、Nginxでも同じような動作をしているのかもしれません。

プラグインのバージョンを上げると上書きされてしまうので注意

TimThumb.phpを書き換えた場合、それを利用しているプラグインのバージョンを上げた場合、その書き換えは失われてしまいます。ですので、バージョンアップ後はもう一度書き換えるようにしてください。

コメント(0)

新しいコメントを投稿