# New Feature: Fully qualified class name resolution as scalar with class keyword

- Thread: https://externals.io/message/59931
- Original archive: https://news-web.php.net/php.internals/59931
- Started by Ralph Schindler on 2012-04-14T19:50:09+00:00
- Messages: 41
- Page 1 of 2: messages 1 to 25 (25 per page, add `?page=N` to the URL)
- Next page: https://externals.io/message/59931.md?page=2
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #59931 — Ralph Schindler — 2012-04-14T19:50:09+00:00

URL: https://externals.io/message/59931#59931

Hi all,

There are many different use cases were in code we expect classes names 
as arguments to functions as fully qualified names.  We do this in ZF a 
lot with our Service Location and DI components, but also with our code 
reflection API, etc.  A more interesting use case I would like to call 
out is with PHPUnit, for example in a test, you might find this:

   $mock = $this->getMock('A\Namespaced\ClassName');

This becomes cumbersome when you are dealing with lots of strings about 
lots of class names.  This is also an area where, currently, namespace 
declaration and use statements offer no real support.

The patch located here:

https://github.com/ralphschindler/php-src/commit/02210d51851a96d723fbedcfc64cde9f9ae2b22a

... implements the ability for a developer to leverage the file's 
namespace declaration and use statements to be able to produce a scalar 
(string) of the class name that can be then used, for example, as an 
argument to a function elsewhere.

This overloads the "class" keyword, and by virtue of the existing usage 
of "class" this feature is completely backwards compatible.  All 
existing tests pass.  For example, the above PHPUnit snipped would become:

   use A\Namespaced\ClassName;
   $mock = $this->getMock(ClassName::class);

Another example with reflection:

   use SomeOther\FullyNamespaced\ClassElsewhere as CE;
   $r = new ReflectionClass(CE::class);

More examples from the test file:

   namespace Foo\Bar {
     class Baz {}
     var_dump(Moo::CLASS); // "Foo\Bar\Moo"
   }

   namespace {
     use Bee\Bop as Moo,
         Foo\Bar\Baz;

     var_dump(Baz::class); // "Foo\Bar\Baz"
     var_dump(Boo::class); // "Boo"
     var_dump(Moo::CLASS); // "Bee\Bop"
     var_dump(\Moo::Class); // "Moo"

     $class = Baz::class; // assign class as scalar to var
     $x = new $class;
     var_dump($x);  object(Foo\Bar\Baz)#1 (0) {}
   }


What do you guys think?

-ralph

---

## #59936 — Marco Pivetta — 2012-04-14T21:14:24+00:00

URL: https://externals.io/message/59931#59936 · In reply to: #59931

I used to implement `public static function getClass() { return
 `get_called_class()`; }`, so I really like this one, makes it also easier for
IDEs when refactoring code :)

I was wondering about `class A { const CLASS = 'hello'; }` but that would
cause an unexpected `T_CLASS`, so I guess there's no conflicts...


Marco Pivetta

http://twitter.com/Ocramius

http://marco-pivetta.com





> Hi all,
>
> There are many different use cases were in code we expect classes names as
> arguments to functions as fully qualified names.  We do this in ZF a lot
> with our Service Location and DI components, but also with our code
> reflection API, etc.  A more interesting use case I would like to call out
> is with PHPUnit, for example in a test, you might find this:
>
>  $mock = $this->getMock('A\Namespaced\**ClassName');
>
> This becomes cumbersome when you are dealing with lots of strings about
> lots of class names.  This is also an area where, currently, namespace
> declaration and use statements offer no real support.
>
> The patch located here:
>
> https://github.com/**ralphschindler/php-src/commit/**
> 02210d51851a96d723fbedcfc64cde**9f9ae2b22a<https://github.com/ralphschindler/php-src/commit/02210d51851a96d723fbedcfc64cde9f9ae2b22a>
>
> ... implements the ability for a developer to leverage the file's
> namespace declaration and use statements to be able to produce a scalar
> (string) of the class name that can be then used, for example, as an
> argument to a function elsewhere.
>
> This overloads the "class" keyword, and by virtue of the existing usage of
> "class" this feature is completely backwards compatible.  All existing
> tests pass.  For example, the above PHPUnit snipped would become:
>
>  use A\Namespaced\ClassName;
>  $mock = $this->getMock(ClassName::**class);
>
> Another example with reflection:
>
>  use SomeOther\FullyNamespaced\**ClassElsewhere as CE;
>  $r = new ReflectionClass(CE::class);
>
> More examples from the test file:
>
>  namespace Foo\Bar {
>    class Baz {}
>    var_dump(Moo::CLASS); // "Foo\Bar\Moo"
>  }
>
>  namespace {
>    use Bee\Bop as Moo,
>        Foo\Bar\Baz;
>
>    var_dump(Baz::class); // "Foo\Bar\Baz"
>    var_dump(Boo::class); // "Boo"
>    var_dump(Moo::CLASS); // "Bee\Bop"
>    var_dump(\Moo::Class); // "Moo"
>
>    $class = Baz::class; // assign class as scalar to var
>    $x = new $class;
>    var_dump($x);  object(Foo\Bar\Baz)#1 (0) {}
>  }
>
>
> What do you guys think?
>
> -ralph

