[VOTE] ::class feature to resolve namespaced class names to scalars

php.internals

Ralph Schindler

13 years ago
Hi internals! The ::class resolution proposal had significant discussion in April and I've updated the patch to address issues that came up then. At this point, I've gotten some positive feedback from various places and feel its time to open it up for a vote to internals. RFC: https://wiki.php.net/rfc/class_name_scalars#vote PR: https://github.com/php/php-src/pull/187 Thanks, Ralph

Anatoliy Belsky

13 years ago
Hi Ralph, I've tested the feature/class_name_scalar in your repo on Windows. Both TS and NTS build and pass the test. Regards Anatoliy Am Di, 11.09.2012, 16:39 schrieb Ralph Schindler:

Dmitry Stogov

13 years ago
Hi Ralph, I think the syntax is wired. Instead of classname::class I would prefer something like class(classname). Thanks. Dmitry. On 09/11/2012 06:39 PM, Ralph Schindler wrote:

Marco Pivetta

13 years ago
@Dmitry that looks more like a function call, while (IMO) it is more intuitive to consider it like a static property... Marco Pivetta http://twitter.com/Ocramius http://marco-pivetta.com On 13 September 2012 10:17, Dmitry Stogov <dmitry@zend.com> wrote:

Lars Strojny

13 years ago
Hi Dmitry, Am 13.09.2012 um 10:17 schrieb Dmitry Stogov <dmitry@zend.com>: [...]
> I think the syntax is wired. > Instead of classname::class I would prefer something like class(classname).
Wouldn’t this look too much like a function with all the implications that might cause like users expecting class($variable) to work or even class(otherfunc())? cu, Lars

Simon J Welsh

13 years ago
On 13/09/2012, at 8:28 PM, Lars Strojny <lars@strojny.net> wrote:
> Hi Dmitry, > > Am 13.09.2012 um 10:17 schrieb Dmitry Stogov <dmitry@zend.com>: > [...] >> I think the syntax is wired. >> Instead of classname::class I would prefer something like class(classname). > > Wouldn’t this look too much like a function with all the implications that might cause like users expecting class($variable) to work or even class(otherfunc())? > > cu, > Lars
I would expect $variable::class to work (like late static bindings). However, I do agree that class(ClassName) just looks off and makes it look like you can pass class names to functions. --- Simon Welsh Admin of http://simon.geek.nz/

Lars Strojny

13 years ago
Hi Simon, Am 13.09.2012 um 10:34 schrieb Simon J Welsh <simon@simon.geek.nz>: [...]
> I would expect $variable::class to work (like late static bindings).
[...] Than better try the patch, as it doesn’t work now :) But it is a good point indeed. @Ralph: what do you think? cu, Lars

Julien Pauli

13 years ago
On Thu, Sep 13, 2012 at 10:36 AM, Lars Strojny <lars@strojny.net> wrote:
> Hi Simon, > > Am 13.09.2012 um 10:34 schrieb Simon J Welsh <simon@simon.geek.nz>: > [...] >> I would expect $variable::class to work (like late static bindings). > [...] > > Than better try the patch, as it doesn’t work now :) > > But it is a good point indeed. @Ralph: what do you think? >
Perhaps get_class_fqn(string:ClassName) ? Julien.P

Stas Malyshev

13 years ago
Hi!
> Perhaps get_class_fqn(string:ClassName) ?
Do you propose a function? Because I don't see how it can work as function - namespace resolution is compile-time.
-- Stanislav Malyshev, Software Architect SugarCRM: http://www.sugarcrm.com/ (408)454-6900 ext. 227

Ralph Schindler

13 years ago
>> Perhaps get_class_fqn(string:ClassName) ? > > Do you propose a function? Because I don't see how it can work as > function - namespace resolution is compile-time.
I personally think we should keep resolutions as much to compile time as possible. Your suggestion implies that we now have either a function and a new keyword, or two new keywords: get_class_fqn, and ClassName. I like that ::class is basically 7 chars for a FQ name resolution at compile time, after all, point of this is that we can leverage namespacing in scalars/string when referring to classes as strings. -ralph

Ralph Schindler

