LoginSignup
19
13

More than 5 years have passed since last update.

PHP:オブジェクトからネームスペースを取り除いたクラス名を取得する関数

Last updated at Posted at 2016-02-17

Foo\Bar\Buzクラスのインスタンスから"Buz"を求める関数です。

いろんな実装方法があるのですが、結論から言うと読みやすさと速さの観点から(new \ReflectionClass($obj))->getShortName()が一番良さそうです。

実装1: クラス名をファイルパスに見立ててbasenameで調べるhackeyなパターン

namespace Foo;
class Bar {}

function get_simple_name1($obj) {
    return basename(strtr(get_class($obj), '\\', '/'));
}

assert(get_simple_name1(new \Foo\Bar) === 'Bar');
assert(get_simple_name1(new \Exception) === 'Exception');

実装2: 一度配列にして取り出すパターン

function get_simple_name2($obj) {
    return array_slice(explode('\\', get_class($obj)), -1)[0];
}

assert(get_simple_name2(new \Foo\Bar) === 'Bar');
assert(get_simple_name2(new \Exception) === 'Exception');

実装3: リフレクションで調べるパターン

function get_simple_name3($obj) {
    return (new \ReflectionClass($obj))->getShortName();
}

assert(get_simple_name3(new \Foo\Bar) === 'Bar');
assert(get_simple_name3(new \Exception) === 'Exception');

実装4: 文字列のオフセットで切り取るパターン

function get_simple_name4($obj) {
    $class = get_class($obj);
    return substr($class, -strrpos($class, '\\'));
}

assert(get_simple_name4(new \Foo\Bar) === 'Bar');
assert(get_simple_name4(new \Exception) === 'Exception');

速さのベンチマーク

どれが良いかよくわからないので、速度を比較してみる。

function benchmark($name, callable $test) {
    $start = microtime(true);
    for ($i = 0; $i < 100000; $i += 1) $test();
    echo $name, ': ', microtime(true) - $start, PHP_EOL;
}

$obj = new \Foo\Bar;
benchmark('get_simple_name1', function() use ($obj) {
    get_simple_name1($obj);
});
benchmark('get_simple_name2', function() use ($obj) {
    get_simple_name2($obj);
});
benchmark('get_simple_name3', function() use ($obj) {
    get_simple_name3($obj);
});
benchmark('get_simple_name4', function() use ($obj) {
    get_simple_name4($obj);
});

結果は、リフレクションが一番早いけれど、有意差があるかは不明だが、get_classが遅いんじゃないかという仮説がたちました

get_simple_name1: 0.41280698776245
get_simple_name2: 0.42476606369019
get_simple_name3: 0.39611792564392
get_simple_name4: 0.41671085357666

get_classはリフレクションより早かったです。

$obj = new \Foo\Bar;
benchmark('get_class', function() use ($obj) {
    get_class($obj);
});
benchmark('ReflectionClass', function() use ($obj) {
    (new \ReflectionClass($obj))->getShortName();
});
get_class:       0.15777897834778
ReflectionClass: 0.31506705284119
19
13
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19
13