---

## #59938 — Sebastian Krebs — 2012-04-14T22:00:51+00:00

URL: https://externals.io/message/59931#59938 · In reply to: #59936

Am 14.04.2012 23:14, schrieb Marco Pivetta:
> I used to implement `public static function getClass() { return
> `get_called_class()`; }`, so I really like this one, makes it also easier for
> IDEs when refactoring code :)
>
> I was wondering about `class A { const CLASS = 'hello'; }` but that would
> cause an unexpected `T_CLASS`, so I guess there's no conflicts...

I have

     class A { const _CLASS = __CLASS__; }

in many classes. This feature would help a lot.


>
>
> Marco Pivetta
>
> http://twitter.com/Ocramius
>
> http://marco-pivetta.com

---

## #59964 — Ralph Schindler — 2012-04-15T14:13:27+00:00

URL: https://externals.io/message/59931#59964 · In reply to: #59936

> I used to implement `public static function getClass() { return
> `get_called_class()`; }`, so I really like this one, makes it also easier
> for IDEs when refactoring code :)

Oh completely, that is one of the major benefits.  My current workflow 
for refactoring is to refactor with the built-in support, but then also 
having to go find/replace on the full class name, just in case.

-ralph

---

## #59967 — Lars Strojny — 2012-04-15T18:07:03+00:00

URL: https://externals.io/message/59931#59967 · In reply to: #59964

Hi Ralph, hi everybody,

given the clear use case and the simplicity of the patch, a very good idea. 

With regards,
Lars

Am 15.04.2012 um 16:13 schrieb Ralph Schindler:

> 
> > […]
> 
> Oh completely, that is one of the major benefits.  My current workflow for refactoring is to refactor with the built-in support, but then also having to go find/replace on the full class name, just in case.
> 
> -ralph

---

## #59973 — Simon Schick — 2012-04-15T23:13:23+00:00

URL: https://externals.io/message/59931#59973 · In reply to: #59931

2012/4/14 Ralph Schindler <ralph@ralphschindler.com>:
> Hi all,
>
> There are many different use cases were in code we expect classes names as
> arguments to functions as fully qualified names.  We do this in ZF a lot
> with our Service Location and DI components, but also with our code
> reflection API, etc.  A more interesting use case I would like to call out
> is with PHPUnit, for example in a test, you might find this:
>
>  $mock = $this->getMock('A\Namespaced\ClassName');
>
> This becomes cumbersome when you are dealing with lots of strings about lots
> of class names.  This is also an area where, currently, namespace
> declaration and use statements offer no real support.
>
> The patch located here:
>
> https://github.com/ralphschindler/php-src/commit/02210d51851a96d723fbedcfc64cde9f9ae2b22a
>
> ... implements the ability for a developer to leverage the file's namespace
> declaration and use statements to be able to produce a scalar (string) of
> the class name that can be then used, for example, as an argument to a
> function elsewhere.
>
> This overloads the "class" keyword, and by virtue of the existing usage of
> "class" this feature is completely backwards compatible.  All existing tests
> pass.  For example, the above PHPUnit snipped would become:
>
>  use A\Namespaced\ClassName;
>  $mock = $this->getMock(ClassName::class);
>
> Another example with reflection:
>
>  use SomeOther\FullyNamespaced\ClassElsewhere as CE;
>  $r = new ReflectionClass(CE::class);
>
> More examples from the test file:
>
>  namespace Foo\Bar {
>    class Baz {}
>    var_dump(Moo::CLASS); // "Foo\Bar\Moo"
>  }
>
>  namespace {
>    use Bee\Bop as Moo,
>        Foo\Bar\Baz;
>
>    var_dump(Baz::class); // "Foo\Bar\Baz"
>    var_dump(Boo::class); // "Boo"
>    var_dump(Moo::CLASS); // "Bee\Bop"
>    var_dump(\Moo::Class); // "Moo"
>
>    $class = Baz::class; // assign class as scalar to var
>    $x = new $class;
>    var_dump($x);  object(Foo\Bar\Baz)#1 (0) {}
>  }
>
>
> What do you guys think?
>
> -ralph
>
> --
> 
> 
>