13 years ago
On 9/13/12 3:36 AM, Lars Strojny wrote:
> Hi Simon, > > Am 13.09.2012 um 10:34 schrieb Simon J Welsh <simon@simon.geek.nz>: > [...] >> I would expect $variable::class to work (like late static bindings). > [...] > > Than better try the patch, as it doesn’t work now :) > > But it is a good point indeed. @Ralph: what do you think? > > cu, > Lars >
What is $variable is not a string? and/or what if $variable is a string but the contents don't match a namespace resolution rule? What happens? -ralph

Stas Malyshev

13 years ago
Hi!
>>> I would expect $variable::class to work (like late static bindings).
What this would mean? ClassName::class has a clear meaning - ClassName is a name of the class (possibly aliased) and class is the property of this class, namely its full name. However I do not see how $variable::class can do anything meaningful. Since namespace resolution is static compile-time, $variable can not be anything but the full name of the class, so what $variable::class supposed to do? Just be equal to $variable? What's the point of such operation, what may be achieved by it? Reference to "late static binding" is even more confusing - if you mean that $variable is object, then the binding is not "static" - since you have an object - and you have perfectly good get_class($variable) to do that. Is that what you were meaning?
-- Stanislav Malyshev, Software Architect SugarCRM: http://www.sugarcrm.com/ (408)454-6900 ext. 227

Anthony Ferrara

13 years ago
Stas, On Thu, Sep 13, 2012 at 4:58 PM, Stas Malyshev <smalyshev@sugarcrm.com>wrote:
> Hi! > > >>> I would expect $variable::class to work (like late static bindings). > > What this would mean? ClassName::class has a clear meaning - ClassName > is a name of the class (possibly aliased) and class is the property of > this class, namely its full name. However I do not see how > $variable::class can do anything meaningful. Since namespace resolution > is static compile-time, $variable can not be anything but the full name > of the class, so what $variable::class supposed to do? Just be equal to > $variable? What's the point of such operation, what may be achieved by it? >
Right now, you can access static properties and methods from a string/object by doing $var::$foo... I would assume that this works the same way. That way, you can take in a string class name, or an object, and get the class in one shot `$obj::class` instead of `get_class($obj)`... Just for consistency... Anthony

Stas Malyshev

13 years ago
Hi!
> Right now, you can access static properties and methods from a > string/object by doing $var::$foo... I would assume that this works the > same way. That way, you can take in a string class name, or an object, > and get the class in one shot `$obj::class` instead of > `get_class($obj)`... Just for consistency...
I guess it can be made work if we do it right - e.g. via ZEND_FETCH_CONSTANT. I'm not a big fan of inventing new syntax for things that already exist and can be done with the same effort - but technically it should be possible.
-- Stanislav Malyshev, Software Architect SugarCRM: http://www.sugarcrm.com/ (408)454-6900 ext. 227

Dmitry Stogov

13 years ago
We already have isset(), empty(), unset() that are a special purpose functions handled by compiler. Thanks. Dmitry. On 09/13/2012 12:28 PM, Lars Strojny wrote:

Julien Pauli

13 years ago
On Thu, Sep 13, 2012 at 11:12 AM, Dmitry Stogov <dmitry@zend.com> wrote:
> We already have isset(), empty(), unset() that are a special purpose > functions handled by compiler. > > Thanks. Dmitry.
Yes, if we communicate the right way about our feature not beeing a true PHP function and taking isset(), empty() et all as examples, people would understand I think :) Julien.P

Lars Strojny

13 years ago
Hi Dmitry, Am 13.09.2012 um 11:12 schrieb Dmitry Stogov <dmitry@zend.com>:
> We already have isset(), empty(), unset() that are a special purpose functions handled by compiler.
[...] That’s exactly my point: these special purpose functions present themself to the user as usual functions and set a certain expectation. That’s why we now allow empty(func()). If something presents itself as a syntax element, there is no such expectation and the only valid software metric, WTFs per minute decreases slightly. cu, Lars

Ralph Schindler

