path設定のセパレータがOSで違うのにハマった

ちょっと複雑な設計になってくると、パスの制限を回避したくなります。
いや、本当はそういう制限があっても問題ないのが本当はいいのだけど、いちいちdefineで宣言するのもめんどくさいし、過程よりも結果に重きをおくべきなのはいうまでもありません。
ということで、set_include_pathをいじって、システムの設計を一部変更して、テストサーバにアップしたとたんに異変が。
今まで動いていたのが、ファイルが見つからないの嵐に。
よくよく調べたら、Windowsとそれ以外ではpath設定のセパレータが異なるという。
OSのpathを利用しているからだと分かればたいしたことないのだけれど、コロンとセミコロンなんて、ぱっと見て違いに気づきませんよ、普通。
定数のPATH_SEPARATORを使えばいいのだけれど、こういう回避の仕方はphpだからこそというか、無理やりというか・・・
マニュアルのページには以下のようなコードが載っていました。

<?php
if ( ! defined( "PATH_SEPARATOR" ) ) {
  if ( strpos( $_ENV[ "OS" ], "Win" ) !== false )
    define( "PATH_SEPARATOR", ";" );
  else define( "PATH_SEPARATOR", ":" );
}
?>

phpの定数とか関数の初期値は、バージョンが変われば変化してしまう危険があるので、あまり使いたくないけど、どの道php6はまだ先のことだろうから、とりあえずPATH_SEPARATORをつかってしのぐことにしようかな。

.htaccessでやればいいみたいだけど、詳しい説明が載ってない。
設定済みのものを取得私鉄かしたいような場合だと、.htaccessでは全部書き直さなければいけないようなので、phpで一度取得した後に再設定する方法がいいのだろう・・・。

と、散々愚痴っていたけど、php.iniをよく見たら

; UNIX: "/path1:/path2"
; Windows: "\path1;\path2"


このように、しっかり書かれてあった。

まとめると、以下のようになる
php.iniで設定する場合

include_path = ".;c:\php\pear;c:\php\cli\pear;c:\home\php_myLib"

.htaccessで設定
する場合

php_value include_path ".:/usr/local/lib/php:/home/user/php_myLib"

長いこと使っていても知らなかった。
というか、使うことがなかっただけかもしれない。

PHPでメールを送信するときのメモ

メール送信はどうも使い慣れません。
現在のWebコンテンツでメール送信は切っても切り離せないものですが、どうも使い方に慣れません。

とりあえず、何度かこうやってメモしていけば体が覚えてくれることでしょう。
本棚にはオライリーの4000円もする「電子メールプロトコル」の本がありますが、たいして活用されていません。

とりあえず、さて、メールを送信したアドレスが存在しない場合、その送信先のドメインが存在しなかったり、ユーザが存在以内場合はリターンメールが返ってくるのですが、その通知先を指定できます。
(そもそもこの考え方であっているのか?)
ヘッダでは「Return-Path」です。
ヘッダにあたる部分には以下のように記述しておくことになっています。

Return-Path: return@exsample.com


しかし、この方法ではほとんど有効ではなく、スクリプトやサーバが指定したものに強制的に上書きされることがほとんどのようです。
もちろん、設定できるのですが、動的に変化させる場合この方法では使えません。
これを回避するには、sendmailへのスイッチが有効なようです。
PHPでは第5引数に次の内容を追加します。

"-f return@exsample.com"


つまり実際にはこうなります。

mb_send_mail( $to, $subject, $body, $headers, "-f $mail" );

これで、受信したメールのソースを見ても正常に設定されました。

メール送信用のモジュールやライブラリを使っている場合はこの限りではありませんので、ご注意ください。

参考にしたのはこのあたり
http://builder.japan.zdnet.com/member/u87200/blog/2009/02/08/entry_27020134/

PHPのHTTP_Clientライブラリ

ファイルをアップロードするにはHTTP_Clientがいいらしいんだけど、
セッションでログイン管理しているからCookieを食わせなくてはいけない。
正確には、すでに食っているので、クッキーの値を送ってやる必要がある。
いろいろ調べてみると、HTTP_Client_CookiManagerというものがあって、passCookies()でセットできるらしいところまではわかったけどうまくいかない。
解説サイトも翻訳しただけで、ろくなサイトが見つからない。
やっぱりこういうクライアント側のごにょごにょはPerlしか使い物にならないのだろうか・・・

