5

In the codebase of one of my clients I see a lot of references to a qualified class name as a string;

[
    'foobar' => 'My\Namespace\Class'
]

Instead of using:

[
    'foobar' => My\Namespace\Class::class
]

For a couple of reasons we want to add a PHP CodeSniffer rule to catch these strings and add a warning so the string can be refactored to the ::class constant. The first part (catching the string) is easy, but because we are doing static code analysis we can't do (for example) a class_exists or looking up the results of get_declared_classes().

Next option could be analyzing the string itself ([A-Za-z0-9]), but this is not very reliable because a lot of strings will match but are not meant to be a classname.

Another option is to first 'collect' all the classnames (based on T_CLASS token) and analyze all strings after that based on the collected list of classes. Not very easy to implement IMHO because CodeSniffer works on a per-file basis.

Last option i could think about is also quite dirty; because we always use composer in our projects we could take the autoloading files of composer and try to match against the classmaps and namespaces. Also not very reliable and clean.

Anybody with another suggestion we didn't think about?!

Arjan
  • 416
  • 2
  • 4
  • Looks great to me, how far did you get? I can help you with that, since this is in my issue list. – Tomas Votruba May 12 '17 at 11:33
  • Sorry, no progress so far. I haven't investigated yet but i could imagine that static code analysis tools like PHPStan are already able to do this. – Arjan Jul 13 '17 at 13:59
  • No problem. Feel free to watch or colaborate over this issue: https://github.com/Symplify/Symplify/issues/59 I might help you to build that. PHPStan only analyzes code, doesn't change anything. – Tomas Votruba Jul 13 '17 at 15:27
  • Work in progress here: https://github.com/Symplify/Symplify/pull/262 – Tomas Votruba Jul 14 '17 at 19:36
  • Aaand done: https://github.com/Symplify/Symplify/blob/master/packages/CodingStandard/README.md#class-references-should-be-used-over-string-for-classes-and-interfaces :) You can use with EasyCodingStandard (recommended) or PHP-CS-Fixer – Tomas Votruba Jul 15 '17 at 16:07

1 Answers1

2

Good news! I created this fixer - you can find it here.

The best is to use it with EasyCodingStandard like this:

# ecs.yml
services:
    Symplify\CodingStandard\Fixer\Php\ClassStringToClassConstantFixer: ~

Install:

composer require --dev symplify\easy-coding-standard

Run:

vendor/bin/ecs check src

Fix:

vendor/bin/ecs check src --fix

Enjoy and let me know how it works for you.

If any troubles come up, just create an issue here. I'm happy to improve this tool as much as possible.

Tomas Votruba
  • 23,240
  • 9
  • 79
  • 115