Hi, Ralph

I really like this feature in general.

One thing I personally dislike in this implementation is the
difference between CLASS and class ... One with and one without
namespaces ...
If we can unify that, this would be a great help in understanding that
feature in future and getting the difference while reading code.
And please don't forget: Code will be written once, maybe rewritten
some times, but it will be read way more times!

Bye
Simon

---

## #59981 — Ralph Schindler — 2012-04-16T01:31:27+00:00

URL: https://externals.io/message/59931#59981 · In reply to: #59973

> One thing I personally dislike in this implementation is the
> difference between CLASS and class ... One with and one without
> namespaces ...

I am not quite following.  There is no functional difference between 
"class", "CLASS", or "Class".  The parser is case insensitive with 
regards to keywords, which "class" or `T_CLASS` is on of.  The code 
snipped I showed there was from the .phpt test that I had included in 
the Zend/test code base to ensure it worked and did not break existing 
tests.

As per the namespaced and non-namespaced blocks, I was demonstrating how 
::class would resolve names regardless of if it were a FQCN or a short 
class name.  Effectively, you can put ::class behind any "type" name and 
it should work as demonstrated.

-ralph

---

## #59984 — Simon Schick — 2012-04-16T06:18:21+00:00

URL: https://externals.io/message/59931#59984 · In reply to: #59981

2012/4/16 Ralph Schindler <ralph@ralphschindler.com>
>
> I am not quite following.  There is no functional difference between
> "class", "CLASS", or "Class".  The parser is case insensitive with regards
> to keywords, which "class" or `T_CLASS` is on of.  The code snipped I showed
> there was from the .phpt test that I had included in the Zend/test code base
> to ensure it worked and did not break existing tests.
>
> As per the namespaced and non-namespaced blocks, I was demonstrating how
> ::class would resolve names regardless of if it were a FQCN or a short class
> name.  Effectively, you can put ::class behind any "type" name and it should
> work as demonstrated.
>
> -ralph
>

Hi, Ralph

Thanks for clarification.
I was missing the backslash before Moo::Class which lead to that thought.

As the class-definition for Moo is missing, I think it's an empty
class (like Baz) on the root-level defined somewhere else, right?
Otherwise this should do something else than guessing the class-name.

Bye
Simon

---

## #59996 — Ralph Schindler — 2012-04-16T12:55:17+00:00

URL: https://externals.io/message/59931#59996 · In reply to: #59984

Hey Simon,

> As the class-definition for Moo is missing, I think it's an empty
> class (like Baz) on the root-level defined somewhere else, right?
> Otherwise this should do something else than guessing the class-name.

If you look at the patch, this feature is not doing anything PHP doesn't 
already do in other circumstances - demonstrated by the fact that its 
only about 4 lines of code ;)

In PHP, in situations like (instanceof):

   if ($foo instanceof Bar)

or (catch)

   } catch (SomeException $e) {

or (method signature)

   public function setFoo(FooInterface $foo)

... PHP does not invoke the autoloader to determine if the class name 
actually exists as a declaration somewhere, it simply resolves it 
according to some very specific rules (in the case of this patch, 
carried out by zend_resolve_class_name()).

If I am within a namespace and am using a short name without a preceding 
"\", it means the class I am referencing exists in the current 
namespace.  Whether or not that class exists is irrelevant as my short 
name can only mean "a class by this name in the current namespace".  In 
this code:

   namespace Foo\Bar {
     global $foo;
     if ($foo && $foo instance Bar) {
         // ...
     }
   }

... that you, the developer, intend that your reference to Baz actually 
means "Foo\Bar\Baz", it can never mean anything else.

So, in a nutshell, there is no guessing going on ;)
-ralph

---

## #59999 — Simon Schick — 2012-04-16T13:15:58+00:00

URL: https://externals.io/message/59931#59999 · In reply to: #59996

