Req #71352 [Com]: instanceof magic method
Edit report at https://bugs.php.net/bug.php?id=71352&edit=1
ID: 71352
Comment by: willfitch@php.net
Reported by: tom at r dot je
Summary: instanceof magic method
Status: Open
Type: Feature/Change Request
Package: *General Issues
Operating System: *
PHP Version: 7.0.2
Block user comment: N
Private report: N
New Comment:
This is a feature request - not an issue. For major feature requests, an RFC should be created
explicitly defining the feature itself. Note - you'll need a sponsor to author this change in
the event you aren't able to provide a patch.
Before doing that, I think the first step would be to add the wiki page, then get a feeler from
internals on the idea. I sense there will be quite a bit of pushback.
Previous Comments:
------------------------------------------------------------------------
[2016-01-12 16:48:01] tom at r dot je
Description:
------------
Currently there is no way to make a wrapper without using eval()
we see this in PHPUnit: https://github.com/sebastianbergmann/phpunit-mock-objects/blob/master/src/Framework/MockObject/Generator.php
To generate a mock object PHPUnit has to generate the string
```
class NewClass extends OldClass {
public function oldMethod() {
}
public function oldMethod() {
}
}
```
and then use eval() to dynamically create this class. This takes a lot of effort and obviously is
not a great solution.
It would be better, for this and other uses where a wrapper is useful (such as AOP) if this was
possible:
```
class Wrapper {
private $object;
public function __construct($object) {
$this->object = $object;
}
public function __call($func, $args) {
$this->object->$func(...$args);
}
public function __set($name, $value) {
$this->object->$name = $value;
}
public function __get($name) {
return $this->object->$name;
}
}
```
This will act as a wrapper for $object using new Wrapper(new MyObj) however this
breaks, and the reason PHPUnit has to use eval is because the wrapper isn't
actually an instance of the type being wrapped so this code fails:
```
function processObject(MyObj $obj) {
}
```
This works:
processObject(new MyObj);
but this does not:
processObject(new Wrapper(new MyObj));
It would be better if there was a way to make an object pretend to be another type. My suggestion is
this:
```
```
class Wrapper {
private $object;
public function __construct($object) {
$this->object = $object;
}
public function __call($func, $args) {
$this->object->$func(...$args);
}
public function __set($name, $value) {
$this->object->$name = $value;
}
public function __get($name) {
return $this->object->$name;
}
public function __instanceof($name) {
return $name == get_class($this->object;
}
}
```
The __instanceof method would be called when an object is passed into a method with a type hint and
the object is the wrong type. Rather than just erroring, the instanceof method is called with the
type-hinted class name as an argument and the class can then pretend to be another class.
This may need to be an interface so that __call works.
There are several uses for this, an obvious one is PHPUnit's mock objects and another one would
be being able to better implement Aspect Oriented Programming, something which needs the same
workaround as PHPUnit currently.
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=71352&edit=1
Thread (3 messages)