calias: クラスのエイリアスを登録するエクステンション

php_calias-0.0.1.tgz
この前のKOF2007の打ち上げ兼Piece Network 1の打ち合わせで出た話を元に、PHP 5.3/6.0の名前空間とは異なる、既存クラスのエイリアスを登録するエクステンションを書いてみました。PHP 5.2以降対応です。
Application Sever SAPIもしくはPersister Extensionについても計画中。企画倒れになるかもしれませんが。

使用例

基本的な使い方は、calias_register()でエイリアスを登録するだけです。calias_unregister()でエイリアスを解除、calias_clear()で一括解除もできます。

<?php
class Foo_Bar_Baz_Qux
{
	/* ... */
}

var_dump(calias_register('BBQ', 'Foo_Bar_Baz_Qux')); // エイリアスを登録

$bbq = new BBQ; // BBQとしてFoo_Bar_Baz_Quxのインスタンスを生成
var_dump(get_class($bbq));

var_dump(calias_unregister('BBQ')); // エイリアスを解除

$bbq2 = new Foo_Bar_Baz_Qux; // オリジナルはそのまま利用できる
var_dump(get_class($bbq2));

$bbq3 = new BBQ; // エイリアスは解除されているのでエラー
bool(true)
string(15) "Foo_Bar_Baz_Qux"
bool(true)
string(15) "Foo_Bar_Baz_Qux"

Fatal error: Class 'BBQ' not found in /path/to/bbq.php on line 17

Call Stack:
    0.0005      12345   1. {main}() /path/to/bbq.php:0


calias_delim2ns()でZend Frameworkのクラスを名前空間を使ったクラス名に変換してみるテスト。
名前空間の仕様はPHP 5.3/6.0の正式リリースまでに仕様が変わる可能性があります。

<?php
namespace Zend;
use Zend::Db::Adapter::Pdo as Zpdo;
require_once 'Zend/Db/Adapter/Pdo/Pgsql.php';

print_r(calias_delim2ns('Zend_'));

$config = new Config(array('dbname'   => 'foo',
                           'username' => 'bar',
                           'password' => 'baz'));

$db = new Zpdo::Pgsql($config);

var_dump(get_class($config), get_class($db));
Array
(
    [Zend::Db::Adapter::Abstract] => Zend_Db_Adapter_Abstract
    [Zend::Exception] => Zend_Exception
    [Zend::Config::Exception] => Zend_Config_Exception
    [Zend::Config] => Zend_Config
    [Zend::Db] => Zend_Db
    [Zend::Loader] => Zend_Loader
    [Zend::Db::Exception] => Zend_Db_Exception
    [Zend::Db::Select] => Zend_Db_Select
    [Zend::Db::Expr] => Zend_Db_Expr
    [Zend::Db::Statement::Interface] => Zend_Db_Statement_Interface
    [Zend::Db::Statement] => Zend_Db_Statement
    [Zend::Db::Statement::Pdo] => Zend_Db_Statement_Pdo
    [Zend::Db::Adapter::Pdo::Abstract] => Zend_Db_Adapter_Pdo_Abstract
    [Zend::Db::Adapter::Pdo::Pgsql] => Zend_Db_Adapter_Pdo_Pgsql
)
string(11) "Zend_Config"
string(25) "Zend_Db_Adapter_Pdo_Pgsql"

API

bool calias_register(string $alias_name, string $class_name)

既存クラスのエイリアスを登録する。(大文字小文字は無視)

$alias_nameまたは$class_nameが妥当なクラス名でないとき、クラス$class_nameが存在しないとき、クラス$alias_nameが既に存在するとき等はエラー。

bool calias_unregister(string $alias_name)

エイリアスを削除する。(大文字小文字は無視)

array calias_replace_prefix(string $prefix, string $replacement)

既存クラス名のプリフィクスを置換したエイリアスを一括で登録する。(大文字小文字は無視)

$prefixが空のとき、$prefixまたは$replacementが妥当なクラス名接頭辞でないとき等はエラー。置換後のエイリアス名が妥当なクラス名でない場合や既存クラス名と重複する場合は、そのエイリアスは登録されない。

戻り値は新しく登録されたエイリアス名をキー、オリジナルのクラス名を値とする連想配列

array calias_delim2ns([string $prefix])

(PHP 5.3以降のみ)

既存クラス名のアンダースコアをダブルコロン (Zend用語でPaamayim Nekudotayim、読めない) で置換したエイリアスを一括で登録する。特定のクラス群だけを対象にしたい場合は$prefixで制限できる。

置換後のエイリアス名が妥当なクラス名でない場合や既存クラス名と重複する場合は、そのエイリアスは登録されない。

戻り値は新しく登録されたエイリアス名をキー、オリジナルのクラス名を値とする連想配列

array calias_list(void)

登録済みのエイリアスのリストを取得する。

戻り値はエイリアス名をキー、オリジナルのクラス名を値とする連想配列

void calias_clear(void)

全てのエイリアスを一括で解除する。

仕様

PHPのクラスはグローバル変数のハッシュテーブルCG(class_table)に小文字に正規化されたクラス名をキーとしてクラス情報 (zend_class_entry構造体のポインタのポインタ) を格納するというかたちで保持されています。そして、このエクステンションではクラス情報が参照カウント方式で管理されているという点に着目して、オリジナルのクラスの参照カウントを増やしてCG(class_table)に別のキーで登録することでエイリアスを実現しています。エイリアスは同時にエイリアス管理専用のハッシュテーブルにも登録されており、ここから削除されると同時にCG(class_table)からも削除されるようになっています。このとき、参照カウントも減らされ、エイリアス登録前と同じ値に戻ります。

class-name alias 図1