PHPのクラス名の取得方法について

採用はこちら

PHPでは、クラス名を取得する方法がいくつかあります。

ただし、どの方法を使うべきかは「何からクラス名を取得したいのか」によって変わります。

たとえば、すでに作成済みのオブジェクトからクラス名を取得したい場合は get_class() を使います。

一方で、クラス名を文字列として安全に扱いたい場合は User::class のような書き方がよく使われます。

また、親クラスや抽象クラスの中で子クラス名を取得したい場合は、self::class ではなく static::class を使う必要があります。

この記事では、PHPでクラス名を取得する主な方法と、それぞれの違い・使い分けについて詳しく解説します。

目次

オブジェクトからクラス名を取得する方法

get_class()を使う

すでにインスタンス化されたオブジェクトからクラス名を取得したい場合は、get_class() を使います。

class User {}

$user = new User();

echo get_class($user);

実行結果は次のようになります。

User

get_class() は、指定したオブジェクトのクラス名を文字列で返します。

名前空間がある場合は、名前空間を含む完全修飾クラス名が返ります。

namespace App\Models;

class User {}

$user = new User();

echo get_class($user);

実行結果は次のとおりです。

App\Models\User

このように、get_class() は「オブジェクトの実際のクラス名を取得したい場合」に使う方法です。

$thisのクラス名を取得する

クラスのメソッド内で、自分自身のインスタンスのクラス名を取得したい場合も get_class() を使えます。

class User
{
    public function showClassName()
    {
        echo get_class($this);
    }
}

$user = new User();
$user->showClassName();

実行結果は次のようになります。

User

継承がある場合、get_class($this) は実際に生成されたインスタンスのクラス名を返します。

class BaseModel
{
    public function showClassName()
    {
        echo get_class($this);
    }
}

class User extends BaseModel {}

$user = new User();
$user->showClassName();

実行結果は次のとおりです。

User

この例では、メソッド自体は BaseModel に定義されていますが、実際のインスタンスは User なので、User が返ります。

クラス名を文字列として取得する方法

クラス名::classを使う

PHPでは、クラス名に ::class を付けることで、そのクラスの完全修飾クラス名を文字列として取得できます。

class User {}

echo User::class;

実行結果は次のようになります。

User

名前空間がある場合は、名前空間を含むクラス名が返ります。

namespace App\Models;

class User {}

echo User::class;

実行結果は次のとおりです。

App\Models\User

User::class は、PHPの実務で非常によく使われる書き方です。

たとえば、Laravelではコントローラーやモデル、サービスクラスなどを指定するときによく使います。

use App\Http\Controllers\UserController;

Route::get('/users', [UserController::class, 'index']);

文字列で直接クラス名を書くこともできます。

$class = 'App\Http\Controllers\UserController';

しかし、この書き方はクラス名を変更したときに修正漏れが起きやすくなります。

一方、UserController::class のように書いておけば、IDEの補完やリファクタリング機能が効きやすくなります。

$class = UserController::class;

そのため、クラス名を文字列として扱いたい場合は、基本的に クラス名::class を使うのがおすすめです。

::classはクラスの存在確認ではない

User::class は、クラス名を文字列として取得する構文です。

ただし、これは「そのクラスが実際に存在するかどうか」を確認するためのものではありません。

$class = App\Models\User::class;

このコードは、基本的には次のような文字列を取得するためのものです。

App\Models\User

クラスが存在するか確認したい場合は、class_exists() を使います。

$class = App\Models\User::class;

if (class_exists($class)) {
    $user = new $class();
}

つまり、::class はクラス名を安全に文字列として扱うための書き方であり、存在確認のための関数ではありません。

クラス内部でクラス名を取得する方法

__CLASS__を使う

クラスの内部で、そのクラス自身の名前を取得したい場合は __CLASS__ を使えます。

class User
{
    public function showClassName()
    {
        echo __CLASS__;
    }
}

$user = new User();
$user->showClassName();

実行結果は次のようになります。

User

名前空間がある場合は、名前空間を含むクラス名が返ります。

namespace App\Models;

class User
{
    public function showClassName()
    {
        echo __CLASS__;
    }
}

この場合、実行結果は次のようになります。

App\Models\User

__CLASS__ はマジック定数の一つです。

そのため、実行時のオブジェクトではなく、「そのコードが書かれているクラス」を基準にクラス名を返します。

__CLASS__は継承先のクラス名を返さない

__CLASS__ を使うときに注意したいのは、継承先のクラス名を返すわけではないという点です。

class BaseModel
{
    public function showClassName()
    {
        echo __CLASS__;
    }
}

class User extends BaseModel {}

$user = new User();
$user->showClassName();

このコードの実行結果は次のようになります。

BaseModel

User ではなく、BaseModel が返ります。

これは、__CLASS__ が「そのコードが定義されているクラス」を返すためです。

つまり、親クラスに書かれた __CLASS__ は、子クラスから呼び出しても親クラス名を返します。

self::classとstatic::classの違い

self::classは定義元のクラス名を返す

self::class も、クラス内部でクラス名を取得するときに使えます。

class User
{
    public function showClassName()
    {
        echo self::class;
    }
}

$user = new User();
$user->showClassName();

実行結果は次のようになります。

User

ただし、self::class__CLASS__ と同じように、基本的には定義元のクラスを基準に解決されます。

class BaseModel
{
    public static function showClassName()
    {
        echo self::class;
    }
}

class User extends BaseModel {}

User::showClassName();

実行結果は次のとおりです。

BaseModel

このように、self::class は実際に呼び出したクラスではなく、そのメソッドが定義されているクラス名を返します。

static::classは継承先のクラス名を考慮する

親クラスや抽象クラスの中で、実際に呼び出された子クラス名を取得したい場合は static::class を使います。

class BaseModel
{
    public static function showClassName()
    {
        echo static::class;
    }
}

class User extends BaseModel {}

User::showClassName();

実行結果は次のようになります。

User

static::class は、PHPの遅延静的束縛、つまり late static bindings によって解決されます。

そのため、親クラスに書かれていても、実際に呼び出されたクラスが User であれば User が返ります。

インスタンスメソッド内でも同じように使えます。

class BaseModel
{
    public function showClassName()
    {
        echo static::class;
    }
}

class User extends BaseModel {}

$user = new User();
$user->showClassName();

実行結果は次のとおりです。

User

self::classとstatic::classの使い分け

self::classstatic::class は似ていますが、継承が関係すると結果が変わります。

class BaseModel
{
    public static function showSelf()
    {
        echo self::class;
    }

    public static function showStatic()
    {
        echo static::class;
    }
}

class User extends BaseModel {}

User::showSelf();
echo "\n";
User::showStatic();

実行結果は次のようになります。

BaseModel
User

使い分けは次のように考えるとわかりやすいです。

self::class;   // 定義元のクラス名を取得したい場合
static::class; // 実際に呼び出されたクラス名を取得したい場合

親クラスや抽象クラスで子クラス名を扱いたい場合は、static::class を使うのが基本です。

get_called_class()を使う方法

呼び出し元クラス名を取得する

get_called_class() を使っても、実際に呼び出されたクラス名を取得できます。

class BaseModel
{
    public static function showClassName()
    {
        echo get_called_class();
    }
}

class User extends BaseModel {}

User::showClassName();

実行結果は次のようになります。

User

get_called_class() は、late static bindings における呼び出し元クラス名を取得する関数です。

そのため、親クラスに定義されたメソッドの中で使っても、子クラスから呼び出されれば子クラス名が返ります。

static::classの方が読みやすい場合が多い

現在のPHPでは、単に呼び出し元クラス名を取得したいだけであれば、get_called_class() よりも static::class の方が読みやすい場面が多いです。

