Req #71352 [NEW]: instanceof magic method
| From: | tom at r dot je | Date: | Tue, 12 Jan 2016 16:48:03 +0000 |
| Subject: | Req #71352 [NEW]: instanceof magic method | ||
| Groups: | php.bugs | ||
| Request: | Send a blank email to php-bugs+get-198611@lists.php.net to get a copy of this message | ||
From: tom at r dot je
Operating system: *
PHP version: 7.0.2
Package: *General Issues
Bug Type: Feature/Change Request
Bug description:instanceof magic method
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 bug report at https://bugs.php.net/bug.php?id=71352&edit=1
--
Try a snapshot (PHP 5.4): https://bugs.php.net/fix.php?id=71352&r=trysnapshot54
Try a snapshot (PHP 5.5): https://bugs.php.net/fix.php?id=71352&r=trysnapshot55
Try a snapshot (trunk): https://bugs.php.net/fix.php?id=71352&r=trysnapshottrunk
Fixed in SVN: https://bugs.php.net/fix.php?id=71352&r=fixed
Fixed in release: https://bugs.php.net/fix.php?id=71352&r=alreadyfixed
Need backtrace: https://bugs.php.net/fix.php?id=71352&r=needtrace
Need Reproduce Script: https://bugs.php.net/fix.php?id=71352&r=needscript
Try newer version: https://bugs.php.net/fix.php?id=71352&r=oldversion
Not developer issue: https://bugs.php.net/fix.php?id=71352&r=support
Expected behavior: https://bugs.php.net/fix.php?id=71352&r=notwrong
Not enough info: https://bugs.php.net/fix.php?id=71352&r=notenoughinfo
Submitted twice: https://bugs.php.net/fix.php?id=71352&r=submittedtwice
register_globals: https://bugs.php.net/fix.php?id=71352&r=globals
PHP 4 support discontinued: https://bugs.php.net/fix.php?id=71352&r=php4
Daylight Savings: https://bugs.php.net/fix.php?id=71352&r=dst
IIS Stability: https://bugs.php.net/fix.php?id=71352&r=isapi
Install GNU Sed: https://bugs.php.net/fix.php?id=71352&r=gnused
Floating point limitations: https://bugs.php.net/fix.php?id=71352&r=float
No Zend Extensions: https://bugs.php.net/fix.php?id=71352&r=nozend
MySQL Configuration Error: https://bugs.php.net/fix.php?id=71352&r=mysqlcfg