php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Request #62113 ReflectionMethod::invoke && invokeArgs support static binding...
Submitted: 2012-05-22 21:38 UTC Modified: 2021-09-14 12:38 UTC
Votes:3
Avg. Score:3.3 ± 0.5
Reproduced:2 of 2 (100.0%)
Same Version:2 (100.0%)
Same OS:1 (50.0%)
From: nathanb@php.net Assigned:
Status: Suspended Package: Reflection related
PHP Version: 5.4.3 OS: N/A
Private report: No CVE-ID: None
 [2012-05-22 21:38 UTC] nathanb@php.net
Description:
------------
I think it'd be useful to be able to set the static binding of a class method if 
it's a static method. Currently you can only set the binding if it's not a static 
method, but my patch (see below) now will allow you to pass a string or an object 
to the ReflectionMethod::invoke and invokeArgs methods allowing you to set the 
static binding of static functions.

The script below will work with the patch in place, but not work with current 
version of PHP because you *must* pass a valid object or null as the first 
argument, but if you are wanting it to call a static method my patch will allow 
you to set the Class the static method will run under.

Test script:
---------------
<?php
trait A{
	public static function static_method(){
		return get_called_class();
	}
	public function normal_method(){
		return get_called_class();
	}
	public function normal_method_this(){
		return get_class($this);
	}
}

class B{
}
class C extends B{
	use A;
	public function test(){
		$returns = array();
		$returns[] = 'C => ' .			current((new ReflectionClass('C'))->getTraits())->getMethod('static_method')->invoke($this);
		$returns[] = 'B => ' .			current((new ReflectionClass('C'))->getTraits())->getMethod('static_method')->invoke('B');
		$returns[] = 'C => ' .			current((new ReflectionClass('C'))->getTraits())->getMethod('static_method')->invoke('C');
		$returns[] = 'A => ' .			current((new ReflectionClass('C'))->getTraits())->getMethod('static_method')->invoke(null);
		$returns[] = 'stdClass => ' .	current((new ReflectionClass('C'))->getTraits())->getMethod('static_method')->invoke(new stdClass);

		$returns[] = 'C => ' .			current((new ReflectionClass('C'))->getTraits())->getMethod('static_method')->invokeArgs($this, array());
		$returns[] = 'B => ' .			current((new ReflectionClass('C'))->getTraits())->getMethod('static_method')->invokeArgs('B', array());
		$returns[] = 'C => ' .			current((new ReflectionClass('C'))->getTraits())->getMethod('static_method')->invokeArgs('C', array());
		$returns[] = 'A => ' .			current((new ReflectionClass('C'))->getTraits())->getMethod('static_method')->invokeArgs(null, array());
		
		$returns[] = 'C => ' .			current((new ReflectionClass('C'))->getTraits())->getMethod('normal_method')->invoke($this);
		$returns[] = 'stdClass => ' .	current((new ReflectionClass('C'))->getTraits())->getMethod('normal_method')->invoke(new stdClass);
		$returns[] = 'B => ' .			current((new ReflectionClass('C'))->getTraits())->getMethod('normal_method')->invoke(new B());

		$returns[] = 'C => ' .			current((new ReflectionClass('C'))->getTraits())->getMethod('normal_method_this')->invoke($this);
		$returns[] = 'stdClass => ' .	current((new ReflectionClass('C'))->getTraits())->getMethod('normal_method_this')->invoke(new stdClass());
		$returns[] = 'B => ' .			current((new ReflectionClass('C'))->getTraits())->getMethod('normal_method_this')->invoke(new B());

		// Normal methods need an object
		//$returns[] = current((new ReflectionClass('C'))->getTraits())->getMethod('normal_method')->invokeArgs($this, array());
		//$returns[] = current((new ReflectionClass('C'))->getTraits())->getMethod('normal_method')->invoke('B', array()); // Error
		//$returns[] = current((new ReflectionClass('C'))->getTraits())->getMethod('normal_method')->invoke('B', array()); // Error
		//$returns[] = current((new ReflectionClass('C'))->getTraits())->getMethod('normal_method')->invoke(null, array()); // Error
		//$returns[] = current((new ReflectionClass('C'))->getTraits())->getMethod('normal_method_this')->invokeArgs($this, array());
		//$returns[] = current((new ReflectionClass('C'))->getTraits())->getMethod('normal_method_this')->invoke('B', array()); // Error
		//$returns[] = current((new ReflectionClass('C'))->getTraits())->getMethod('normal_method_this')->invoke('B', array()); // Error
		//$returns[] = current((new ReflectionClass('C'))->getTraits())->getMethod('normal_method_this')->invoke(null, array()); // Error
		return $returns;
	}
}

$a = new C;
print_r($a->test());
echo  "\n";

Expected result:
----------------
Array
(
    [0] => C => C
    [1] => B => B
    [2] => C => C
    [3] => A => A
    [4] => stdClass => stdClass
    [5] => C => C
    [6] => B => B
    [7] => C => C
    [8] => A => A
    [9] => C => C
    [10] => stdClass => stdClass
    [11] => B => B
    [12] => C => C
    [13] => stdClass => stdClass
    [14] => B => B
)

Actual result:
--------------
Currently wont work because you can only pass objects or null as first parameter

Patches

ReflectionMethod-invoke-static-bindings (last revision 2012-05-22 21:38 UTC by nathanbruer at gmail dot com)

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2012-09-12 14:47 UTC] nathanb@php.net
-: nathanbruer at gmail dot com +: nathanb@php.net
 [2012-09-12 14:47 UTC] nathanb@php.net
* Updated email address for profiling and spam reasons
 [2013-01-31 18:36 UTC] lisachenko dot it at gmail dot com
Related discussion on mailing list: http://news.php.net/php.internals/64943
 [2021-09-14 12:38 UTC] cmb@php.net
-Status: Open +Status: Suspended
 [2021-09-14 12:38 UTC] cmb@php.net
Apparently, this went nowhere and skimming the internal
discussion[1] shows that this feature is controversial.  As such
this feature requires the RFC process[2].  Anybody is welcome to
pursue it any time; I suspend this ticket until that happens.

[1] <https://externals.io/message/64943>
[2] <https://wiki.php.net/rfc/howto>
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sat Dec 21 12:01:31 2024 UTC