Hi,
I have noted that detecting a class name using "::class" it will return
the called case instead of the original case.
see http://3v4l.org/97K36
That's annoying as I like to check the right class case on autoload to
detect mistakes.
Sure, class names in PHP are case-insensitive but filesystems aren't and
most autoloader using the FS to find the right file. To catch such kind
of mistakes I would like to implement a fast check in my autoloader to
get noted on development instead on production. It's currently only
possible with ReflectionClass but this will be much slower as with ::class.
Are there any reasons to get the called case of the class instead or the
original one?
Marc
Hi,
I have noted that detecting a class name using "::class" it will return the
called case instead of the original case.
see http://3v4l.org/97K36That's annoying as I like to check the right class case on autoload to
detect mistakes.Sure, class names in PHP are case-insensitive but filesystems aren't and
most autoloader using the FS to find the right file. To catch such kind of
mistakes I would like to implement a fast check in my autoloader to get
noted on development instead on production. It's currently only possible
with ReflectionClass but this will be much slower as with ::class.Are there any reasons to get the called case of the class instead or the
original one?
The way this is implemented means that the class doesn't even have to
exist. It's purely compile-time expansion. The identifier doesn't even
have to be a class at all[1]:
<?php
namespace foo;
function bar(){}
var_dump(bar::class); // string(7) "foo\bar"
?>
This was not explained in the RFC at all, and had I known this I would
have voted against it personally.
[1] It doesn't work when you import a function name with use function
because it's only intended to work with classes and
class-like entities.
<?php
namespace foo;
function bar(){}
var_dump(bar::class); // string(7) "foo\bar"
?>
This was not explained in the RFC at all, and had I known this I would
have voted against it personally.
How would you suggest it be different, if not a "compile-time name
expansion for classes"?
On a personal note, I've gotten plenty of benefit from the feature which
(again, for me) totally eclipses the only very small regret that ::class
looks like a class constant lookup. That syntactical point could have
gone either way, but I feel like the accepted syntax is still a good choice.
Your example above might attempt to cause some mis-direction to the
reader of the code a bit because you have clearly defined a symbol
(function) called "bar", yet you're still name-expanding a class called
"bar", which technically could be living in the same namespace in a
different file covered by an autoloader. bar::class still does actually
mean foo\bar the class, not the function.
<?php
namespace foo;
function bar() {}
class bar {}
var_dump(bar::class); // string(7) "foo\bar"
$b = new bar;
var_dump(get_class($b));
Thanks for your input,
-ralph
On Tue, May 26, 2015 at 9:52 AM, Ralph Schindler
ralph@ralphschindler.com wrote:
<?php
namespace foo;
function bar(){}
var_dump(bar::class); // string(7) "foo\bar"
?>
This was not explained in the RFC at all, and had I known this I would
have voted against it personally.How would you suggest it be different, if not a "compile-time name expansion
for classes"?
Emit an opcode for it. This would also allow for dynamic lookups
($foo::class), trigger autoloading, and restrict it to classes and
interfaces (and traits?). All of these things are beneficial in my
opinion, at least.
On a personal note, I've gotten plenty of benefit from the feature which
(again, for me) totally eclipses the only very small regret that ::class
looks like a class constant lookup. That syntactical point could have gone
either way, but I feel like the accepted syntax is still a good choice.
I have found this feature to be useful as well. The essence of this
feature is good, but I feel like the implementation is unfortunate.
Your example above might attempt to cause some mis-direction to the reader
of the code a bit because you have clearly defined a symbol (function)
called "bar", yet you're still name-expanding a class called "bar", which
technically could be living in the same namespace in a different file
covered by an autoloader. bar::class still does actually mean foo\bar the
class, not the function.<?php
namespace foo;
function bar() {}
class bar {}
var_dump(bar::class); // string(7) "foo\bar"
$b = new bar;
var_dump(get_class($b));
bar::class does not necessarily mean foo\bar
the class; it just does
a string expansion. In my opinion it should have been restricted to
only classes and interfaces (or other things like them) since that's
what the RFC and syntax intends, but not what it actually does.
Hi,
I have noted that detecting a class name using "::class" it will return
the called case instead of the original case.
see http://3v4l.org/97K36That's annoying as I like to check the right class case on autoload to
detect mistakes.Sure, class names in PHP are case-insensitive but filesystems aren't and
most autoloader using the FS to find the right file. To catch such kind
of mistakes I would like to implement a fast check in my autoloader to
get noted on development instead on production. It's currently only
possible with ReflectionClass but this will be much slower as with
::class.Are there any reasons to get the called case of the class instead or the
original one?Marc
This happens because ::class construction is evaluated at compiled time,
without triggering autoloader. That means compiler doesn't know what will
be the actual name of a class, it just gives you what you asked for.
It's currently only possible with ReflectionClass but this will be much
slower as with ::class.
It's only possible with ReflectionClass if this class was already loaded.
There's one way for your autoloader to know if the class name has
characters in a wrong case - build a class map and do a check based on
this map.
Hi!
That's annoying as I like to check the right class case on autoload to
detect mistakes.
I'm not sure I understand this right, but if I do this sounds
contradictory. I.e., if you are trying to autoload the class, you
haven't loaded it yet. If you didn't, how would you know which case is
"right"?
Are there any reasons to get the called case of the class instead or the
original one?
The reason is that the former is constant fast operation while the
latter requires actually loading the class. Which is much more expensive.
--
Stas Malyshev
smalyshev@gmail.com