PHPの関数「mysql_insert_id()」について

データベースを利用していて、割と使用頻度の高い関数mysql_insert_id()
同時に書き込んだ場合、この値が狂うとこまるし、テーブルをロックしたほうがいいのかどうかを調べてみました。
PHP: mysql_insert_id – Manualによれば、セッションで管理されていて、MySQLのlast_insert_idと同じ機能だということです。
つまり、テーブルをロックする必要はないということでした。

PHPでExcelを読み書きする

PHPでEXCELを読み書きするには、

  • Spreadsheet_Excel_Writer
  • Spreadsheet_Excel_Reader

が便利です。
ドキュメントの使い方だけを載せているサイトは沢山ありますが、インストール方法を載せているサイトはぜんぜん無いので書いておきます。

WriteはPEARに登録されていますが、Readerは手動でインストールする必要があります。それにWriteの利用にはOLEのインストールも必要になります。WriterとOLEは共に開発版だったので、-fオプションをつけてインストールする必要があります。

pear install -f OLE
pear install -f Spreadsheet_Excel_Writer

次にReaderのインストールですが、SourceForgeで公開されているので、書庫を保存します。
必要なファイルはExcelフォルダとその中にある2つのファイル「reader.php」と「oleread.inc」です。
Excelのディレクトリごと、PEAR保存フォルダの「Spreadsheet」ディレクトリにコピーします。

本来はこれで仕えるはずですが、残念ながらそうは行きません。

reader.phpを編集してrequireするファイル名を変更します。31行目を削除またはコメントアウトして、1行追加してください。

//require_once 'Spreadsheet/Excel/Reader/OLERead.php';
require_once 'oleread.inc';

OLERead.phpは検索しても出てこないので、PEARに登録するときにこの名前にするつもりだったとか、開発環境ではこの名前になっているとか言う落ちでしょう。自分でもたまにやりますから。これでSpreadsheet_Excel_Readerが動くようになりました。このライブラリの使い方は別の機会に。
おまけ
Writerの解説ページ

Excelを読むにはPerlとPHPのどちらが便利?

Excelのデータを読む必要が出てきました。
稼動しているシステムでは表向きはPHP、内部はほぼPerlという、
純粋なPHPプログラマにはお手上げのシステムです。
もちろん私はPerlerなので、痛くも痒くもありませんが。

さて、例によってPerlとPHPの間にゴングが鳴らされました。
Perlはお決まりのものがあるので置いといて、PHPのPEARでExcelを探してみると・・・

  1. Spreadsheet_Excel_Writer: Package for generating Excel spreadsheets
  2. Structures_DataGrid_DataSource_Excel: DataSource driver using Excel spreadsheets
  3. Structures_DataGrid_Renderer_XLS: Renderer driver using PEAR::Spreadsheet_Excel_Writer

この3つがヒットしました。
ちなみに、PECLには登録なしでした。
なんかいまいちっぽいので、PEARに登録の無いものを探してみることに。

PHPExcelなるものを発見しました。
このライブラリを取り上げているサイトは多いけど、
実際に使っていたり、サンプルコードを掲示しているサイトが一つも無い・・・
Documentを読んだ限りでは多機能だとわかりますが、
本当に動くかどうか検証されていないものをシステムに入れるわけには行きません。

やはり使い慣れたPerlモジュール「Spreadsheet::ParseExcel」の出番ですか・・・

PHP:GDでPNG画像を作る

GDはイメージリソースを作ると、黒で塗りつぶすという余計な事をやってくれます。
そのため、まず間違いなく塗りなおす作業が必要です。
ちなみに、ImageMagickやPerlMagickでは xc:none で透明なキャンバスを作れます。

$image = imagecreatetruecolor( $width, $height ); // イメージリソースを作成
imagealphablending( $image, false ); // アルファブレンディングを無効(謎)
imageSaveAlpha( $image, true ); // アルファチャンネルを有効(謎)
$transparent = imagecolorallocatealpha( $image, 0, 0, 0, 127 ); // 透明度を持つ色を作成
imagefill( $image, 0, 0, $transparent ); // 塗りつぶす


以下のように、透明色だけを設定した場合、
その画像自体では透明になるけれど、他の画像と合成すると透過しなくなる。

// 透明色を灰色に設定(灰色が無い前提)
$transparent = imagecolorallocate( $image, 127, 127, 127 );
ImageColorTransparent( $image, $transparent );