ハマるとなかなか気づかないワナ_XOOPS
ハマるとなかなか気づかないワナ
きちんとPHPでXOOPSのモジュールを作っているのにページが表示されなかったり、表示がおかしくなる、ということが起こることがあります。
実際に起こりうる問題とその回避策を書き記します。
ページが表示されない、エラーが出て回避できない
PHPソースファイルをEUCコードで保存していない(すべてのファイルをEUCで保存すること)
ヘッダ・テンプレート・フッタの呼び出し順番が異なっている
// ヘッダファイルの参照 require('header.php'); // テンプレートの設定 $xoopsOption['template_main'] = 'simplemodule_view.html'; // XOOPSヘッダの設定 include(XOOPS_ROOT_PATH.'/header.php'); // テンプレートにデータを設定する $xoopsTpl->assign('lang_title', _MD_TITLE); $xoopsTpl->assign('lang_mes', _MD_MES); // XOOPSフッタの設定 include(XOOPS_ROOT_PATH.'/footer.php');
プログラムが複雑になると、うっかりXOOPSヘッダを呼ばずに「$xoopsTpl->assign」してしまった、なんてことが起こってしまうことがあります。
テンプレートを「$xoopsOption['template_main']」に指定しているが、「xoops_version.php」の$modversion['templates']に指定していない。
ソースファイルの先頭に空白の行が入ってしまう
ちょっと分かりにくいですが、WebブラウザからHTMLソースを見たときに、先頭行がカラ行になっている、という現象に出くわすことがあります(ありました)。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja"> <head>
ページ自身は何も不都合がないので(空白行が画面に出るわけではないので)問題ない、と思われるかもしれません。実際、問題ないのですが・・・・・1回だけ、ページが空白になってしまい、モジュールをアップデートしても一度ログアウトしてからログインしてもダメだった、ということがありました。
この出力するHTMLの先頭のカラ行をなくすため、何が原因か追ってみました。
print("\n");
みたいに故意に改行しない限りはこうはならないだろう、と思ったのですが1点だけ盲点がありました。
プログラム部であるPHPソースではなく、文字列リソース側の[main.php]にて以下のようにしている箇所がありました。
<?php define('_MD_TITLE', '簡単なモジュール'); define('_MD_MES', 'Hello World!!'); ?>
さて、何が原因か分かりますでしょうか(上記じゃ非常に分かりにくいのですが)?「<?php 〜 ?>」で囲まれた部分は、PHPのソースを記述します。これはいいですよね、しかし、すぐその下にカラ行を入れてしまってます。私は、ソースの終端(EOF)までの間に複数行のカラ行を入れるクセがありましたので これがそのままHTMLとして出力されてしまった、というのが原因でした。「<?php 〜 ?>」以外のところは、HTMLに表示される部分です。「?>」でPHPの処理部分を閉じた後はすぐにEOFにしないといけないですね。
なぜかページが表示されていなかったとき、これをすべてのPHPファイルにて修正し再度モジュールをアップデートしたら、正常に動きました。
これはめったに不都合には遭遇しないのですが、確実にこの問題が不正を起こすときがあります。
それは、ページを表示する代わりにファイルをダウンロードさせる場合です。たとえば、CSVファイルをダウンロードさせる例を考えてみましょう。
PHPソースにて、XOOPSのヘッダ類は呼ばずに(<これが大事です!)以下のように記述すると、「test.csv」ファイルをダウンロードするダイアログが表示されます。
header('Pragma: public'); header("Content-Type: application/octet-stream"); header("Content-Disposition: attachment; filename=test.csv"); print("1,cat,sleep\n"); print("2,dog,sleep\n");
このときに、先ほどのように文字列リソースである「main.php」の末尾に空白行が付いてしまうと、HTMLヘッダが解釈できなくなってしまいます。結果、CSVのダウンロードなのに、ヘッダの記述からCSVの内容までが そのままHTMLとして出力されてしまうことになります。
ということで、教訓としては すべてのPHPファイルにて「<?php 〜 ?>」の後には空白行は入れない、ということですね。
ファイルが二重に呼ばれてしまい、警告される
よく使う処理を別のPHPファイルにおいておき、再利用する(include/requireする)というのはよく使う手段です。
しかし、その別のPHPファイルからさらに別のPHPファイルを参照、とかしていると二重呼び出しが起きてしまうことがあります。そのような場合を考えて、再利用するために分けたPHPファイルでは
include_once('xxx.php'); require_once('xxx.php');
で二重呼び出しが起こらないようにします。
改行コードを入れたのに、改行コードの文字列自身がページに表示されてしまった
画面に
Line1 Line2 Line3
のように表示しようとして、
print('Line1<br>\nLine2<br>\nLine3<br>');
のようにしてしまった経験があります。これを
$str = 'Line1<br>\nLine2<br>\nLine3<br>';
のように変数に入れてもいいです。単に文字列を入れるだけなのでシングルクォーテーションで囲ってます。ですが、表示は
Line1 \nLine2 \nLine3
のように出てしまいました。
エスケープシーケンスのある文字列は、シングルクォーテーション内ではエスケープシーケンスとは解釈されていません。たとえ変数が文字列中になくても、ダブルクォーテーションでくくりましょう。
print("Line1<br>\nLine2<br>\nLine3<br>");
画面に表示されているのならすぐに分かるのですが、文字列検索や文字列置換でうっかりシングルクォーテーション内でエスケープシーケンスの文字を条件に加えてしまうと、意図した処理ができなくなります。
円マークを出したいのにバックスペース表記になっている
XOOPSデフォルトでは、以下のような文字列をブラウザに表示(テンプレートの変数に代入)すると、円マーク(¥)ではなくてバックスペースで表示されてしまいます。
$xoopsTpl->assign('lang_mes', "d:\\user\\hoehoe.txt");
これは、テーマのCSS(themesディレクトリ内のカレントテーマのstyle.css)にて
table td {padding: 0; border-width: 0; vertical-align: top; font-family: Verdana, Arial, Helvetica, sans-serif;}
のようになっている部分の「font-family: Verdana, Arial, Helvetica, sans-serif;」が原因です。これを削除すると、きっちり円マークにはなります。
フォントが小さくなるし、もうちょっと賢いやり方はあると思います・・・。モジュール自身はtableタグ内に埋め込まれていますので、上記のCSSのように「table td」の変更が効いているわけですね。
Future's Laboratory 技術格納庫 2004-2013 Yutaka Yoshisaka.