Jump to content

Get class name by filename


NotionCommotion

Recommended Posts

I want to validate my PHP files to ensure that I didn't forget to import all the classes assigned to attributes.  I will be using ReflectionClass to do so and need the FQCN's and not the filenames.  Originally, I tried get_declared_classes(), however, ran into issues where a class was already declared.  I came up with the following which appears to work, however, it was created based on trial and error and suspect there might be edge cases where it will not provide the desired results (and it is pretty damn ugly as well).  How would you recommend doing so?  A couple thoughts are:

  • Use composer to come up with the classes based on filename and use either vendor/Composer autoload_classmap.php or autoload_static.php.  I don't really like this approach as it requires me to update composer to add any new files.
  • Use composer but figure out how it generates the class map and use a similar approach.  Appears that it is using phpstan or some other utility but I haven't really investigated.
  • Use some third party script to generate the class maps.  If so, please provide recommendations.
  • Use some more modern approach other than PhpToken.  If so, please provide recommendations.
  • Use get_declared_classes() to get a base line and then require the PHP file to find the added class names and somehow deal with issues related to classes already being declared.
  • Use tokens and my parseFile() method.  If so, any recommendations on changing?

PS.  I originally wasn't 100% that attributes in traits and abstract classes would be propagated to the concrete class, but I should have known it to be true and this was confirmed by testing.  At this time, I really just need the concrete classes, however, maybe in the future I will use the script to do some analysis on interfaces, traits, etc. 

 

 

    private function parseFile(string $filename):array
    {
        $getNext=null;
        $getNextNamespace=false;
        $skipNext=false;
        $isAbstract = false;
        $rs = ['namespace'=>null, 'class'=>[], 'trait'=>[], 'interface'=>[], 'abstract'=>[]];
        foreach (\PhpToken::tokenize(file_get_contents($filename)) as $token) {
            if(!$token->isIgnorable()) {
                $name = $token->getTokenName();
                switch($name){
                    case 'T_NAMESPACE':
                        $getNextNamespace=true;
                        break;
                    case 'T_EXTENDS':
                    case 'T_USE':
                    case 'T_IMPLEMENTS':
                        //case 'T_ATTRIBUTE':
                        $skipNext = true;
                        break;
                    case 'T_ABSTRACT':
                        $isAbstract = true;
                        break;
                    case 'T_CLASS':
                    case 'T_TRAIT':
                    case 'T_INTERFACE':
                        if($skipNext) {
                            $skipNext=false;
                        }
                        else {
                            $getNext = strtolower(substr($name, 2));
                        }
                        break;
                    case 'T_NAME_QUALIFIED':
                    case 'T_STRING':
                        if($getNextNamespace) {
                            if(array_filter($rs)) {
                                throw new \Exception(sprintf('Namespace mus be defined first in %s', $filename));
                            }
                            else {
                                $rs['namespace'] = $token->text;
                            }
                            $getNextNamespace=false;
                        }
                        elseif($skipNext) {
                            $skipNext=false;
                        }
                        elseif($getNext) {
                            if(in_array($token->text,  $rs[$getNext])) {
                                throw new \Exception(sprintf('%s %s has already been found in %s', $rs[$getNext], $token->text, $filename));
                            }
                            if($isAbstract) {
                                $isAbstract=false;
                                $getNext = 'abstract';
                            }
                            $rs[$getNext][]=$token->text;
                            $getNext=null;
                        }
                        break;
                    default:
                        $getNext=null;
                }
            }
        }
        $rs['filename'] = $filename;
        return $rs;
    }

 

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.