This post was updated 653 days ago and some of the ideas may be out of date.

直接上代码

function getAllClassesInFile(string $file)
{
    $classes = [];
    $tokens = token_get_all(file_get_contents($file));
    $count = count($tokens);
    // 兼容php7和php8
    $tNamespace = version_compare(PHP_VERSION, '8.0.0', '>=') ? [T_NAME_QUALIFIED, T_STRING] : [T_STRING];

    $namespace = '';
    for ($i = 2; $i < $count; $i++) {
        // 扫描到命名空间
        if ($tokens[$i - 2][0] === T_NAMESPACE && $tokens[$i - 1][0] === T_WHITESPACE) {
            // 清空命名空间
            $namespace = '';
            // 不是命名空间跳过
            if (!in_array($tokens[$i][0], $tNamespace)) {
                continue;
            }
            // 获取命名空间
            $tempNamespace = $tokens[$i][1] ?? '';
            for ($j = $i + 1; $j < $count; $j++) {
                // 如果是分号或者大括号,说明命名空间结束
                if ($tokens[$j] === '{' || $tokens[$j] === ';') {
                    break;
                }
                if ($tokens[$j][0] === $tNamespace) {
                    // 命名空间拼接
                    $tempNamespace .= '\\' . $tokens[$j][1];
                }
            }
            $namespace = $tempNamespace;
            // 扫描到类
        } else if ($tokens[$i - 2][0] === T_CLASS && $tokens[$i - 1][0] === T_WHITESPACE && $tokens[$i][0] === T_STRING) {
            // 拼接命名空间和类名
            $classes[] = ($namespace ? $namespace . '\\' : '') . $tokens[$i][1];
        }
    }

    return $classes;
}

测试一下效果

<?php

/**
 * Created by PhpStorm.
 * User: LinFei
 * Created time 2022/11/29 14:16:39
 * E-mail: fly@eyabc.cn
 */
declare (strict_types=1);

namespace App\Controllers {
    class IndexController
    {

    }
}

namespace {
    class Index
    {

    }
}

namespace App\Rpc {
    class IndexRpc
    {

    }
}

namespace {
    var_dump(getAllClassesInFile(__FILE__));
}

输出结果

array(3) {
  [0]=>
  string(31) "App\Controllers\IndexController"
  [1]=>
  string(5) "Index"
  [2]=>
  string(16) "App\Rpc\IndexRpc"
}