2012/4/16 Ralph Schindler <ralph@ralphschindler.com>
>
> ... PHP does not invoke the autoloader to determine if the class name
> actually exists as a declaration somewhere, it simply resolves it according
> to some very specific rules (in the case of this patch, carried out by
> zend_resolve_class_name()).
>
> If I am within a namespace and am using a short name without a preceding
> "\", it means the class I am referencing exists in the current namespace.
>  Whether or not that class exists is irrelevant as my short name can only
> mean "a class by this name in the current namespace".  In this code:
>
>  namespace Foo\Bar {
>    global $foo;
>    if ($foo && $foo instance Bar) {
>        // ...
>    }
>  }
>
> ... that you, the developer, intend that your reference to Baz actually
> means "Foo\Bar\Baz", it can never mean anything else.
>
> So, in a nutshell, there is no guessing going on ;)
> -ralph

Hi, Ralph

Agree on that. I'd like to have a comment in the test, specially for
this line where you're checking for non-existing classes. It does not
seem to be obvious what should be tested here (at least it was not
obvious for me). This may make it easier to fix stuff if this test
should fail in future.
I don't know if this here is the right test to put the comment in, but
it's at least relying on something global that may change.

Thanks for giving me a deeper knowledge here :)

Bye
Simon

---

## #60054 — Ralph Schindler — 2012-04-17T04:02:03+00:00

URL: https://externals.io/message/59931#60054 · In reply to: #59931

So, at current, is this small enough for just a pull request, or does 
this deserve its own RFC?

-ralph


> Hi all,
>
> There are many different use cases were in code we expect classes names
> as arguments to functions as fully qualified names. We do this in ZF a
> lot with our Service Location and DI components, but also with our code
> reflection API, etc. A more interesting use case I would like to call
> out is with PHPUnit, for example in a test, you might find this:
>
> $mock = $this->getMock('A\Namespaced\ClassName');
>
> This becomes cumbersome when you are dealing with lots of strings about
> lots of class names. This is also an area where, currently, namespace
> declaration and use statements offer no real support.
>
> The patch located here:
>
> https://github.com/ralphschindler/php-src/commit/02210d51851a96d723fbedcfc64cde9f9ae2b22a
>
>
> ... implements the ability for a developer to leverage the file's
> namespace declaration and use statements to be able to produce a scalar
> (string) of the class name that can be then used, for example, as an
> argument to a function elsewhere.
>
> This overloads the "class" keyword, and by virtue of the existing usage
> of "class" this feature is completely backwards compatible. All existing
> tests pass. For example, the above PHPUnit snipped would become:
>
> use A\Namespaced\ClassName;
> $mock = $this->getMock(ClassName::class);
>
> Another example with reflection:
>
> use SomeOther\FullyNamespaced\ClassElsewhere as CE;
> $r = new ReflectionClass(CE::class);
>
> More examples from the test file:
>
> namespace Foo\Bar {
> class Baz {}
> var_dump(Moo::CLASS); // "Foo\Bar\Moo"
> }
>
> namespace {
> use Bee\Bop as Moo,
> Foo\Bar\Baz;
>
> var_dump(Baz::class); // "Foo\Bar\Baz"
> var_dump(Boo::class); // "Boo"
> var_dump(Moo::CLASS); // "Bee\Bop"
> var_dump(\Moo::Class); // "Moo"
>
> $class = Baz::class; // assign class as scalar to var
> $x = new $class;
> var_dump($x); object(Foo\Bar\Baz)#1 (0) {}
> }
>
>
> What do you guys think?
>
> -ralph

---

## #60065 — Nicolas Grekas — 2012-04-17T09:14:59+00:00

URL: https://externals.io/message/59931#60065 · In reply to: #60054

May I suggest using foo::__CLASS__ instead of foo::class ? It's longer, but
closer to what already exists for this semantic (class name as string),
don't you think ?


So, at current, is this small enough for just a pull request, or does this
> deserve its own RFC?
>

Personnaly, I would say that an RFC would be good for historical reference
and documentation.

Nicolas

---

## #60067 — Nikita Popov — 2012-04-17T09:17:05+00:00

URL: https://externals.io/message/59931#60067 · In reply to: #59931

