用于解除引用函数结果的PHP语法

时间:2009-04-13 01:12:43

标签: php arrays syntax function

背景

在我定期使用的每种其他编程语言中,操作函数的返回值很简单,而不会声明一个新变量来保存函数结果。

然而,在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 e.g., 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     

有人可以建议如何在PHP中执行此操作吗?

22 个答案:

答案 0 :(得分:25)

PHP无法访问函数的数组结果。有些人称这是一个问题,有些人只是接受这个语言的设计方式。所以PHP让你创建不必要的变量只是为了提取你需要的数据。

所以你需要这样做。

$var = foobar();
print($var[0]);

答案 1 :(得分:20)

这是特别是数组解除引用,目前在php5.3中不支持,但应该可以在下一个版本5.4中使用。另一方面,在当前的php版本中,对象解除引用是可能的。我也期待这个功能!

答案 2 :(得分:17)

从PHP 5.4起可以进行数组解除引用:

示例(source):

function foo() {
    return array(1, 2, 3);
}
echo foo()[2]; // prints 3

PHP 5.3 你会得到

Parse error: syntax error, unexpected '[', expecting ',' or ';' 

原始答案:

这是been asked already before。答案是不。这是不可能的。

关于此主题的quote Andi Gutmans

  

这是众所周知的功能请求   但PHP 5.0不支持。一世   无法告诉你它是否曾经存在过   支持的。这需要一些研究   还有很多想法。

您还可以在PHP Bugtracker中找到此request a number of times。有关技术详情,建议您查看official RFC和/或询问PHP Internals

答案 3 :(得分:14)

嗯,您可以根据具体情况使用以下任何一种解决方案:

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()的示例代码不正确。 each()返回一个键值对。因此,使用 foreach()

可能更容易
foreach(foo() as $key=>$val) {
    echo($val);
}

答案 4 :(得分:7)

不幸的是,没有办法做到这一点,尽管它在大多数其他编程语言中。

如果你真的想做一个衬里,你可以创建一个名为a()的函数并执行类似

的操作
$test = a(func(), 1); // second parameter is the key.

但除此之外,PHP中不支持func()[1]。

答案 5 :(得分:5)

编写一个完成相同操作的包装器函数。由于PHP的简单类型转换,这可能是非常开放的:

function array_value ($array, $key) {
return $array[$key];
}

答案 6 :(得分:5)

正如其他人所说,这是不可能的。 PHP的语法不允许它。但是,我确实有一个建议从另一个方向攻击问题。

如果您控制getBarArray方法并且可以访问PHP标准库(安装在许多PHP 5.2.X主机上并默认安装在PHP 5.3中),您应该考虑返回{{1而不是本机PHP数组/集合。 ArrayObjectArrayObjects方法,可用于检索任何索引,因此您的代码可能类似于

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);

答案 7 :(得分:5)

如果您只想返回数组中的第一项,请使用current()函数。

return current($foo->getBarArray());

http://php.net/manual/en/function.current.php

答案 8 :(得分:3)

您不能在PHP中链接这样的表达式,因此您必须将array_test()的结果保存在变量中。

试试这个:

function array_test() {
  return array(0, 1, 2);
}

$array = array_test();
echo $array[0];

答案 9 :(得分:3)

实际上,我写了一个允许这种行为的库:

http://code.google.com/p/php-preparser/

适用于所有事物:功能,方法。缓存,所以和PHP本身一样快:)

答案 10 :(得分:2)

非常贫民窟,但是,它只能使用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'));

在大多数其他语言中,我们必须经历一些如此美好的事情。

为了记录,我做了类似于Nolte的事情。对不起,如果我让任何人的眼睛流血。

答案 11 :(得分:2)

这些是解决问题的一些方法。

首先,如果返回的变量数组不属于集合但每个变量具有不同的含义,则可以直接命名变量。

其他两种方法用于返回作为值集合的结果。

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";

答案 12 :(得分:2)

我通常的解决方法是使用像这样的通用函数

 function e($a, $key, $def = null) { return isset($a[$key]) ? $a[$key] : $def; }

然后

  echo e(someFunc(), 'key');

作为奖励,当您不需要时,这也可以避免“未定义的索引”警告。

至于foo()[x]不起作用的原因,答案是非常不礼貌的,不会在这里发表。 ;)

答案 13 :(得分:2)

当然,您可以返回一个对象而不是一个数组并以这种方式访问​​它:

echo "This should be 2: " . test()->b ."\n";

但是我没有找到用数组做这个的可能性:(

答案 14 :(得分:2)

经过进一步研究后,我认为答案是否定的,像这样的临时变量确实是处理函数返回的数组的规范方法。

看起来这将从PHP 5.4开始改变。

此外,这个答案最初是针对此版本的问题:

How to avoid temporary variables in PHP when using an array returned from a function

答案 15 :(得分:2)

这太牵强了,但如果你真的需要它在一条线上:


return index0( $foo->getBarArray() );

/* ... */

function index0( $some_array )
{
  return $some_array[0];
}

答案 16 :(得分:1)

简答:

是。只要函数结果和PHP的特定版本支持PHP,就可以对PHP中函数的返回值进行操作。

引用example2:

//  can php say "homer"?      
//  print zoobar()->fname;     //  homer <-- yup

案例:

  • 函数结果是一个数组,你的PHP版本已经足够
  • 函数结果是一个对象,您想要的对象成员是可以访问的

答案 17 :(得分:1)

以前在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

您也可以对字符串执行相同的操作。它被称为字符串解除引用:

echo 'PHP'[1];

结果:H

答案 18 :(得分:1)

有三种方法可以做同样的事情:

  1. 正如Chacha102所说,使用函数返回索引值:

    function get($from, $id){
        return $from[$id];
    }
    

    然后,您可以使用:

    get($foo->getBarArray(),0);
    

    获取第一个元素,依此类推。

  2. 使用current和array_slice的懒惰方式:

    $first = current(array_slice($foo->getBarArray(),0,1));
    $second = current(array_slice($foo->getBarArray(),1,1));
    
  3. 使用相同的函数返回数组和值:

    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);
    

答案 19 :(得分:1)

如果它只是美学,那么如果你返回一个对象,Object符号将会起作用。就内存管理而言,如果没有临时副本,只需更改引用。

答案 20 :(得分:0)

您可以使用参考:

$ref =& myFunc();
echo $ref['foo'];

这样,你实际上并没有创建返回数组的副本。

答案 21 :(得分:0)

这有用吗?

 return ($foo->getBarArray())[0];

否则,你可以发布getBarArray()函数吗?我不明白为什么到目前为止你发布的内容不起作用。