NotionCommotion Posted August 4, 2021 Share Posted August 4, 2021 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; } Quote Link to comment https://forums.phpfreaks.com/topic/313493-get-class-name-by-filename/ Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.