On Sat, Apr 14, 2012 at 9:50 PM, Ralph Schindler
<ralph@ralphschindler.com> wrote:
> Hi all,
>
> There are many different use cases were in code we expect classes names as
> arguments to functions as fully qualified names.  We do this in ZF a lot
> with our Service Location and DI components, but also with our code
> reflection API, etc.  A more interesting use case I would like to call out
> is with PHPUnit, for example in a test, you might find this:
>
>  $mock = $this->getMock('A\Namespaced\ClassName');
>
> This becomes cumbersome when you are dealing with lots of strings about lots
> of class names.  This is also an area where, currently, namespace
> declaration and use statements offer no real support.
>
> The patch located here:
>
> https://github.com/ralphschindler/php-src/commit/02210d51851a96d723fbedcfc64cde9f9ae2b22a
>
> ... implements the ability for a developer to leverage the file's namespace
> declaration and use statements to be able to produce a scalar (string) of
> the class name that can be then used, for example, as an argument to a
> function elsewhere.
>
> This overloads the "class" keyword, and by virtue of the existing usage of
> "class" this feature is completely backwards compatible.  All existing tests
> pass.  For example, the above PHPUnit snipped would become:
>
>  use A\Namespaced\ClassName;
>  $mock = $this->getMock(ClassName::class);
>
> Another example with reflection:
>
>  use SomeOther\FullyNamespaced\ClassElsewhere as CE;
>  $r = new ReflectionClass(CE::class);
>
> More examples from the test file:
>
>  namespace Foo\Bar {
>    class Baz {}
>    var_dump(Moo::CLASS); // "Foo\Bar\Moo"
>  }
>
>  namespace {
>    use Bee\Bop as Moo,
>        Foo\Bar\Baz;
>
>    var_dump(Baz::class); // "Foo\Bar\Baz"
>    var_dump(Boo::class); // "Boo"
>    var_dump(Moo::CLASS); // "Bee\Bop"
>    var_dump(\Moo::Class); // "Moo"
>
>    $class = Baz::class; // assign class as scalar to var
>    $x = new $class;
>    var_dump($x);  object(Foo\Bar\Baz)#1 (0) {}
>  }
>
>
> What do you guys think?
Hey Ralph!

I like the proposal :)

A quick note on the patch: As the class name is compile-time
resolvable it should in my eyes also be available as a
`static_scalar`, so that it can be used in initialization lists:

    public function doFoo($withClass = ABC::class) {
        new $withClass; // or whatever
    }

To be available as both a `static_scalar` and a general `scalar` one
should put the rule in the `common_scalar` section.

What do you think?

Nikita

---

## #60068 — Marco Pivetta — 2012-04-17T09:22:17+00:00

URL: https://externals.io/message/59931#60068 · In reply to: #60067

@Nicolas: wouldn't __CLASS__ introduce a bit of confusion with the existing
constant?

Marco Pivetta

http://twitter.com/Ocramius

http://marco-pivetta.com





> On Sat, Apr 14, 2012 at 9:50 PM, Ralph Schindler
> <ralph@ralphschindler.com> wrote:
> > […]
> as
> > […]
> out
> > […]
> lots
> > […]
> https://github.com/ralphschindler/php-src/commit/02210d51851a96d723fbedcfc64cde9f9ae2b22a
> > […]
> namespace
> > […]
> of
> > […]
> tests
> > […]
> Hey Ralph!
>
> I like the proposal :)
>
> A quick note on the patch: As the class name is compile-time
> resolvable it should in my eyes also be available as a
> `static_scalar`, so that it can be used in initialization lists:
>
>    public function doFoo($withClass = ABC::class) {
>        new $withClass; // or whatever
>    }
>
> To be available as both a `static_scalar` and a general `scalar` one
> should put the rule in the `common_scalar` section.
>
> What do you think?
>
> Nikita

---

## #60070 — Ralph Schindler — 2012-04-17T11:18:56+00:00

URL: https://externals.io/message/59931#60070 · In reply to: #60065

> May I suggest using foo::__CLASS__ instead of foo::class ? It's longer,
> but closer to what already exists for this semantic (class name as
> string), don't you think ?
>

As Marco suggested, I think using __CLASS__ would be confusing to some. 
  __CLASS__ generally means, "where you see this, replace it with the 
class you are in right now".

I generally don't like to draw comparisons too closely to Java and .NET, 
but Java has this, they call it a "class literal", which works the same 
way as described in my new feature:

 
http://stackoverflow.com/questions/2160788/what-is-a-class-literal-in-java

In .net, if a type is a SystemType.Type object (which I think are all 
types), you can simply call a function on it to get the name:

   http://msdn.microsoft.com/en-us/library/9f49ew66.aspx

