有点奇怪,但我想用像这样的东西从我声明的类中生成一个数组
foreach(get_declared_classes() as $class)
$c[] = $class;
print_r($c);
唯一的问题是,我在加载的类上得到了类似的东西:
stdClass
Exception
ErrorException
Closure
DateTime
DateTimeZone
DateInterval
DatePeriod
LibXMLError
LogicException
BadFunctionCallException
BadMethodCallException
DomainException
InvalidArgumentException
LengthException
OutOfRangeException
RuntimeException
OutOfBoundsException
OverflowException
RangeException
UnderflowException
UnexpectedValueException
RecursiveIteratorIterator
IteratorIterator
{...}
SQLiteResult
SQLiteUnbuffered
SQLiteException
SQLite3
SQLite3Stmt
SQLite3Result
XMLReader
XMLWriter
XSLTProcessor
ZipArchive
是否存在只加载用户特定类而不加载系统加载类的函数?或者可能是限制foreach
列出这些类的条件语句?
反射API可以检测类是否是内部的。ReflectionClass::isInternal
检查类是否是内部的,而不是用户定义的:
$userDefinedClasses = array_filter(
get_declared_classes(),
function($className) {
return !call_user_func(
array(new ReflectionClass($className), 'isInternal')
);
}
);
上面的代码将检查并删除get_declared_classes
返回的每个内部类,只留下用户定义的类。这样,您就不需要像本页其他地方建议的那样创建和维护一组内部类。
没有内置函数可以实现这一点,但您可以在声明任何内容之前使用get_declared_classes
,并将其存储在全局变量中,比如$predefinedClasses
。然后,在您需要使用的地方:
print_r(array_diff(get_declared_classes(), $predefinedClasses));
没有直接内置的可能性,但您可以执行以下操作:
- 在脚本开始时,调用
get_declared_classes()
并将其保存到类似$php_classes
的变量中 -
加载完类后,再次调用
get_declared_classes()
并使用array_diff()
过滤掉$php_classes
,结果是您自己的类的列表。// start $php_classes = get_declared_classes(); // ... // some code loading/declaring own classes // ... // later $my_classes = array_diff(get_declared_classes(), $php_classes);
这是我的解决方案,它确实有效,而且不会影响性能。这只提供了项目中定义的类,而没有其他类。确保在加载完所有类之后,尽可能晚地运行它。
/**
* Get all classes from a project.
*
* Return an array containing all classes defined in a project.
*
* @param string $project_path
* @return array
*/
function smk_get_classes_from_project( $project_path ){
// Placeholder for final output
$classes = array();
// Get all classes
$dc = get_declared_classes();
// Loop
foreach ($dc as $class) {
$reflect = new 'ReflectionClass($class);
// Get the path to the file where is defined this class.
$filename = $reflect->getFileName();
// Only user defined classes, exclude internal or classes added by PHP extensions.
if( ! $reflect->isInternal() ){
// Replace backslash with forward slash.
$filename = str_replace(array(''''), array('/'), $filename);
$project_path = str_replace(array(''''), array('/'), $project_path);
// Remove the last slash.
// If last slash is present, some classes from root will not be included.
// Probably there's an explication for this. I don't know...
$project_path = rtrim( $project_path, '/' );
// Add the class only if it is defined in `$project_path` dir.
if( stripos( $filename, $project_path ) !== false ){
$classes[] = $class;
}
}
}
return $classes;
}
测试它。
本例假设项目具有以下路径:/srv/users/apps/my-project-name
echo '<pre>';
print_r( smk_get_classes_from_project( '/srv/users/apps/my-project-name' ) );
echo '</pre>';
另一种可能的方法是:
$a= get_declared_classes();
// All user-defined classes
print_r(array_slice(get_declared_classes(), count($a)));
@Gordon的回答非常好@Dmitry的解决方案也很好,但只有当你的类在不同的文件中,并且你包含了它们时,它才有效:
$predefinedClasses = get_declared_classes();
include('Myclass.php'); // This will show
class A {} // This will not show
print_r(array_diff(get_declared_classes(), $predefinedClasses));
然而,如果你的文件中除了包含的类之外还有其他类,如果你不想使用Reflection
,我想出了一个(疯狂的)主意:
$predefined_classes = get_declared_classes();
declare(ticks=1) {
include 'Myclass.php';
class A {}
print_r(array_diff(get_declared_classes(), $predefined_classes));
}