I miss a feature in PHP, which would allow me to reference
classes easily. For example in Java, if you have a class
cz.juzna.abc.Acticle and you want to give it to a variable/method,
you can reference it by cz.juzna.abc.Acticle.class.
In PHP, this can be done only by a string with class' name
("cz\juzna\abc\Article"), which is however a string and
not a reference. For example IDE won't see it as usage
of a class (it won't autocomplete, won't find it in usages, …). This makes it
very easy to make errors or typos in such definitions, or to break the system
while refactoring.
It may be difficult to extend PHP itself, but we can add this feature to
Nette\Object:
abstract class Object {
...
static function getClassName() {
return get_called_class();
}
}
With this, I can use cz\juzna\abc\Article::getClassName(),
which is a piece of code; it's „alive“ and will fail if mistaken.
Advantages
- No need for full namespaces, if you have
use-statement for the class - Auto-completion in IDE; you start typing
Roland it offersRoleEntityfor you - Go to definition or Ctrl+click works in IDE
- Warnings in IDE if the class is misspelled
- Found in „find usages“
- Can be refactored
- etc.
Summary: it's a live class now, instead of a dead string.
Patching PHP
This feature would make more sense if available in vanilla PHP, for
every class and not only those extending Nette\Object.
I experimented with PHP's source code and created a small patch which adds
magic constant MyClass::className to every class. Available for PHP
5.3.8 here.
It's not stable for production, rather as a proof of concept for developers to
test, whether it's worth to have it.
I'm also experimenting with a magic constant MyClass::class
which would contain MyClass' reflection object (similar to what we have in
Java), but there are still some questions about this to be answered. Mainly,
that such a constant must be in language core, while PHP's reflection is an
extension (and core depending on an extension is not a very good idea). Any
suggestions are welcome!
Experience
I added this to my Nette fork and have been using this for a month now, and it's so useful to have it in every class, with IDE's hints as well. Especially if you work with ORM like Doctrine.
If you're using ORM and if you type class names as strings often, try it for a while and you'll see ;)
Note: I also wrote a post on Nette forum regarding this issue.


I didn't like the ::getClassName() method, but I realy like idea of making it a constant.
$class = MyClass::class;
Realy nice!
@HosipLan: I don't have this idea finished yet. In my opinion,
MyClass::classshould give again something „live“ (thus not a string with class name), but I'm not sure what. Should it be ReflectionClass? And I guess it should be the same instance everytime you access this constant – this may get more complicated… But will tryDoes ReflectionClass have
__toString() { return $this->getName(); }
method? If does, it could be returned from the constant.
Magic constant should work without autoloading.
You mean that
MyClass::classNameshould not invoke autoloading ofMyClass? Why do you think so? It make sense as it would postpone loading of such class to point where it's really needed.But I think it may be appropriate for the class to be loaded, so that you'd get exception thrown in the place where you used invalid reference, instead of the place where the class gets instantiated for the first time (or used in another way).
Of course, we can discuss this. And a good point, I haven't thought about it.