There are various cases where the fully-qualified name of a class or interface may be returned from or passed as an argument to a function. While PHP has a type declaration for function names, callable
, it does not yet have such a type declaration for class or interface names.
This RFC proposes the introduction of a new type declaration for use on parameters and return values, the class
type declaration. It would accept the fully-qualified name of a class or interface.
It would validate its value using the following steps:
As a parameter type, it would permit default values of NULL
(to make the parameter null) and constant strings (including ::class
syntax).
A simple example of usage:
<?php function accepts_class(class $class = stdClass::class) { var_dump($class); } accepts_class(); // string(8) "stdClass" accepts_class(stdClass::class); // string(8) "stdClass" accepts_class("stdClass"); // string(8) "stdClass" accepts_class(ArrayAccess::class); // string(11) "ArrayAccess" accepts_class("nonexistant"); // Fatal error: Uncaught TypeError: Argument 1 passed to accepts_class() must be of the type class, string given…
This RFC currently proposes to call this type declaration class
. Hack, PHP's sister language, already includes a similar type for class names, but calls it classname
instead.
The name class
has a few advantages:
::class
syntax for obtaining the name of a classnew $class
and $class::$property
)
However, there are also arguments in favour of classname
:
This RFC currently proposes that there would be a single new type, class
, which would accept the names of both classes and interfaces. There might, however, be a case to be made for accepting only classes, and/or having a separate type for interface names (interface
, say), or even a third type for accepting both classes and interfaces.
Having class
accept both classes and interfaces has a few arguments in its favour:
zend_parse_parameters()
type “C”
, used by some functions in the PHP standard library, which likewise accepts both class and interface names::class
works for both class and interface names
That being said, there are also arguments in favour of class
accepting only classes:
class_exists()
treats interfaces as non-existentclass
”
There is an advantage to a separate interface
type, insofar as having PHP distinguish classes and interfaces in type declarations makes for clearer function signatures and avoids potential manual testing of whether a value is class or an interface.
If there was a separate interface
type, there would be an argument for having the class
type also accept interfaces, since classes are a superset of interfaces, and classes can subclass (“implement”) interfaces, but not the other way around.
If none of these approaches are palatable, there could be a third type accepting both classes and interfaces, perhaps named classlike
. However, this might be reaching the point of diminishing returns.
All the possibilities in this section can and have been implemented provisionally, and the branch on GitHub contains all of them in its commit history.
The class
keyword is already a reserved word, so there is no backwards-compatibility break created by its reuse here.
This is proposed for the next PHP 7.x, currently PHP 7.2.
Testing revealed that Opcache's type inference needed updating to accommodate the new type declaration. This has been done and it seems to work, but it is possible other areas of incompatibility exist and have been missed.
Classes, interfaces and traits continue not to be objects in themselves, and are only referenced by name.
A supertype could be introduced, which could name not only classes and interfaces, but also primitive PHP types (int
, string
etc.) and possibly pseudo-types.
The potential future ability to use variables containing type names in place of literal type names in source code could facilitate generic programming.
This would require a 2/3 majority, as a language change. The vote would be a Yes/No vote as to whether to accept the RFC for the appropriate future version of PHP.
There is a patch here which contains tests: https://github.com/php/php-src/compare/master...hikari-no-yume:class_type_declaration
The commits for versions with multiple new types do not handle inheritance concerns.
There is not yet a pull request.
There is not yet a patch for the language specification.
After the project is implemented, this section should contain
: Links to external references, discussions or RFCs