PHP method call while ignoring parameter hint type

Given:

class Foo {
    private $bar;

    public function setBar(Bar $bar) {
         $this->bar = $bar;
    }
}

      

Is there any way to call setBar()

with a parameter not an instance Bar

?

$proxy = new Proxy();

$foo = new Foo();
$foo->setBar($proxy);

// with
class Proxy  {
}

      

The idea is to add a proxy object instead of an instance Bar

. The class Proxy

is generic (in a dependency injection framework) and cannot be executed to implement / extend Bar

.


The Reflection API doesn't seem to provide anything to make this possible. I want to do this without using the PHP extension (default PHP installation> 5.3) (and I try to leave only if possible eval

).

Note: yes, this is weird, I am waiting for comments on this, but please leave "answers" for the actual answers to the question. This is not intended for production code.

+3


source to share


3 answers


Does setBar () need to be called, or can you decide by just setting the private $ bar property?

The latter is possible with ReflectionProperty :: setAccessible , then you can assign anything to the property you want as if it were public property.This will not actually make it public, but it will be modified via reflection classes.



AFAIK, the first is not possible without creating temporary classes in strings and then eval (), which is what mocking frameworks do.

+1


source


With reflection, you can ignore private / protected modifiers, so you can use the attribute directly. If that's not an option, I'm afraid you must sell your soul:

eval("class EvilProxy extends Proxy implements Bar {}");
$foo->setBar(new EvilProxy());

      




(I am assuming it Bar

is dynamic - otherwise you could just create the class EvilProxy

statically without eval()

.)

0


source


In your example, the call

$foo->setBar($proxy);

      

will cause a fatal error. If you can live with a strict standard warning like:

Strict standards: TestFoo :: setBar () declaration must be compatible with Foo :: setBar (Bar $ bar)

You can overwrite this function and then change the parent private property through reflection:

class TestFoo extends Foo
{
    public function setBar(Proxy $bar)
    {
        $this->setPrivateParentProperty('bar', $bar);
    }

    private function setPrivateParentProperty($name, $value)
    {
        $refl     = new ReflectionObject($this);
        $property = $refl->getParentClass()->getProperty($name);
        $property->setAccessible(true);
        $property->setValue($this, $value);
    }
}

      

Then you can use a type TestFoo

instead of a type Foo

(unless there is an interface or abstract or definitive prevention from this):

$foo = new TestFoo();
$foo->setBar($proxy);

      

However, as the strict standards warning indicates, this is not a good thing. Compare also to: Why does PHP allow "incompatible" constructors? for more details on why this severe standard error is listed.

0


source







All Articles