Skip to content

Instantly share code, notes, and snippets.

@cwhite92
Last active April 19, 2024 18:25
Show Gist options
  • Save cwhite92/f0aaf008e1679b27768fbb8c884df6f7 to your computer and use it in GitHub Desktop.
Save cwhite92/f0aaf008e1679b27768fbb8c884df6f7 to your computer and use it in GitHub Desktop.
Get the FQCN from a PHP file specified by file path
<?php
public static function fqcnFromPath(string $path): string
{
$namespace = $class = $buffer = '';
$handle = fopen($path, 'r');
while (!feof($handle)) {
$buffer .= fread($handle, 512);
// Suppress warnings for cases where `$buffer` ends in the middle of a PHP comment.
$tokens = @token_get_all($buffer);
// Filter out whitespace and comments from the tokens, as they are irrelevant.
$tokens = array_filter($tokens, fn($token) => $token[0] !== T_WHITESPACE && $token[0] !== T_COMMENT);
// Reset array indexes after filtering.
$tokens = array_values($tokens);
foreach ($tokens as $index => $token) {
// The namespace is a `T_NAME_QUALIFIED` that is immediately preceded by a `T_NAMESPACE`.
if ($token[0] === T_NAMESPACE && isset($tokens[$index + 1]) && $tokens[$index + 1][0] === T_NAME_QUALIFIED) {
$namespace = $tokens[$index + 1][1];
continue;
}
// The class name is a `T_STRING` which makes it unreliable to match against, so check if we have a
// `T_CLASS` token with a `T_STRING` token ahead of it.
if ($token[0] === T_CLASS && isset($tokens[$index + 1]) && $tokens[$index + 1][0] === T_STRING) {
$class = $tokens[$index + 1][1];
}
}
if ($namespace && $class) {
// We've found both the namespace and the class, we can now stop reading and parsing the file.
break;
}
}
fclose($handle);
return $namespace.'\\'.$class;
}
@cwhite92
Copy link
Author

cwhite92 commented Sep 5, 2023

Based on my testing this works for the following examples:

namespace Foo\Bar;

use Bin\Qux;

class YourClass extends SomeOtherClass
{
    //
}
namespace Foo\Bar {
    use Bin\Qux;

    class YourClass extends SomeOtherClass
    {
        //
    }
};

and even some wonky whitespace or comments:

namespace Foo\Bar;

use Bin\Qux;

class

// I am a comment

YourClass
{
    //
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment