3

我试图保留一个变量引用以供以后使用。

不确定这是否可行,但我希望我可以初始化一个数组元素,并用一个变量引用它。然后,将所述数组元素的值设置为某个值,从而使该值可以从引用的变量中访问。

例如,这有效:

class Test{

    private $_vars = array();

    public function bind($key, &$var){
        $this->_vars[$key] = &$var;
        return $this;
    }

    public function fetch($key, &$var){
        $var = $this->_vars[$key];
        return $this;
    }

}

$test = new Test();
$string_set = 'This is a string';

$test->bind('string', $string_set)
    ->fetch('string', $string_get);

var_dump($string_get);
// expected:  string(16) "This is a string"
// actual:    string(16) "This is a string"

现在问题来了;方法调用的顺序。我不能让call()函数返回对的引用$this,因为该call()函数需要传递存储的匿名函数的返回值(否则我会将调用重新排序为->call()->fetch()而不是->fetch()->call()

无论如何,该fetch()方法应该通过 key in 设置适当的元素($_vars清空任何现有值,或对其进行初始化,以任何一个为准),然后将该元素引用到传递的.NULL$var

当调用匿名函数时(fetch()绑定完成后),它调用bind(),现在将元素绑定$_vars到任何内容(在这种情况下$string_set包含This is a string)如果我的逻辑是正确的,则fetch()绑定变量($string_get在这种情况下)现在应该引用数组$_vars引用$string_set其中包含的元素This is a string

不过好像不是这样的。这是失败的代码(为简洁起见,被剥离,但所有重要部分都在那里

class Test{

    private $_vars = array();
    private $_function;

    public static function factory(){
        return $test = new self(function() use(&$test){
            $string_set = 'This is a string';
            $test->bind('string', $string_set);
            return true;
        });
    }

    private function __construct($function){
        $this->_function = $function;
    }

    public function bind($key, &$var){
        $this->_vars[$key] = &$var;
        return $this;
    }

    public function fetch($key, &$var){
        $this->_vars[$key] = null;
        $var = &$this->_vars[$key]; // edited; was not assigning by reference
        return $this;
    }

    public function call(){
        return (bool) call_user_func($this->_function);
    }

}

$return = Test::factory()
    ->fetch('string', $string_get)
    ->call();

var_dump($return, $string_get);
// expected:  bool(TRUE), string(16) "This is a string"
// actual:    bool(TRUE), NULL

我在这里追逐雏菊,这可能吗?无论哪种方式,我都感谢并提前感谢您甚至瞥了一眼这个问题,任何见解都非常感谢。

编辑:中的行fetch()-$var = $this->_vars[$key];没有通过引用分配数组元素。我现在已将其编辑为$var = &$this->_vars[$key];,尽管它似乎没有效果。

奖励:如果这个问题是可以解决的,那显然很棒;我实际上希望这bind()可以$var通过价值来衡量,而不是通过参考。方法签名将更改为类似set($key, $value). 无论如何,再次提前感谢。


为了详细说明看似好奇的人(看着你的方向@Tomalak),我将提供更完整的类和使用场景:

class Action{

    private static $_cache = array();
    private static $_basePath;

    private $_vars = array();
    private $_function;

    public static function setBasePath($basePath){
        $basePath = rtrim($basePath, '/') . '/';
        if(!is_dir($basePath)){
            // throw exception, $basePath not found
        }
        self::$_basePath = $basePath;
    }

    public static function load($actionPath){
        $actionPath = self::$_basePath . $actionPath;
        if(array_key_exists($actionPath, self::$_cache)){
            return self::$_cache[$actionPath];
        }
        if(!is_file($actionPath)){
            // throw exception, $actionPath not found
        }
        $action = call_user_func(function() use(&$action, $actionPath){
            return require($actionPath);
        });
        if(!($action instanceof self)){
            // throw exception, $action of invalid type
        }
        self::$_cache[$actionPath] = $action;
        return $action;
    }

    public function __construct($function){
        if(!is_callable($function)){
            // throw exception, $function not callable
        }
        $this->_function = $function;
    }

    public function bindReturn($key, &$var){
        $this->_vars[$key] = &$var;
        return $this;
    }

    public function fetchInto($key, &$var){
        $this->_vars[$key] = null;
        $var = &$this->_vars[$key];
        return $this;
    }

    public function run(){
        return (bool) call_user_func_array($this->_function, func_get_args());
    }

}

############################################################################

// actions/test.php

return new Action(function($name)
    use(&$action){

        if($name == 'Alice'){
            return false;
        }

        $data = "Hi, my name is {$name}.";
        $action->bindReturn('data', $data);

        return true;

    });

############################################################################

// index.php (or whatever)

$result = Action::load('actions/test.php') // loaded
    ->fetchInto('data', $data)
    ->run('Alice');

// Failed
echo $result
    ? 'Success - ' . $data
    : 'Failed';

$result = Action::load('actions/test.php') // called from cache
    ->fetchInto('data', $data)
    ->run('Bob');

// Success - Hi, my name is Bob
echo $result
    ? 'Success - ' . $data
    : 'Failed';
4

2 回答 2

2

看起来你有问题

public function fetch($key, &$var){
    $this->_vars[$key] = null;
    $var = $this->_vars[$key];
    return $this;
}

如果要删除密钥,请不要将其设置为 null,请取消设置:

编辑:更改代码以避免未初始化的变量异常。

public function fetch($key, &$var){
    if(isset($this->_vars[$key]))
    {
        $var = $this->_vars[$key];
        unset($this->_vars[$key]);
    }
    else
    {
        $var = null;
    }
    return $this;
}
于 2011-08-12T17:42:49.550 回答
2

您想要做的事情根本不可能(至少在引用时),因为您无法“重定向”引用。这是发生的事情:

$instance->fetch('foo', $myVar);

public function fetch($key, &$var){
    // Here $var is a reference to $myVar.
    $var = &$this->_vars[$key]; // now $var is a reference to $this->_vars[$key]
                                // it is not connected to $myVar anymore.
}

您可以执行以下操作:您可以传递fetch()对数组的引用并将该数组中的元素设置为引用,$this->_vars[$key]或者您可以传递fetch()对象并将成员变量设置为引用。


哦,sry 错过了显而易见的事情:您当然可以bindReturn()在您提供的用例中使用您的函数。那将毫无问题地工作。

于 2011-08-12T21:23:16.193 回答