Determining what classes are defined in a PHP class file
I needed something like this for a project I am working on, and here are the functions I wrote:
function file_get_php_classes($filepath) {
$php_code = file_get_contents($filepath);
$classes = get_php_classes($php_code);
return $classes;
}
function get_php_classes($php_code) {
$classes = array();
$tokens = token_get_all($php_code);
$count = count($tokens);
for ($i = 2; $i < $count; $i++) {
if ( $tokens[$i - 2][0] == T_CLASS
&& $tokens[$i - 1][0] == T_WHITESPACE
&& $tokens[$i][0] == T_STRING) {
$class_name = $tokens[$i][1];
$classes[] = $class_name;
}
}
return $classes;
}
How do I find all the classes used in a PHP file?
Parsing and then interpreting PHP code is not something that can be solved well using a regex. You would need a something much more clever, like a state machine, that can actually understand things like scope, class names, inheritance etc to be able to do what you want.
It just so happens, that I happen to have written a PHP-to-Javascript converter based on a state-machine that will almost do most of what you want to do:
all the defined classes
Yes, all the classes create a ClassScope with all their variables listed and their methods are created as FunctionScope's, so you can tell which methods a class has.
anything they extend
Yes, every class has it's parent classes listed in ClassScope->$parentClasses
any created instances
Nope, but wouldn't be hard to add extra code to record these.
anytime they were statically invoked.
Nope - but that actually could be done with a regex.
Although it doesn't exactly solve your problem, the project as it stands would get you 95% of the way towards what you want to do, which would save a couple weeks work.
Finding the PHP File (at run time) where a Class was Defined
Try ReflectionClass
- ReflectionClass::getFileName — Gets a filename
Example:
class Foo {}
$reflector = new \ReflectionClass('Foo');
echo $reflector->getFileName();
This will return false
when the filename cannot be found, e.g. on native classes.
Get class name from file
There are multiple possible solutions to this problem, each with their advantages and disadvantages. Here they are, it's up to know to decide which one you want.
Tokenizer
This method uses the tokenizer and reads parts of the file until it finds a class definition.
Advantages
- Do not have to parse the file entirely
- Fast (reads the beginning of the file only)
- Little to no chance of false positives
Disadvantages
- Longest solution
Code
$fp = fopen($file, 'r');
$class = $buffer = '';
$i = 0;
while (!$class) {
if (feof($fp)) break;
$buffer .= fread($fp, 512);
$tokens = token_get_all($buffer);
if (strpos($buffer, '{') === false) continue;
for (;$i<count($tokens);$i++) {
if ($tokens[$i][0] === T_CLASS) {
for ($j=$i+1;$j<count($tokens);$j++) {
if ($tokens[$j] === '{') {
$class = $tokens[$i+2][1];
}
}
}
}
}
Regular expressions
Use regular expressions to parse the beginning of the file, until a class definition is found.
Advantages
- Do not have to parse the file entirely
- Fast (reads the beginning of the file only)
Disadvantages
- High chances of false positives (e.g.:
echo "class Foo {";
)
Code
$fp = fopen($file, 'r');
$class = $buffer = '';
$i = 0;
while (!$class) {
if (feof($fp)) break;
$buffer .= fread($fp, 512);
if (preg_match('/class\s+(\w+)(.*)?\{/', $buffer, $matches)) {
$class = $matches[1];
break;
}
}
Note: The regex can probably be improved, but no regex alone can do this perfectly.
Get list of declared classes
This method uses get_declared_classes()
and look for the first class defined after an include.
Advantages
- Shortest solution
- No chance of false positive
Disadvantages
- Have to load the entire file
- Have to load the entire list of classes in memory twice
- Have to load the class definition in memory
Code
$classes = get_declared_classes();
include 'test2.php';
$diff = array_diff(get_declared_classes(), $classes);
$class = reset($diff);
Note: You cannot simply do end()
as others suggested. If the class includes another class, you will get a wrong result.
This is the Tokenizer solution, modified to include a $namespace variable containing the class namespace, if applicable:
$fp = fopen($file, 'r');
$class = $namespace = $buffer = '';
$i = 0;
while (!$class) {
if (feof($fp)) break;
$buffer .= fread($fp, 512);
$tokens = token_get_all($buffer);
if (strpos($buffer, '{') === false) continue;
for (;$i<count($tokens);$i++) {
if ($tokens[$i][0] === T_NAMESPACE) {
for ($j=$i+1;$j<count($tokens); $j++) {
if ($tokens[$j][0] === T_STRING) {
$namespace .= '\\'.$tokens[$j][1];
} else if ($tokens[$j] === '{' || $tokens[$j] === ';') {
break;
}
}
}
if ($tokens[$i][0] === T_CLASS) {
for ($j=$i+1;$j<count($tokens);$j++) {
if ($tokens[$j] === '{') {
$class = $tokens[$i+2][1];
}
}
}
}
}
Say you have this class:
namespace foo\bar {
class hello { }
}
...or the alternative syntax:
namespace foo\bar;
class hello { }
You should have the following result:
var_dump($namespace); // \foo\bar
var_dump($class); // hello
You could also use the above to detect the namespace a file declares, regardless of it containing a class or not.
List All Classes And Methods In A Script File
OK, this is what I'd suggest :
// Get new class name
$classes = get_declared_classes();
include 'your_php_file.php';
$diff = array_diff(get_declared_classes(), $classes);
$class = reset($diff);
// Get class's methods
$methods = get_class_methods($class);
// Print them out
echo "Class : ".$class;
foreach ($methods as $method) {
echo "$method\n";
}
Get all defined classes of a parent class in php
If you need that, it really smells like bad code, the base class shouldn't need to know this.
However, if you definitions have been included (i.e. you don't need to include new files with classes you possibly have), you could run:
$children = array();
foreach(get_declared_classes() as $class){
if($class instanceof foo) $children[] = $class;
}
Related Topics
Checking If Array Is Multidimensional or Not
How to Install the Ext-Curl Extension with PHP 7
How to Easily Consume a Web Service from PHP
PHP Objects VS Arrays -- Performance Comparison While Iterating
PHP Technique to Query the Apns Feedback Server
Turn Off Warnings and Errors on PHP and MySQL
PHP Curl Curlopt_Ssl_Verifypeer Ignored
PHP Add Elements to Multidimensional Array with Array_Push
How to Add New Column to MySQL Table
Save Current Page as HTML to Server
How to Create a Database Using Pdo in PHP
Using PHP to Output an Mp4 Video