In addition, I am unsure if there would be any BC issues with your 
proposed syntax.  I do know with mine (::class) does not pose any BC 
issues since the class keyword was limited to declaring a class only. 
At least, the tests prove this, and I can't find any other usages of 
 `T_CLASS` in the parser.

> Personnaly, I would say that an RFC would be good for historical
> reference and documentation.

I think you're right, I'll do this today.

-ralph

---

## #60081 — Ralph Schindler — 2012-04-17T14:54:53+00:00

URL: https://externals.io/message/59931#60081 · In reply to: #60067

Hi Nikita,

> A quick note on the patch: As the class name is compile-time
> resolvable it should in my eyes also be available as a
> `static_scalar`, so that it can be used in initialization lists:
>
>      public function doFoo($withClass = ABC::class) {
>          new $withClass; // or whatever
>      }
>
> To be available as both a `static_scalar` and a general `scalar` one
> should put the rule in the `common_scalar` section.
>
> What do you think?

I've added this to the patch and Zend/tests:

   * 
https://github.com/ralphschindler/php-src/compare/master...feature/class-name-scalar

I've also added an RFC page, any thoughts on improving the RFC?

   * https://wiki.php.net/rfc/class_name_scalars

-ralph

---

## #60083 — Matthew Weier O'Phinney — 2012-04-17T15:20:29+00:00

URL: https://externals.io/message/59931#60083 · In reply to: #60081

> Hi Nikita,
>
> > […]
>
> I've added this to the patch and Zend/tests:
>
>    * 
> https://github.com/ralphschindler/php-src/compare/master...feature/class-name-scalar
>
> I've also added an RFC page, any thoughts on improving the RFC?
>
>    * https://wiki.php.net/rfc/class_name_scalars

In the examples, you mix case:

    Boo::class
    Moo::Class
    \Moo::CLASS

Make sure you note that this is intentional, and that the keyword is
case insensitive -- i.e., changing the case does not alter the use cases
presented.

Also, I'd note why you're selecting "class" as the keyword (basically,
because it _is_ a keyword, and thus will never conflict with any class
constants or method names).

Otherwise, very straight-forward.

-- 
Matthew Weier O'Phinney
Project Lead            | matthew@zend.com
Zend Framework          | http://framework.zend.com/
PGP key: http://framework.zend.com/zf-matthew-pgp-key.asc

---

## #60086 — Stas Malyshev — 2012-04-17T16:58:55+00:00

URL: https://externals.io/message/59931#60086 · In reply to: #60065

Hi!

> May I suggest using foo::__CLASS__ instead of foo::class ? It's longer, but
> closer to what already exists for this semantic (class name as string),
> don't you think ?

I like this. __CLASS__ is already being used as class name, and little
chance of colliding with some code since you're not supposed to be using
__ prefix in your names.

-- 
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227

---

## #60087 — Nikita Popov — 2012-04-17T17:07:46+00:00

URL: https://externals.io/message/59931#60087 · In reply to: #60086

> Hi!
>
> > […]
>
> I like this. __CLASS__ is already being used as class name, and little
> chance of colliding with some code since you're not supposed to be using
> __ prefix in your names.
From the collisions point of view `class` and `__CLASS__` are equally
safe. They both are lexer keywords, so it's not possible to declare
constants with them as name.

Imho ClassName::class reads nicer and also looks similar to the
similar ClassName.class syntax in Java.

Nikita

---

## #60088 — Matthew Weier O'Phinney — 2012-04-17T17:23:10+00:00

URL: https://externals.io/message/59931#60088 · In reply to: #60086

> > […]
>
> I like this. __CLASS__ is already being used as class name, and little
> chance of colliding with some code since you're not supposed to be using
> __ prefix in your names.

"class" won't collide anyways, as it's already a keyword, and you can't use it
in your constant or function names. __CLASS__ has bad connotations for me, as it
resolves to the declaring class normally, not the class invoked.

-- 
Matthew Weier O'Phinney
Project Lead            | matthew@zend.com
Zend Framework          | http://framework.zend.com/
PGP key: http://framework.zend.com/zf-matthew-pgp-key.asc

---

## #60090 — Ivan Enderlin @ Hoa — 2012-04-17T18:16:08+00:00

URL: https://externals.io/message/59931#60090 · In reply to: #60081

Hi Ralph,


