headers already sent …

WordPressカスタマイズのお仕事をしていて・・・。
他のURLへリダイレクトする必要がある処理が出てきた。リダイレクトの処理は当然header関数を使用するわけなのだが・・・。
なんとしたことか「modify header information – headers already sent by …」なんてミスをやってしまった。ちなみにこのプログラム、実際に出力処理はしているのだが、ファイルの最初でob_start関数を実行し、出力を抑制している。にもかかわらず、エラーが出る。なんで?。
どうしても理由がわからないので、ファイルの一番最初にheader関数をもってきた。しかしそれでもエラー。なんで?、なんで?。
実はプログラムは何も悪くなかった。原因はBOM。ファイルを保存する際に誤ってBOMつきUTF-8で保存してしまったことが原因だった。
こんなところでもBOMではまってしまった・・・。

fsockopenは時間がかかる?

不思議?というか、わからない現象に出くわして、ちょっと悩んでいる。
外部URLに接続してコンテンツを持ってくる(要はRESTでxmlを取得したりする)時には、いろいろな取得方法がある。
(1) fopenとかfile_get_contentsで取得
 引数にURLを直接渡す方法で一番簡単だが、データを取りこぼすことがある。
(2) curlで取得
 インストール時のコンパイルオプションによっては使えないことがある。
(3) fsockopenで直接HTTPを話して取得
 直接HTTPを話すスクリプトを用意する必要がある。

PEARのHTTP_Requestを使うという選択肢もあるが、これも結局は内部で上記を呼び出している(と思う)ので同じことだ。
上記で一番確実な方法は(3)のfsockopenを使う方法だ。PHPの標準関数でできるし、取りこぼしもないので、これを使うべきだ(と思う)。しかし、ちょっと困ったことになってしまった。fsockopenでデータを取得するのに時間がかかるのだ。
fsockopenの手順としては、以下のような感じ。
(1) fsockopenで相手サーバに接続
(2) fputでリクエストを送信
(3) fgetsでレスポンスを受信

しかし(1)で異常に時間がかかってしまうのだ。時間にして20秒くらいかかる。これがなぜだかわからない・・・。
ちなみに当該URLを、ブラウザ上で開くと数秒で表示される。それにfile_get_contentsで取得しても、やはり数秒で結果を返してくる。

ん〜〜〜。

いろいろ調べてみたが理由がわからなかった。レスポンスを受信するのに時間がかかるのであれば、相手サーバの処理時間とか、通信速度の問題か、とも思うのだが、fsockopenで時間がかかるのが不思議だ。fsockopenで時間がかかるのなら、file_get_contentsでも時間がかかってしまいそうなのだが、あいにくこちらは時間がかからない。

どなたか、思い当たるところがあったら教えていただきたい。
どうぞよろしくお願いします。

文字コードUTF-8で、BOMの有無による問題

Xoopsのモジュールを書いていて、すごく悩ましい問題に出くわした。
テンプレートを2つ(それぞれ仮にAとBと呼ぶことにする)用意したのだが、同じようなタグしか記述していないのに、どうしても片方で余白ができてしまう。原因を突き止めるためにテンプレートの中身を最低限の内容にしてみた。

テンプレートAの中身
<div>A</div>

テンプレートBの中身
<div>B</div>

しかしこれでも片方で余白が出来てしまう。これはスタイルシートとかタグレベルの問題ではないことは明白だ。では何がそうさせるのか。
答えは「UTFのBOM」でした。

最近は文字コードとしてUTF-8を使用するようにしている。テキストエディタとしてEmEditorを愛用しているのだが、UTF-8でもBOMの有無を設定できるようになっている。
BOMとはUTF-16で必要となる「ビット列の並び」を示す符号のようなものだ(検索したらそう書いてあった)。本来UTF-8では必要ないはずなのだが、UTFで書かれているということを示すためだけにBOMがつけられるとのことだった。

前述の問題は片方のテンプレートがBOM付きで保存されていたことが問題で、BOMをとって保存すると余白なく表示されることを確認できた。
いずれにしても文字コードは、問題を引き起こす原因の一つであることは間違いないようだ。

クラス内でコールバック関数を使ったときの失敗

コールバック関数はとっても便利だ。しかし、今回、とあるプログラム作成で思いっきりはまった事象があったのでメモする。今回はarray_walkという関数を使用した。array_walk関数は指定された配列の全ての要素に対して、コールバックで与えられた関数を適用する、という関数だ。

bool array_walk ( array &array, callback funcname [, mixed userdata] )

まず一つ目は単なる備忘録。「callback funcname」には関数名をしているのだが、クラス内で使用する場合は配列の形で関数名を渡してやる。具体的にはこんな感じ。

array($this,’_callbackfunction’)

別のクラス内にある関数を使う場合には上記の「$this」がクラス名(もしくはオブジェクト名)になる。
これは大したことない。問題は次。

とあるクラスの関数内でarray_walkを使用し、全ての要素に対して特定のチェックをかけるルーチンを記述したかった。当然チェックをかけるルーチンはコールバック関数で記述する。

ここでコールバック関数を以下のように書いてみた。
function _check($value,$key,$check){
  if($value==$check){
    $this->checked[]=$key;
  }
}

array_walkの第3引数で「$check」を渡しておき、コールバック関数内で値と「$check」を比較し、同じならクラス内のメンバ変数$checkedに配列の要素として追加していく、というものだ。
しかしこれ、プログラムを実行し、最後にメンバ変数$checkedを出力しても、何も格納されないのだ。何回やっても、代入の仕方を変えてもダメ。何をやっても空だ。

そしてふと気づいた。これって単に関数として呼び出してるだけで、オブジェクトには何の関係もないのでは・・・、もしそうならメンバ変数とか、コールバック関数内から別の関数を呼ぶことも出来ない。

ということだった。
結局array_walkはやめて、単にループで回してチェックをかけることで解決した。まだまだ技量も知識も足りないらしい。

複雑なライブラリを読むために

先日紹介したPearのグラフツール「Image_Graph」。強力なツールではあるのだが、マニュアルがそろっていないことが難点だ。使い方もややこしいような気がするのだが、おそらく「ある種類のオブジェクトを生成する方法が複数ある」ことが原因のように思う。結局生成したオブジェクトが、どこから派生したものなのかさっぱりわからないので、そこから何ができるのかさっぱり・・・なのだ。そういう複雑なクラスを読むために便利な関数がある。PHPマニュアルにある「クラス/オブジェクト関数」だ。
例えば「get_parent_class」。この関数で親クラスの名前がわかる。これを使って親クラスの名前を知れば、通常クラス名にあわせてファイル名が命名されているのだから、どのファイルを参考すればよいのか判断がつくはずだ。
それに「get_class_methods」。これを使うと、使用可能なメソッドがわかるし、「get_class_vars」でデフォルトのプロパティもわかる。デバッグ時には結構有効に使える関数群だ。

しかし・・・しかしだ。「Image_Graph」は難解だ。こなれるまでまだ1年くらいかかりそう(いや、おそらくそれ以上・・・)。


守谷市(まちの情報ポータル) 無料アンケートレンタルjpForm.net