我正在尝试保留变量引用以供以后使用。
不确定这是否可能,但我希望我可以初始化一个数组元素,并用变量引用它。然后,将所述数组元素的值设置为某个值,从而使值可以从引用的变量中访问。
例如,这有效:
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()
方法应该在$_vars
到NULL
中按键设置相应的元素(清空任何现有值,或者初始化它,无论哪个)然后将该元素引用到传递的$var
。
当调用匿名函数(<{>> fetch()
绑定完成之后)时,它会调用bind()
,现在将$_vars
中的元素绑定到任何内容( 一个$string_set
在这种情况下包含This is a string
)如果我的逻辑是正确的,那么fetch()
绑定变量(在这种情况下为 $string_get
< / em>)现在应引用$_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';
答案 0 :(得分: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;
}
答案 1 :(得分: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()
函数。这没有问题。