> I've also added an RFC page, any thoughts on improving the RFC?
>
>   * https://wiki.php.net/rfc/class_name_scalars
Are you sure that the example section is correct? Because your first 
var_dump is Moo::CLASS but the symbol Moo does not exist yet, only the 
class Foo\Bar\Baz was declared at this point.

Btw, interesting patch and nice implementation. I approved.

Best regards.

-- 
Ivan Enderlin
Developer of Hoa
http://hoa.42/ or http://hoa-project.net/

PhD. student at DISC/Femto-ST (Vesontio) and INRIA (Cassis)
http://lifc.univ-fcomte.fr/ and http://www.inria.fr/

Member of HTML and WebApps Working Group of W3C
http://w3.org/

---

## #60093 — Nicolas Grekas — 2012-04-17T18:45:48+00:00

URL: https://externals.io/message/59931#60093 · In reply to: #60087

> From the collisions point of view `class` and `__CLASS__` are equally
> safe.

> Imho ClassName::class reads nicer and also looks similar to the
> similar ClassName.class syntax in Java.

The current __CLASS__ could then be written self::class. Looks more
"namespace/object oriented", where __CLASS__ feels procedural?

How would static::class behave ? is it handled by the current patch?
Maybe the test case could be extended to reflect this, and also for
self::class?

---

## #60098 — Ralph Schindler — 2012-04-17T19:25:05+00:00

URL: https://externals.io/message/59931#60098 · In reply to: #60090

> var_dump is Moo::CLASS but the symbol Moo does not exist yet, only the
> class Foo\Bar\Baz was declared at this point.

It could exist.  It could be a class name handled by an autoloader 
somewhere else.

This method of class name resolving operates in the spirit of how our 
namespace implementation works.  Namespaces don't actually "import" 
things into the files symbol table, it makes aliases for them, as such 
the namespace implementation alone never triggers an autoload simply b/c 
you were talking about a class somewhere.

The ::class resolver essentially does the same thing, for any given name 
you are talking about, it will resolve that name against the current 
namespace resolution rules.

>
> Btw, interesting patch and nice implementation. I approved.
>
> Best regards.
>

Thanks!
-ralph

---

## #60101 — Ralph Schindler — 2012-04-17T19:31:29+00:00

URL: https://externals.io/message/59931#60101 · In reply to: #60093

> How would static::class behave ? is it handled by the current patch?
> Maybe the test case could be extended to reflect this, and also for
> self::class?

Fantastic question.  I am unsure how to handle this.  Currently, it will 
simply resolve those names against the rules (I am sure this is the 
wrong behavior.)  So,

    namespace Foo\Bar { var_dump(self::class); }

Would now produce:

    string(12) "Foo\Bar\self"

This is the same with 'self', 'static', and 'parent'.  I guess the 
question is, should that produce a compile error, or conditionally work 
depending on if you are inside of a class declaration or not?

I will add this consideration to the RFC.

-ralph

---

## #60103 — Galen Wright-Watson — 2012-04-17T19:36:43+00:00

URL: https://externals.io/message/59931#60103

On Sat, Apr 14, 2012 at 12:50 PM, Ralph Schindler
<ralph@ralphschindler.com>wrote:

> Hi all,
>
> There are many different use cases were in code we expect classes names as
> arguments to functions as fully qualified names.  We do this in ZF a lot
> with our Service Location and DI components, but also with our code
> reflection API, etc.  A more interesting use case I would like to call out
> is with PHPUnit, for example in a test, you might find this:
>
>  $mock = $this->getMock('A\Namespaced\**ClassName');
>
> [...]
>
>
> This overloads the "class" keyword, and by virtue of the existing usage of
> "class" this feature is completely backwards compatible.  All existing
> tests pass.  For example, the above PHPUnit snipped would become:
>
> Would it be easy to have a patch that simply allows use of the class name,
or is the "::class" suffix necessary to resolve some ambiguity? Example
usage:

    $mock = $this->getMock(A\Namespaced\**ClassName);
    # or
    use A\Namespaced\ClassName;
    $mock = $this->getMock(ClassName);

Would changing the definition for class_name_scalar be sufficient?

    class_name_scalar:
        class_name { zend_resolve_class_name(&$1, ZEND_FETCH_CLASS_GLOBAL,
1 TSRMLS_CC); $$ = $1;  }
    ;

To my eye, this is the least surprising syntax.

---

Next page: https://externals.io/message/59931.md?page=2