13 years ago
> I think the syntax is wired. > Instead of classname::class I would prefer something like class(classname). >
I am not a big fan of the syntax class(ShortClass\Name) as to me it looks like a function call. Personally, I like drawing parallels from the same languages that I think helped shaped PHP's object-model. In this case, the Java has a similar enough feature where Type.class returns a class object (in our case we just need to return a string of the FQ class name). Your suggestion is similar to that of, I think, C# where typeof(SomeClassName) would return a reflection-like/type object where you could get the FullName(): http://msdn.microsoft.com/en-us/library/58918ffs%28v=vs.71%29.aspx I could go either way, at this point (after the April discussion on the matter), I had not really given much thought to class() lang. construct. Personally, ::class feels a bit better to me in that the context feels more "compile-time", like __CLASS__, and the NS resolutions, than does class() that you suggest. From a wider perspective, I've seen these variations in the wild: class Foo { const CLASSNAME = __CLASS__; // or const _class = __CLASS__; } Which allows for the usage: Foo::CLASSNAME; for example. FWIW, both reusing the class() keyword making it BC, which is something I like. -ralph

Dmitry Stogov

13 years ago
Hi Ralph, You persuade me. :) The SOMETHING::class syntax looked wired to me because I didn't understand it. However, the SOMETHING::class syntax might be considered as a reference to a predefined class constant and in this case it looks quite consistent. I suggest to reflect it in RFC and documentation (if we agree to include it in release) to avoid future misunderstanding. Also I would expect SOMETHING::class to work in all cases where class constants work. e.g. self::class, parent::class, static::class, $obj::class. To do it for parent, static and $obj you'll probably need a new opcode - ZEND_FETCH_CLASSNAME that must be very similar to ZEND_FETCH_CLASS. May be it's possible to do the same using ZEND_FETCH_CONSTANT, but I don't think it makes sense to complicate the existing opcode. SOMETHING::class must be consistent with traits. In case all the above works, I say +1 and even may help with implementation. Finally, may be SOMETHING::__CLASS__ is a bit more clear than SOMETHING::class. Thanks. Dmitry. On 09/14/2012 12:51 AM, Ralph Schindler wrote:

Patrick ALLAERT

13 years ago
2012/9/14 Dmitry Stogov <dmitry@zend.com>:
> Finally, may be SOMETHING::__CLASS__ is a bit more clear than > SOMETHING::class.
That is the reason why I voted "no", but more because of the token used than the feature. I previously stated that I preferred __CLASS__ as well to be more in line with what we currently have, I haven't changed my mind since the arguments provided didn't convinced me at all. Cheers, Patrick

Ryan McCue

13 years ago
Patrick ALLAERT wrote:
> 2012/9/14 Dmitry Stogov <dmitry@zend.com>: >> Finally, may be SOMETHING::__CLASS__ is a bit more clear than >> SOMETHING::class. > > That is the reason why I voted "no", but more because of the token > used than the feature. > I previously stated that I preferred __CLASS__ as well to be more in > line with what we currently have, I haven't changed my mind since the > arguments provided didn't convinced me at all.
I somewhat agree; using __CLASS__ would make it more obvious that it's compile-time rather than runtime, IMO.
-- Ryan McCue <http://ryanmccue.info/>

Ralph Schindler

