我在我的课外有一个函数,我在内部使用call_user_func
调用它,我的问题是我无法访问函数内部的类。我需要一种方法来访问我的类,而不是在参数中传递它,如果有一种方法可以使$this
在函数内部工作,这将是非常好的。
除了将带有参数的类传递给函数之外的任何建议都将受到赞赏;
function test($arg1)
{
$this->code = 10; // i know $this won't work here,
// but i need a way to change $code
// property from this function without
// passing class into this function by using arguments
}
class MyClass
{
public $code;
public function call()
{
call_user_func("test", "argument1");
}
}
答案 0 :(得分:3)
如果您可以在课堂内移动该功能,您可以这样调用它:
call_user_func(array($this, 'the_function'));
如果你有PHP5.3,你可以使用一个闭包:
$that = $this;
$function = function() use ($that) {
// use $that instead of $this
};
call_user_func($function);
如果你可以添加一个参数,你可以这样做:
call_user_func('the_function', "argument1", $this);
如果函数要求,请将$this
作为第一个参数传递:
(如果函数有一个名为$__this
的参数,则将$this
作为参数传递
function the_function($__this, $foo, $bar) {
}
$arguments = array('argument1');
$function = new ReflectionFunction('the_function');
$params = $function->getParameters();
if (count($params) > 0 && $params[0]->name == '__this') {
array_unshift($arguments, $this);
}
$function->invokeArgs($arguments);
你可以对文档评论做同样的事情:
/**
* @IWantThis
*/
function the_function($__this) {
}
$function = new ReflectionFunction('the_function');
if (preg_match('/@IWantThis/', $function->getDocComment()) {
...
答案 1 :(得分:2)
直接您有两个选择:将对象传递给函数或将值传递给对象。我不知道是这个函数唯一的工作,所以这可能无法解决你的问题,只是在你写的时候显示替代方法,将对象传递给函数不是一个选项:
function test($arg1)
{
return 10;
}
class MyClass
{
public $code;
public function call()
{
$this->code = call_user_func("test", "argument1");
}
}
如果您不想要其中任何一个,您必须创建一些上下文,对象和函数,操作,以便彼此连接。
您可以静态或动态创建上下文。第一个通常与全局变量相关,这可能导致代码长期难以维护,例如:
function test($arg1)
{
global $object;
$object->code = 10;
}
class MyClass
{
public $code;
public function call()
{
global $object;
$object = $this;
call_user_func("test", "argument1");
unset($object);
}
}
要创建更具动态性的上下文,您将所有内容封装到某个上下文中:
class contextCallback
{
private $object;
public function __construct($object)
{
$this->object = $object;
}
public function test()
{
$this->object = 10;
}
}
class MyClass
{
public $code;
public function call()
{
$callback = new contextCallback($this);
call_user_func(array($callback, 'test'), "argument1");
# or:
$callback->test("argument1");
}
}
但是我认为然后传递$this
作为参数要简单得多,而且代码要少得多。我不知道为什么你需要call_user_func
所以它保持这种抽象。
编辑:作为另一种选择,要从具体类中解耦,当您只需要设置值时,请考虑返回多个值:
function test($arg1)
{
$object->code = 10;
return array($value, $object);
}
class MyClass
{
public $code;
public function call()
{
list($value, $object) = call_user_func("test", "argument1");
foreach($object as $var => $value)
$this->$var = $value;
}
}
答案 2 :(得分:1)
你有两个选择。使方法成为MyClass
对象的方法或使对象成为函数的参数。
如果你有一个功能,你希望它做同样的事情,每个时间。这意味着如果函数依赖于某个状态(如$this
的值),那么您需要找到一种方法来1.将其设为全局(此处不是选项)或2.将其作为参数。
你在该函数中不需要 $this
,你需要一些恰好具有$code
内容所命名的属性的对象(I认为这实际上是一个错字。我认为你的意思是$this->code
而不是$this->$code
)。
答案 3 :(得分:1)
您可以使用closure (php 5.3+)将对象引用“传递”给那些需要它的函数 但是你必须在“旧”功能和“新”扩展功能之间做出改变。新功能仍然只能访问对象的公共属性/方法。
<?php
class MyClass
{
public $code = 0;
protected $functions=array();
public function call($fn)
{
if ( is_string($fn) && isset($this->functions[$fn]) ) {
$fn = $this->functions[$fn];
}
if ( !is_callable($fn) ) {
die('add error handler here');
}
$rv = call_user_func($fn, 'argument1');
}
public function loadFunctions($file) {
$fnInit = require $file;
$fns = $fnInit($this);
$this->functions = array_merge($this->functions, $fns);
}
}
$m = new MyClass;
$m->loadFunctions('ext.php');
$m->call('oldFn');
$m->call('foo');
$m->call('bar');
echo 'and now $m->code is: ', $m->code;
和ext.php:
<?php
function oldFn($arg) { // that's probably all you have to do atm to have a new "extension function" for your class
echo "oldFn($arg)\n";
}
return function($obj) { // and that's more or less how the new functions would have to be declared/defined
return array(
'foo'=>function($arg1) use($obj) {
echo "foo($arg1) + code: $obj->code\n";
$obj->code = 1;
},
'bar'=>function($arg1) use($obj) {
echo "bar($arg1) + code: $obj->code\n";
$obj->code = 2;
}
);
};
打印
oldFn(argument1)
foo(argument1) + code: 0
bar(argument1) + code: 1
and now $m->code is: 2
(如果这对我来说似乎有些可行,我可以写一些文字......但现在不行;-))
答案 4 :(得分:0)
call_user_func("test", array($this,"argument1"));
我不是100%,但您应该可以使用
访问它function test($arg1)
{
$arg1[0]->code = 10;
}
答案 5 :(得分:0)
runkit
会满足您的需求,特别是runkit_function_redefine
吗?