class BaseModel
{
    public static function showClassName()
    {
        echo static::class;
    }
}

get_called_class() が間違いというわけではありません。

ただし、コードの見通しを考えると、現在のPHPでは static::class を使った方が意図が伝わりやすいことが多いです。

名前空間なしのクラス名を取得する方法

ReflectionClass::getShortName()を使う

get_class()User::class は、名前空間を含む完全修飾クラス名を返します。

App\Models\User

ここから User だけを取得したい場合は、ReflectionClass::getShortName() を使うと便利です。

namespace App\Models;

class User {}

$reflection = new \ReflectionClass(User::class);

echo $reflection->getShortName();

実行結果は次のようになります。

User

ReflectionClass を使うと、短いクラス名だけでなく、完全なクラス名や名前空間も取得できます。

$reflection = new \ReflectionClass(User::class);

echo $reflection->getName();
echo $reflection->getNamespaceName();
echo $reflection->getShortName();

それぞれ、次のような値を取得できます。

App\Models\User
App\Models
User

名前空間を除いたクラス名だけが欲しい場合は、文字列処理で対応することもできます。

しかし、可読性や安全性を考えると、基本的には ReflectionClass::getShortName() を使う方がわかりやすいです。

文字列処理で短いクラス名を取得する

Reflectionを使わずに、文字列処理で短いクラス名を取得することもできます。

$class = App\Models\User::class;

$parts = explode('\\', $class);
$shortName = end($parts);

echo $shortName;

実行結果は次のとおりです。

User

この方法はシンプルですが、クラス名を文字列として分解しているだけです。

より安全に書くなら、次のような方法もあります。

$class = App\Models\User::class;

$shortName = basename(str_replace('\\', '/', $class));

echo $shortName;

一方で、次のような書き方は注意が必要です。

$shortName = substr(strrchr($class, '\\'), 1);

この方法は、クラス名に名前空間が含まれている場合は動きます。

しかし、名前空間がないクラス名に対して使うと、期待どおりに動かない可能性があります。

そのため、短いクラス名を取得したい場合は、基本的には次の書き方がおすすめです。

$shortName = (new \ReflectionClass($class))->getShortName();

動的にクラスを扱う方法

クラス名からインスタンスを生成する

PHPでは、クラス名を文字列として持っていれば、その文字列を使ってインスタンスを生成できます。

class User {}

$class = User::class;

$user = new $class();

これは次のように書いているのと同じ意味です。

$user = new User();

名前空間付きのクラスでも同じように使えます。

namespace App\Models;

class User {}

$class = User::class;

$user = new $class();

このような動的なインスタンス生成は、ファクトリ、DIコンテナ、サービスクラスの解決などで使われることがあります。

ただし、コンストラクタ引数が必要なクラスでは、単純に new $class() と書くだけではインスタンス化できない場合があります。

class UserService
{
    public function __construct(LoggerInterface $logger)
    {
    }
}

このような場合は、LaravelやSymfonyなどのフレームワークではDIコンテナを使ってインスタンスを解決するのが一般的です。

$service = app(UserService::class);

get_class()を使うときの注意点

引数なしのget_class()は避ける

古いPHPコードでは、次のような書き方を見ることがあります。

class User
{
    public function showClassName()
    {
        echo get_class();
    }
}

しかし、現在の新規コードではこの書き方は避けた方がよいです。

PHP 8.3以降では、引数なしの get_class() は非推奨になっています。

そのため、次のように明示的に書くのがおすすめです。

get_class($this);

また、目的に応じて次のように書き分けます。

self::class;   // 定義元クラス名を取得したい場合
static::class; // 呼び出し元クラス名を取得したい場合

つまり、現在のPHPでは次のような書き方は避けるべきです。

get_class();

代わりに、何のクラス名を取得したいのかを明確にして書きましょう。

