btoメモ

なんか適当に書く

PHPで拡張を動的に有効にする汎用的な方法

PHPの拡張とは

PHPの機能を拡張するためにCで書かれた動的ライブラリのこと。

拡張を有効にするには

拡張を有効にする方法はphp.iniに設定する方法とdl()から動的に呼び出す方法の2つ。

動的に拡張を追加するにはdl()を使います。

dl()を使う問題点

dl('foo'); のように拡張名だけ指定して有効にできると便利なのですが、ちゃんと拡張のファイル名を指定しなければいけません。

で、ファイル名がOSによって異なるので、呼び出し方が異なります。

UNIX系OSの場合、拡張子が "so" になる。

dl('foo.so');

Windowsの場合、拡張子が "dll" になって、さらにファイル名の先頭に "php_" という文字列がつく。

dl('php_foo.dll');

LLなんだから、こういう基本的なところは簡便にできるようにして欲しいな〜。

それとも動的に拡張を読み込むのは特殊ケースなのかしら?

PHP_SHLIB_SUFFIXを使う

最近のPHPではPHP_SHLIB_SUFFIXという定数に拡張の拡張子が定義されているので、それを使えばOK。

$prefix = PHP_SHLIB_SUFFIX === 'dll' ? 'php_' : '';

dl($prefix.'foo.'.PHP_SHLIB_SUFFIX);

PHP_SHLIB_SUFFIXが定義されてない場合

古いPHPではPHP_SHLIB_SUFFIXが定義されてない。

そういう場合はPHP_OSを見て、Windowsかどうかで無理矢理処理する。

$suffix = strtoupper(substr(PHP_OS, 0, 3)) === 'WIN' ? 'dll' : 'so';

$prefix = $suffix === 'dll' ? 'php_' : '';

dl($prefix.'foo.'.$suffix);

Mac OS Xで動かない><

これで完璧だと思ったんだけど、Mac OS Xで動かない><

PHP_SHLIB_SUFFIX が "dylib" なのに、拡張が ".so" でインストールのが原因。

どっちやねん(怒

でも、将来的に ".so" から ".dylib" に変更されるかもしれない可能性を考えると、あまりアドホックにやりたくない。

というわけでいくつか候補となるファイル名をいくつか試してdl()を呼び出すことにして回避。

loadExtension()

というわけで、最終的にできた完成系がこれ。

function loadExtension($extension)

{

if (extension_loaded($extension)) {

return true;

}

if (defined('PHP_SHLIB_SUFFIX')) {

$suffix = PHP_SHLIB_SUFFIX;

} else if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {

$suffix = 'dll';

} else {

$suffix = 'so';

}

$prefix = $suffix === 'dll' ? 'php_' : '';

$libraries = array("{$prefix}{$extension}.{$suffix}");

$libraries[] = "{$extension}.so";

$libraries[] = "php_{$extension}.dll";

$libraries = array_unique($libraries);

foreach ($libraries as $library) {

if (@dl($library)) {

return true;

}

}

return false;

}

LinuxでもWindowsでもMac OS Xでもうまくいくはず。

できるだけ汎用的に書いているので、多少環境が変わっても(Mac OS X拡張子がdylibに変更とか)大丈夫なようになってるはず。