获得$ this内部功能

时间:2011-08-26 14:28:16

标签: php

我在我的课外有一个函数,我在内部使用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");
    }
}

6 个答案:

答案 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吗?