php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Request #71037 Interfaces for Reflection API
Submitted: 2015-12-05 08:58 UTC Modified: 2017-01-29 07:32 UTC
Votes:1
Avg. Score:1.0 ± 0.0
Reproduced:0 of 0 (0.0%)
From: andreas at dqxtech dot net Assigned:
Status: Suspended Package: Reflection related
PHP Version: 7.0.0 OS: Linux
Private report: No CVE-ID: None
Have you experienced this issue?
Rate the importance of this bug to you:

 [2015-12-05 08:58 UTC] andreas at dqxtech dot net
Description:
------------
The native Reflection API should provide interfaces like \IReflectionClass, which can then be used for type hinting.

This way, libraries such as https://github.com/Roave/BetterReflection or https://github.com/Andrewsville/PHP-Token-Reflection don't need to extend or wrap core reflection classes, but can instead implement the interface.

One problem with this is that some libraries might only want to implement some of the methods of e.g. \ReflectionFunction, but not all of them. To allow this, there would need to be partial interfaces - which could be a longer discussion.

I think for a start it would be sufficient to just have one interface for each of the already existing classes of the Reflection API. More interfaces could be added in the future.

Test script:
---------------
class C {..}

function foo(\IReflectionClass $reflectionClass) {..}

foo(new \ReflectionClass('C'));

class MyReflectionClass implements \IReflectionClass {
  ..
}

foo(new MyReflectionClass('C'));


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2015-12-05 09:00 UTC] andreas at dqxtech dot net
Of course I don't really care if it is IReflectionFunction or ReflectionFunctionInterface. But the latter pattern would give us ReflectionInterface vs ReflectionInterfaceInterface, which seems bad.
 [2015-12-05 21:41 UTC] danack@php.net
You almost certainly don't want this.

Having interface in PHP core is fine for small well defined constructs. However it becomes very very painful when the interfaces are either only vaguely defined or very large, as each change to the definition of the interface would be a backwards compatibility breaking change. The Reflection classes are both large and ill-defined.

Having the internal classes implement an interface would either be very annoying for users of this interface, or for PHP core devs who would now have to wait until major/minor releases to change the definitions of the interfaces.

Alternatively, you can achieve what you want to achieve by simply defining the appropriate interface in UserLand, and then making a proxy implementation to the Reflection api. e.g.


interface ReflectionClassInterface {
    public function getConstant(string $name);
    public function getConstants() : array;
    public function getConstructor() : \ReflectionMethod;
    //all the other methods.
}

class ReflectionClassCore implments ReflectionClassInterface {

    private $reflectionClass;

	public function __construct(\ReflectionClass $reflectionClass) {
		$this->reflectionClass = $reflectionClass;
	}
	
	public function getConstant(string $name) {
        return $this->reflectionClass->getConstant($name);
    }

    public function getConstants() : array {
        return $this->reflectionClass->getConstants();
    }

    public function getConstructor() : \ReflectionMethod {
        return $this->reflectionClass->getConstructor();
    }
    //...and so on.
}

This would take you less than an hour to do, which is significantly less time that just the discussion on the internals list would take. That interface wouldn't break when the internal classes have methods added or altered, and probably has other benefits as well e.g. being able to improve the reflection api without waiting for PHP core to change.

TL:DR interfaces are great, but not right here....
 [2015-12-06 07:47 UTC] andreas at dqxtech dot net
Ok.. only this won't work when calling existing 3rd party functions / methods that expect a \ReflectionSomething as a parameter.

An alternative would be to interface only a stable subset of the reflection functionality. The part that makes sense to implement differently.
 [2015-12-06 07:53 UTC] andreas at dqxtech dot net
Btw, one reason why such libraries exist in the first place:

https://bugs.php.net/bug.php?id=70761
Request #70761	Fatal error if missing parent class - create "stub" class instead

Typical scenario:
A library contains a class that is autoloadable, but its parent class or implemented interface is not - because it belongs to an optional dependency.

Then we have some kind of discovery mechanism, which wants to look at the class for whichever purpose.
Doing this with native reflection will trigger autoload and include, which then causes fatal due to the missing parent class or interface.

The idea there was to fatal when the class is actually used, not when the file is included.
 [2016-03-26 21:36 UTC] krakjoe@php.net
-Status: Open +Status: Closed -Assigned To: +Assigned To: krakjoe
 [2016-03-26 21:36 UTC] krakjoe@php.net
For this kind of change, an RFC is required.

Please see: https://wiki.php.net/rfc/howto
 [2016-03-26 21:41 UTC] krakjoe@php.net
-Status: Closed +Status: Suspended
 [2017-01-29 07:32 UTC] krakjoe@php.net
-Assigned To: krakjoe +Assigned To:
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Tue Apr 23 06:01:30 2024 UTC