get_class($object);
get_class($this);
self::class;
static::class;

実務でよく使うクラス名取得の例

Laravelのルートで使う

Laravelでは、コントローラーを指定するときに ::class がよく使われます。

use App\Http\Controllers\UserController;

Route::get('/users', [UserController::class, 'index']);

文字列でコントローラー名を書くよりも、IDEの補完やリファクタリングに強くなります。

ログにクラス名を出力する

処理ログにクラス名を含めたい場合は、static::class を使うと便利です。

class UserService
{
    public function execute()
    {
        logger()->info(static::class . ' started');
    }
}

継承を前提にしたクラスであれば、static::class を使うことで子クラス名をログに出しやすくなります。

例外メッセージにクラス名を含める

例外メッセージにクラス名を含める場合にも使えます。

throw new \RuntimeException(static::class . ' failed.');

どのクラスでエラーが発生したかをメッセージに含められるため、デバッグしやすくなります。

親クラスで子クラス名を扱う

抽象クラスや親クラスで子クラス名を使いたい場合は、static::class が便利です。

abstract class BaseRepository
{
    public function getClassName()
    {
        return static::class;
    }
}

class UserRepository extends BaseRepository {}

$repository = new UserRepository();

echo $repository->getClassName();

実行結果は次のようになります。

UserRepository

このように、親クラス側に共通処理を書きつつ、子クラスごとのクラス名を取得できます。

クラス名取得方法の使い分け

目的別の使い分け

PHPでクラス名を取得する方法は複数ありますが、目的別に整理すると次のようになります。

目的使う方法
オブジェクトから実際のクラス名を取得したいget_class($object)
自分自身のインスタンスのクラス名を取得したいget_class($this)
クラス名を文字列として安全に取得したいUser::class
定義元のクラス名を取得したいself::class / __CLASS__
継承先・呼び出し元クラス名を取得したいstatic::class
late static bindingsの呼び出し元クラス名を取得したいget_called_class()
名前空間なしの短いクラス名を取得したいReflectionClass::getShortName()

実務で覚えておきたい基本形

実務では、まず次の4つを覚えておけば多くのケースに対応できます。

// オブジェクトからクラス名を取得する
$className = get_class($object);

// クラス名を文字列として取得する
$className = User::class;

// 親クラスや抽象クラスで子クラス名を取得する
$className = static::class;

// 名前空間なしのクラス名を取得する
$shortName = (new \ReflectionClass($className))->getShortName();

この4つを押さえておけば、PHPでクラス名を取得する基本的な場面にはほとんど対応できます。

まとめ

PHPでクラス名を取得する方法は、用途によって使い分けることが重要です。

すでにオブジェクトがある場合は、get_class($object) を使います。

クラス名を文字列として扱いたい場合は、User::class のように書くのがおすすめです。

クラス内部で定義元のクラス名を取得したい場合は、self::class__CLASS__ を使います。

一方で、親クラスや抽象クラスの中から子クラス名を取得したい場合は、static::class を使います。

また、名前空間を除いた短いクラス名だけが欲しい場合は、ReflectionClass::getShortName() を使うとわかりやすく安全です。

最後に、PHP 8.3以降では引数なしの get_class() が非推奨になっているため、新規コードでは使わないようにしましょう。

基本的には、次のように使い分ければ問題ありません。

get_class($object); // オブジェクトの実クラス名
User::class;        // クラス名を文字列として取得
self::class;        // 定義元クラス名
static::class;      // 呼び出し元クラス名

クラス名の取得は、ログ出力、例外処理、DIコンテナ、ルーティング、ファクトリパターンなど、実務でもよく使われます。

それぞれの違いを理解しておくと、継承や名前空間を含むコードでも意図したクラス名を正しく取得できるようになります。

以上、PHPのクラス名の取得方法についてでした。

最後までお読みいただき、ありがとうございました。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次