PHP syntax for dereferencing function result

2018-12-31 04:45发布

Background

In every other programming language I use on a regular basis, it is simple to operate on the return value of a function without declaring a new variable to hold the function result.

In PHP, however, this does not appear to be so simple:

example1 (function result is an array)

<?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 (function result is an object)

<?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     

Can anyone suggest how to do this in PHP?

22条回答
只靠听说
2楼-- · 2018-12-31 05:13

There are three ways to do the same thing:

  1. As Chacha102 says, use a function to return the index value:

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

    Then, you can use:

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

    to obtain the first element and so on.

  2. A lazy way using current and array_slice:

    $first = current(array_slice($foo->getBarArray(),0,1));
    $second = current(array_slice($foo->getBarArray(),1,1));
    
  3. Using the same function to return both, the array and the value:

    class FooClass {
        function getBarArray($id = NULL) {
            $array = array();
    
            // Do something to get $array contents
    
            if(is_null($id))
                return $array;
            else
                return $array[$id];
            }
    }
    

    Then you can obtain the entire array and a single array item.

    $array = $foo->getBarArray();
    

    or

    $first_item = $foo->getBarArray(0);
    
查看更多
倾城一夜雪
3楼-- · 2018-12-31 05:14

Well, you could use any of the following solutions, depending on the situation:

function foo() {
    return array("foo","bar","foobar","barfoo","tofu");
}
echo(array_shift(foo())); // prints "foo"
echo(array_pop(foo())); // prints "tofu"

Or you can grab specific values from the returned array using list():

list($foo, $bar) = foo();
echo($foo); // prints "foo"
echo($bar); // print "bar"

Edit: the example code for each() I gave earlier was incorrect. each() returns a key-value pair. So it might be easier to use foreach():

foreach(foo() as $key=>$val) {
    echo($val);
}
查看更多
萌妹纸的霸气范
4楼-- · 2018-12-31 05:15

Array Dereferencing is possible as of PHP 5.4:

Example (source):

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

with PHP 5.3 you'd get

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

Original Answer:

This has been been asked already before. The answer is no. It is not possible.

To quote Andi Gutmans on this topic:

This is a well known feature request but won't be supported in PHP 5.0. I can't tell you if it'll ever be supported. It requires some research and a lot of thought.

You can also find this request a number of times in the PHP Bugtracker. For technical details, I suggest you check the official RFC and/or ask on PHP Internals.

查看更多
不再属于我。
5楼-- · 2018-12-31 05:15

Short Answer:

Yes. It is possible to operate on the return value of a function in PHP, so long as the function result and your particular version of PHP support it.

Referencing example2:

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

Cases:

  • The function result is an array and your PHP version is recent enough
  • The function result is an object and the object member you want is reachable
查看更多
余欢
6楼-- · 2018-12-31 05:18

Extremely ghetto, but, it can be done using only PHP. This utilizes a lambda function (which were introduced in PHP 5.3). See and be amazed (and, ahem, terrified):

function foo() {
    return array(
        'bar' => 'baz',
        'foo' => 'bar',
}

// prints 'baz'
echo call_user_func_array(function($a,$k) { 
    return $a[$k]; 
}, array(foo(),'bar'));

The lengths we have to go through to do something so beautiful in most other languages.

For the record, I do something similar to what Nolte does. Sorry if I made anyone's eyes bleed.

查看更多
与君花间醉酒
7楼-- · 2018-12-31 05:21

Actually, I've written a library which allows such behavior:

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

Works with everything: functions, methods. Caches, so being as fast as PHP itself :)

查看更多
登录 后发表回答