用于取消引用函数结果的PHP语法
背景
在我定期使用的每种其他编程语言中,对一个函数的返回值操作很简单,而不用声明一个新variables来保存函数结果。
然而,在PHP中,这似乎并不那么简单:
example1(函数结果是一个数组)
<?php function foobar(){ return preg_split('/\s+/', 'zero one two three four five'); } // can php say "zero"? /// print( foobar()[0] ); /// <-- nope /// print( &foobar()[0] ); /// <-- nope /// print( &foobar()->[0] ); /// <-- nope /// print( "${foobar()}[0]" ); /// <-- nope ?>
example2(函数结果是一个对象)
<?php function zoobar(){ // NOTE: casting (object) Array() has other problems in PHP // see eg, http://stackoverflow.com/questions/1869812 $vout = (object) Array('0'=>'zero','fname'=>'homer','lname'=>'simpson',); return $vout; } // can php say "zero"? // print zoobar()->0; // <- nope (parse error) // print zoobar()->{0}; // <- nope // print zoobar()->{'0'}; // <- nope // $vtemp = zoobar(); // does using a variable help? // print $vtemp->{0}; // <- nope
任何人都可以build议如何在PHP中做到这一点?
这是特别的数组解引用,目前在php5.3中不支持,但应该可以在下一个版本5.4中使用。 另一方面,在目前的PHP版本中,对象解引用是可能的。 我也期待这个function!
PHP无法访问函数的数组结果。 有些人把这称为一个问题,有些人只是接受这个语言是如何devise的。 所以PHP让你创build非必需variables来提取你所需要的数据。
所以你需要做的。
$var = foobar(); print($var[0]);
从PHP 5.4起可以使用数组解引用:
示例( 来源 ):
function foo() { return array(1, 2, 3); } echo foo()[2]; // prints 3
与PHP 5.3你会得到
Parse error: syntax error, unexpected '[', expecting ',' or ';'
原始答案:
这已经 被问到 过了 。 答案是不。 这不可能。
引用 Andi Gutmans关于这个话题:
这是一个众所周知的function请求,但不会在PHP 5.0中受支持。 我不能告诉你它是否会得到支持。 这需要一些研究和思考。
您也可以在PHP Bugtracker 中多次find这个请求 。 对于技术细节,我build议你检查官方的RFC和/或问PHP内部 。
那么,根据具体情况,您可以使用以下任何解决scheme:
function foo() { return array("foo","bar","foobar","barfoo","tofu"); } echo(array_shift(foo())); // prints "foo" echo(array_pop(foo())); // prints "tofu"
或者你可以使用list()从返回的数组中获取特定的值:
list($foo, $bar) = foo(); echo($foo); // prints "foo" echo($bar); // print "bar"
编辑:我以前给每个()的示例代码是不正确的。 each()返回一个键值对。 所以使用foreach()可能更容易:
foreach(foo() as $key=>$val) { echo($val); }
不幸的是没有办法做到这一点,虽然它是在大多数其他编程语言。
如果你真的想做一个class轮,你可以做一个叫做()的函数,做一些类似的事情
$test = a(func(), 1); // second parameter is the key.
但除此之外,PHP中不支持func()[1]。
正如其他人所说,这是不可能的。 PHP的语法不允许。 不过,我有一个build议,从另一个方向来攻击这个问题。
如果您在控制getBarArray
方法并可以访问PHP标准库(安装在许多PHP 5.2.X主机上,并且默认安装了PHP 5.3),则应考虑返回一个ArrayObject
而不是原生的PHP数组/集合。 ArrayObjects
有一个offetGet
方法,可以用来检索任何索引,所以你的代码可能看起来像这样
<?php class Example { function getBarArray() { $array = new ArrayObject(); $array[] = 'uno'; $array->append('dos'); $array->append('tres'); return $array; } } $foo = new Example(); $value = $foo->getBarArray()->offsetGet(2);
如果你需要一个本地数组/集合,你总是可以投出结果。
//if you need $array = (array) $foo->getBarArray();
写一个包装的function,将完成相同的。 由于PHP的简单的types转换,这可能是非常开放的:
function array_value ($array, $key) { return $array[$key]; }
如果您只想返回数组中的第一个项目,请使用current()函数。
return current($foo->getBarArray());
其实,我写了一个图书馆,允许这样的行为:
http://code.google.com/p/php-preparser/
适用于一切:function,方法。 caching,所以像PHP本身一样快:)
你不能像PHP那样链接expression式,所以你必须将array_test()
的结果保存在一个variables中。
尝试这个:
function array_test() { return array(0, 1, 2); } $array = array_test(); echo $array[0];
这太牵强了,但如果你真的需要它在一行:
return index0( $foo->getBarArray() ); /* ... */ function index0( $some_array ) { return $some_array[0]; }
当然,你可以返回一个对象,而不是一个数组,并以这种方式访问它:
echo "This should be 2: " . test()->b ."\n";
但我没有find一个可能性做一个数组:(
我通常的解决方法是有一个这样的通用function
function e($a, $key, $def = null) { return isset($a[$key]) ? $a[$key] : $def; }
接着
echo e(someFunc(), 'key');
作为奖励,这也可以避免在你不需要的时候出现“未定义索引”的警告。
至于为什么foo()[x]
不起作用,答案是非常不礼貌的,不会在这里发表。 ;)
这些是解决您的问题的一些方法。
首先,如果您返回的数组不是集合的一部分,但是各自具有不同的含义,则可以直接使用这些variables来命名variables。
其他两种方法是返回值的集合的结果。
function test() { return array(1, 2); } list($a, $b) = test(); echo "This should be 2: $b\n"; function test2() { return new ArrayObject(array('a' => 1, 'b' => 2), ArrayObject::ARRAY_AS_PROPS); } $tmp2 = test2(); echo "This should be 2: $tmp2->b\n"; function test3() { return (object) array('a' => 1, 'b' => 2); } $tmp3 = test3(); echo "This should be 2: $tmp3->b\n";
极端贫民窟,但是,它可以完成只使用PHP。 这使用了lambda函数(在PHP 5.3中引入)。 看,并惊讶(而且,啊,吓坏了):
function foo() { return array( 'bar' => 'baz', 'foo' => 'bar', } // prints 'baz' echo call_user_func_array(function($a,$k) { return $a[$k]; }, array(foo(),'bar'));
我们必须经过这么长的时间才能在大多数其他语言中做出如此美丽的事情。
为了logging,我做了类似Nolte的事情。 对不起,如果我让任何人的眼睛stream血。
经过进一步的研究,我相信答案是否定的,像这样的临时variables确实是处理从函数返回的数组的正则方法。
看起来这将改变从PHP 5.4开始。
此外,这个答案最初是针对这个问题的版本:
如何在使用从函数返回的数组时避免PHP中的临时variables
如果仅仅是审美的话,那么如果你返回一个对象,那么对象符号就可以工作。 就内存pipe理而言,如果做了临时拷贝,只需要改变参考。
简答:
是。 只要函数结果和你的特定版本的PHP支持它,就可以在PHP函数的返回值上进行操作。
引用example2:
// can php say "homer"? // print zoobar()->fname; // homer <-- yup
案例:
- 函数的结果是一个数组,你的PHP版本已经足够了
- 函数的结果是一个对象,你想要的对象成员是可达的
有三种方法可以做同样的事情:
-
正如Chacha102所说,使用一个函数来返回索引值:
function get($from, $id){ return $from[$id]; }
那么,你可以使用:
get($foo->getBarArray(),0);
获得第一个元素等等。
-
使用current和array_slice的一种懒惰的方式:
$first = current(array_slice($foo->getBarArray(),0,1)); $second = current(array_slice($foo->getBarArray(),1,1));
-
使用相同的函数返回数组和值:
class FooClass { function getBarArray($id = NULL) { $array = array(); // Do something to get $array contents if(is_null($id)) return $array; else return $array[$id]; } }
然后你可以获得整个数组和单个数组项。
$array = $foo->getBarArray();
要么
$first_item = $foo->getBarArray(0);
以前在PHP 5.3中,你必须这样做:
function returnArray() { return array(1, 2, 3); } $tmp = returnArray(); $ssecondElement = $tmp[1];
结果: 2
从PHP 5.4开始,可以像下面这样取消引用数组:
function returnArray() { return array(1, 2, 3); } $secondElement = returnArray()[1];
结果: 2
从PHP 5.5开始:
你甚至可以变聪明:
echo [1, 2, 3][1];
结果: 2
你也可以用string做同样的事情。 这就是所谓的string解引用:
echo 'PHP'[1];
结果: H
这是否工作?
return ($foo->getBarArray())[0];
否则,你可以发布getBarArray()函数吗? 我不明白为什么这不会从你发布到目前为止。
你可以使用引用:
$ref =& myFunc(); echo $ref['foo'];
这样,你并没有真正创build返回的数组的副本。