13 years ago
> I somewhat agree; using __CLASS__ would make it more obvious that it's > compile-time rather than runtime, IMO. >
It's not always going to be compile-time. For self::class and Foo::class, it will be compile time every time. For static:class and parent::class, that has to be done at runtime as the class_entry is not completely hooked up (active_class_entry does not have parent* pointer, even if the class is extended). The 99% use case is: Foo::class, where a short name can be resolved against the current namespace and current import/use statements. The rest of the use cases, as we've seen, are going to be filled out for consistency. That means that: class Foo { const SOMECLASSNAME = static::class; // or parent::class } Will/should result in an E_FATAL (this use case doesn't really make a ton of sense anyway, but people are likely to do it). (I *think* the same applies for method signatures too, btw.)
>> That is the reason why I voted "no", but more because of the token >> used than the feature. >> I previously stated that I preferred __CLASS__ as well to be more in >> line with what we currently have, I haven't changed my mind since the >> arguments provided didn't convinced me at all.
I guess I can't convince preference :) I prefer ::class over ::__class__, and in that only marginally, because its shorter. After all, the whole point of this feature is because people are using namespaces (for the shortness of class names) and they need to use long class names as string, but want all the benefits of the namespacing/aliasing in the current scope. -ralph

Patrick Schaaf

13 years ago
Hi, if it looks, smells, and works like a class constant, can't just BE a class constant, automatically created, but just as-if "const class = 'xxx';" had been present in the definition in the first place? Not that I know php code internals in any thorough way, but I imagine that that approach would obviate the need for any new opcodes. best regards Patrick

Dmitry Stogov

13 years ago
In general it'll work, but it'll waste memory. Thanks. Dmitry. On 09/14/2012 12:33 PM, Patrick Schaaf wrote:

Jan Dolecek

13 years ago
I'm not able to try it myself at the moment and it's not described in the RFC, so I'd like to ask: Will it invoke autoloading, if the class does not exist (yet)? I think this should be considered. If so, it's not good as it kills lazy-loading. If not so, it we may get errors later than expected. I think these problems deserve discussion. (I'd prefer to keep lazy-loading, since existence of class gets validated by IDE) Regards, JD On Tue, Sep 11, 2012 at 4:39 PM, Ralph Schindler <ralph@ralphschindler.com>wrote:

Marco Pivetta

13 years ago
Hi JD, On 13 September 2012 15:57, Jan Dolecek <juzna.cz@gmail.com> wrote:
> I'm not able to try it myself at the moment and it's not described in the > RFC, so I'd like to ask: > > Will it invoke autoloading, if the class does not exist (yet)? > > I think this should be considered. If so, it's not good as it kills > lazy-loading. If not so, it we may get errors later than expected. > I think these problems deserve discussion. (I'd prefer to keep > lazy-loading, since existence of class gets validated by IDE) > > Regards, > JD > > > On Tue, Sep 11, 2012 at 4:39 PM, Ralph Schindler > <ralph@ralphschindler.com>wrote: > > > Hi internals! > > > > The ::class resolution proposal had significant discussion in April and > > I've updated the patch to address issues that came up then. At this > point, > > I've gotten some positive feedback from various places and feel its time > to > > open it up for a vote to internals. > > > > RFC: https://wiki.php.net/rfc/**class_name_scalars#vote< > https://wiki.php.net/rfc/class_name_scalars#vote> > > > > PR: https://github.com/php/php-**src/pull/187< > https://github.com/php/php-src/pull/187> > > > > Thanks, > > Ralph > > > > -- > > PHP Internals - PHP Runtime Development Mailing List > > To unsubscribe, visit: http://www.php.net/unsub.php > > > > >
I don't think autoloading is needed here, since the FQCN can be resolved without it (exactly like with type hinting). Marco Pivetta http://twitter.com/Ocramius http://marco-pivetta.com

Lars Strojny

13 years ago
Hi, Am 13.09.2012 um 16:02 schrieb Marco Pivetta <ocramius@gmail.com>:
> I don't think autoloading is needed here, since the FQCN can be resolved > without it (exactly like with type hinting).
Has nothing to do with autoloading. It only checks if there is a use statement. Auto-loading is triggered during call time, not during compile time. cu, Lars

Ralph Schindler

13 years ago
Hi all, I know there are few edge cases that need to be resolved. What I am looking for in the RFC/vote is to determine if ::class (as it works in the PoC patch) has enough acceptance for inclusion in master. If there is not enough interest in this by the powers that be, or the feature as currently proposed is not popular enough. I'd rather not spend many more hours on it. I'd like to get as much direction as possible from people so we can close out the edge cases and I can have some clear goals to work towards to get the implementation (including all edge cases) ready to be merged. That said, here is a summary: * The VOTE is for whether entertaining ::class would make it into master, it has little to do with edge cases. * Here are the edge cases / implementation details that need a decision: - $variable::class (should it even be supported?) - self, static, parent::class not in a class definition - self, static, parent::class in a method signature - self, static, parent::class in a method body - if static & parent are runtime, do we return false on misses? -ralph On 9/11/12 9:39 AM, Ralph Schindler wrote:

Stas Malyshev

13 years ago
Hi!
> * Here are the edge cases / implementation details that need a decision: > > - $variable::class (should it even be supported?)
I don't see it doing anything useful.
> - self, static, parent::class not in a class definition > - self, static, parent::class in a method signature > - self, static, parent::class in a method body
In constant context, self:: may work, but static:: can't work for obvious reasons. parent:: can be made work too I think - though the class may not be known at the run time, its name should be. As for runtime context, static:: can be made work too but I wonder why bother if we have perfectly good get_called_class()...
-- Stanislav Malyshev, Software Architect SugarCRM: http://www.sugarcrm.com/ (408)454-6900 ext. 227

Ralph Schindler

13 years ago
Hey Stas,
>> * Here are the edge cases / implementation details that need a decision: >> >> - $variable::class (should it even be supported?)
> I don't see it doing anything useful.
I generally agree. In the current patch, this does not work and would need another run in the parser.
>> - self, static, parent::class not in a class definition >> - self, static, parent::class in a method signature >> - self, static, parent::class in a method body > > In constant context, self:: may work, but static:: can't work for > obvious reasons. parent:: can be made work too I think - though the > class may not be known at the run time, its name should be.
self works in compile-time in the current patch. static::class and parent::class work in the current patch in run-time, but they are effectively doing a get_called_class() and get_parent_class() respectively. This part of my implementation can be cleaned up to remain in runtime but utilize zend_do_fetch_class() instead.
> As for runtime context, static:: can be made work too but I wonder why > bother if we have perfectly good get_called_class()...
For some people, I think it's a matter of completeness, regardless if it is a compile-time name resolution or a runtime class lookup. Personally, (I am not the majority here I feel), I'd rather see zend_error(E_FATAL) for any runtime lookups, forcing people to use the runtime-lookup-isms (like get_called_class(), or get_parent_class()). For the latter, returning "false" there seems more likely, where as parent::class returning false when not in an inherited class seems odd to me. -ralph

Stas Malyshev

13 years ago
Hi!
> In the current patch, this does not work and would need another run in > the parser.
Couldn't we just stuff it in ZEND_FETCH_CONSTANT? I'm not arguing for it, I'm just saying *if* we wanted it...
-- Stanislav Malyshev, Software Architect SugarCRM: http://www.sugarcrm.com/ (408)454-6900 ext. 227

Etienne Kneuss

13 years ago
Hi, On Fri, Sep 14, 2012 at 12:24 AM, Stas Malyshev <smalyshev@sugarcrm.com> wrote:
> Hi! > >> In the current patch, this does not work and would need another run in >> the parser. > > Couldn't we just stuff it in ZEND_FETCH_CONSTANT? I'm not arguing for > it, I'm just saying *if* we wanted it...
Even though it's not really useful, we should have it for the sake of consistency. As long as it doesn't cause major technical complications to implement, I don't see why we shouldn't have that available. Best,
-- Etienne Kneuss

Pierre Joye

13 years ago
hi Ralph, Given the current discussions and the few votes, I would recommend to move this RFC back to the discussion phase, clear the open questions (syntax or other) again before moving back to vote. Cheers, On Tue, Sep 11, 2012 at 4:39 PM, Ralph Schindler <ralph@ralphschindler.com> wrote:
> Hi internals! > > The ::class resolution proposal had significant discussion in April and I've > updated the patch to address issues that came up then. At this point, I've > gotten some positive feedback from various places and feel its time to open > it up for a vote to internals. > > RFC: https://wiki.php.net/rfc/class_name_scalars#vote > > PR: https://github.com/php/php-src/pull/187 > > Thanks, > Ralph > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: http://www.php.net/unsub.php >
-- Pierre @pierrejoye | http://blog.thepimp.net | http://www.libgd.org

Ralph Schindler

13 years ago
That is what I will do. What has become clear to me is that this feature does indeed have a lot of promise, and me working on it further to address new concerns (and directions) would not be wasted time. I will close the vote, clean up the patch to address new concerns, then bring this back to a vote again at a later date. -ralph On 9/14/12 1:11 AM, Pierre Joye wrote: