• 13
name

A PHP Error was encountered

Severity: Notice

Message: Undefined index: userid

Filename: views/question.php

Line Number: 191

Backtrace:

File: /home/prodcxja/public_html/questions/application/views/question.php
Line: 191
Function: _error_handler

File: /home/prodcxja/public_html/questions/application/controllers/Questions.php
Line: 433
Function: view

File: /home/prodcxja/public_html/questions/index.php
Line: 315
Function: require_once

name Punditsdkoslkdosdkoskdo

PHP syntax for dereferencing function result

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     
    • For the benefit of readers who don't scroll to the later answers, array derefencing has been added to PHP 5.4 (in beta at time of this comment)...
      • 2
    • @Pacerier by what metric are you declaring one more "beautiful" than the other? Is one more efficient? Frankly, the second choice is quicker and easier to write.

PHP can not access array results from a function. Some people call this an issue, some just accept this as how the language is designed. So PHP makes you create unessential variables just to extract the data you need.

So you need to do.

$var = foobar();
print($var[0]);
  • 26
Reply Report
    • I realise that I'm still incredibly new to this, but why is this a problem? It...makes sense to me that you'd need to create a variable to hold a value/result; though admittedly: very new
    • Some people call this an issue, but this is just how the language is designed. Other languages are designed in a way where this is possible, and people coming from those languages feel that this is an issue.
      • 2
    • It's an issue because it becomes very easy to lose track of where you are if you have a function that returns a structured variable or object. For example, what if you have $data['tvshow']['episodes'][1]['description'] as a valid address in your variable?
      • 1
    • Really, the language seems consistent on allowing fluent usage of results, so why not with arrays? Seems like they agreed.
      • 2
    • @ÓlafurWaage, No, PHP is not designed this way. This is an oversight and not "just how the language is designed". It is precisely because this is an issue that it is fixed in PHP 5.4.

This is specifically array dereferencing, which is currently unsupported in php5.3 but should be possible in the next release, 5.4. Object dereferencing is on the other hand possible in current php releases. I'm also looking forward to this functionality!

  • 20
Reply Report
      • 2
    • NOTE: This question was incorrectly marked as a duplicate of array dereferencing. This question is not a duplicate, because it is not exclusively about arrays. A PHP function can return any value type, not just arrays (see example2 in the original post, where the function result is an object, and not an array).

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.

  • 17
Reply Report

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);
}
  • 14
Reply Report
      • 1
    • In PHP 5.5.10 it still throws the following error: "Strict standards: Only variables should be passed by reference in php". Ridiculous.
      • 1
    • @ZsoltGyöngyösi, That error is present way back in PHP 5.05. See 3v4l.org/voQIS . Also, performance note: array_pop may be fast because you need to simply remove the last element, but array_shift is incredibly slow because it needs to change all the number indexes by shifting them down by 1.

There isn't a way to do that unfortunately, although it is in most other programming languages.

If you really wanted to do a one liner, you could make a function called a() and do something like

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

But other than that, func()[1] is not supported in PHP.

  • 7
Reply Report
      • 2
    • Oh wow, I didn't know that. Do you know why that doesn't work? Shouldn't func() be essentially an array type with the return value, so [1] acts on an array? Or does PHP parse it poorly?
      • 1
    • @Kouroki Kaze: array_slice still returns an array, even if the slice would result in a single value. You could combine it with current, but that's starting to get a bit long for a single line. ;-)

As others have mentioned, this isn't possible. PHP's syntax doesn't allow it. However, I do have one suggestion that attacks the problem from the other direction.

If you're in control of the getBarArray method and have access to the PHP Standard Library (installed on many PHP 5.2.X hosts and installed by default with PHP 5.3) you should consider returning an ArrayObject instead of a native PHP array/collection. ArrayObjects have an offetGet method, which can be used to retrieve any index, so your code might look something like

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

And if you ever need a native array/collection, you can always cast the results.

//if you need 
$array = (array) $foo->getBarArray();
  • 5
Reply Report

Write a wrapper function that will accomplish the same. Because of PHP's easy type-casting this can be pretty open-ended:

function array_value ($array, $key) {
return $array[$key];
}
  • 5
Reply Report
    • The most efficient function would use an array reference here. Example: function array_value(&$a,$k) { $b = &$a; return $b[$k]; }
    • I think you can get the same result by just telling the function to return by reference, i.e. function &array_value (...

If you just want to return the first item in the array, use the current() function.

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

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

  • 5
Reply Report
    • No, there is no guarantee that current is currently pointing to the first element. See 3v4l.org/OZLjR and 3v4l.org/kEC9H for examples whereby blindly calling current will indeed give you the non-first item. Whenever you call current you must first call reset, otherwise be prepared for trouble.

You can't chain expressions like that in PHP, so you'll have to save the result of array_test() in a variable.

Try this:

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

$array = array_test();
echo $array[0];
  • 3
Reply Report

This is too far-fetched, but if you really NEED it to be in one line:


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

/* ... */

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

  • 2
Reply Report

You could, of course, return an object instead of an array and access it this way:

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

But I didn't find a possibility to do this with an array :(

  • 2
Reply Report

my usual workaround is to have a generic function like this

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

and then

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

as a bonus, this also avoids 'undefined index' warning when you don't need it.

As to reasons why foo()[x] doesn't work, the answer is quite impolite and isn't going to be published here. ;)

  • 2
Reply Report
      • 1
    • Do you ever happen to find yourself looking at code that uses this technique, and wondering (even if just for a few milliseconds), "Now what does this do again?"
    • This still creates a temporary (2 or 3, in fact), but they're in a lower scope an quickly go away, so that's a bonus.

These are some ways to approach your problem.

First you could use to name variables directly if you return array of variables that are not part of the collection but have separate meaning each.

Other two ways are for returning the result that is a collection of values.

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";
  • 2
Reply Report

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.

  • 2
Reply Report
    • Man, that was like 4.5 years ago. Who know what I was thinking then? Probably just meant something like "put together with ducktape and string".

Warm tip !!!

This article is reproduced from Stack Exchange / Stack Overflow, please click

Trending Tags

Related Questions