PHP: Variable in a function name - php

I want to trigger a function based on a variable.
function sound_dog() { return 'woof'; }
function sound_cow() { return 'moo'; }
$animal = 'cow';
print sound_{$animal}(); *
The * line is the line that's not correct.
I've done this before, but I can't find it. I'm aware of the potential security problems, etc.
Anyone? Many thanks.

You can do that, but not without interpolating the string first:
$animfunc = 'sound_' . $animal;
print $animfunc();
Or, skip the temporary variable with call_user_func():
call_user_func('sound_' . $animal);

You can do it like this:
$animal = 'cow';
$sounder = "sound_$animal";
print ${sounder}();
However, a much better way would be to use an array:
$sounds = array('dog' => sound_dog, 'cow' => sound_cow);
$animal = 'cow';
print $sounds[$animal]();
One of the advantages of the array method is that when you come back to your code six months later and wonder "gee, where is this sound_cow function used?" you can answer that question with a simple text search instead of having to follow all the logic that creates variable function names on the fly.

http://php.net/manual/en/functions.variable-functions.php
To do your example, you'd do
$animal_function = "sound_$animal";
$animal_function();

You can use curly brackets to build your function name. Not sure of backwards compatibility, but at least PHP 7+ can do it.
Here is my code when using Carbon to add or subtract time based on user chosen type (of 'add' or 'sub'):
$type = $this->date->calculation_type; // 'add' or 'sub'
$result = $this->contactFields[$this->date->{'base_date_field'}]
->{$type.'Years'}( $this->date->{'calculation_years'} )
->{$type.'Months'}( $this->date->{'calculation_months'} )
->{$type.'Weeks'}( $this->date->{'calculation_weeks'} )
->{$type.'Days'}( $this->date->{'calculation_days'} );
The important part here is the {$type.'someString'} sections. This will generate the function name before executing it. So in the first case if the user has chosen 'add', {$type.'Years'} becomes addYears.

For PHP >= 7 you can use this way:
function sound_dog() { return 'woof'; }
function sound_cow() { return 'moo'; }
$animal = 'cow';
print ("sound_$animal")();

You should ask yourself why you need to be doing this, perhaps you need to refactor your code to something like the following:
function animal_sound($type){
$animals=array();
$animals['dog'] = "woof";
$animals['cow'] = "moo";
return $animals[$type];
}
$animal = "cow";
print animal_sound($animal);

You can use $this-> and self:: for class-functions. Example provided below with a function input-parameter.
$var = 'some_class_function';
call_user_func(array($this, $var), $inputValue);
// equivalent to: $this->some_class_function($inputValue);

And yet another solution to what I like to call the dog-cow problem. This will spare a lot of superfluous function names and definitions and is perfect PHP syntax and probably future proof:
$animal = 'cow';
$sounds = [
'dog' => function() { return 'woof'; },
'cow' => function() { return 'moo'; }
];
print ($sounds[$animal])();
and looks a little bit less like trickery as the "string to function names" versions.
JavaScript devs might prefer this one for obvious reasons.
(tested on Windows, PHP 7.4.0 Apache 2.4)

Related

PHP: Specify argument variable names when calling a function?

This might seem like an academic or useless topic, but I'm curious.
When developing web pages with PHP, I often need to call functions that take several arguments. I frequently need to look up the spec for the function (on php.net or in my include files, if it's a function I defined) to remind myself what the variables are and what order they're in and what the defaults are, etc. I imagine many of you can relate to this.
A function defined like this:
function do_something_awesome ($people_array, $places_recordset, $num_cycles, $num_frogs,
$url = '?default=yes', $submit_name = 'default_submit_label') {
...
}
when called, might look like this:
$result = do_something_awesome($names, $rsTowns, $c, $f);
My question is this: I'd like to write my code in a way that reminds me of which argument corresponds to each variable, during function calls like this. Is it ever legal to call a function as follows?
$result = do_something_awesome($people_array = $names, $places_recordset = $rsTowns,
$num_cycles = $c, $num_frogs = $f);
If not in PHP, are there other languages where method calls can be made in this way?
To answer your first question:
My question is this: I'd like to write my code in a way that reminds me of which argument corresponds to each variable, during function calls like this.
AFAIK, many PHP coders do it by passing in an associative array as the only argument. However, you'll have to do your own variables checking inside the called function.
$result = do_something_awesome(array(
'people_array' => $names,
'places_recordset' => $rsTowns,
'num_cycles' => $c,
'num_frogs' => $f
));
As for:
Is it ever legal to call a function as follows?
It won't cause any PHP errors, but what you are effectively doing is:
$result = do_something_awesome( expression, expression, expression, expression );
See: PHP Functions arguments
PHP won't know to put $people_array = ... or $num_frogs = ... in their corresponding places when you decide to switch their order around. Furthermore, as DCoder said, these expressions actually take place in the current scope, and will change any pre-existing variables without letting you know.
What about using an object as the only argument:
function my_function($arguments) {
if (!is_object($arguments)) throw new Exception();
$default_values = array('arg1' => 'value1', 'arg2' => 'value2');
foreach ($default_values as $key => $default_value)
if (!isset($arguments->$key)) $arguments->$key = $default_value;
## do the job ##
}
## and then
$my_arguments = new stdClass();
$my_arguments->arg2 = 'some_value';
my_function($my_arguments);
You can try this out:
$bas = 'This is passed to the function.';
$bar = 'This will be modified.';
function foo($bar)
{
echo $bar;
}
foo($bar = $bas);
echo $bar;
The output from this script would be 'This is passed to the function.This is passed to the function.'. So like DCoder said, while you can use them and it's perfectly legal but if you had other variables with the same name as the function arguments, this will overwrite them (in this case the original $bar was overwritten).

How to Pass Class Variables in a Function Parameter

The main function of the example class uses the reusableFunction twice with different data and attempts to send that data to a different instance variable ($this->result1container and $this->result2container) in each case, but the data doesn't get into the instance variables.
I could get it to work by making reusableFunction into two different functions, one with array_push($this->result1container, $resultdata) and the other with array_push($this->result2container, $resultdata), but I am trying to find a solution that doesn't require me to duplicate the code.
My solution was to try to pass the name of the result container into the function, but no go. Does somebody know a way I could get this to work?
Example Code:
Class Example {
private $result1container = array();
private $result2container = array();
function __construct() {
;
}
function main($data1, $data2) {
$this->reusableFunction($data1, $this->result1container);
$this->reusableFunction($data2, $this->result2container);
}
function reusableFunction($data, $resultcontainer) {
$resultdata = $data + 17;
// PROBLEM HERE - $resultcontainer is apparently not equal to
// $this->result1container or $this->result2container when I
// try to pass them in through the parameter.
array_push($resultcontainer, $resultdata);
}
function getResults() {
return array(
"Container 1" => $this->result1container,
"Container 2" => $this->result2container);
}
}
(If this is a duplicate of a question, I apologize and will happily learn the answer from that question if somebody would be kind enough to point me there. My research didn't turn up any answers, but this might just be because I didn't know the right question to be searching for)
It looks to me like you want to be passing by reference:
function reusableFunction($data, &$resultcontainer) {
...
If you don't pass by reference with the & then you are just making a local copy of the variable inside reuseableFunction .
You are changing the copy, not the original. Alias the original Array by referenceDocs:
function reusableFunction($data, &$resultcontainer) {
# ^
And that should do the job. Alternatively, return the changed Array and assign it to the object member it belongs to (as for re-useability and to keep things apart if the real functionality is doing merely the push only).
Additionally
array_push($resultcontainer, $resultdata);
can be written as
$resultcontainer[] = $resultdata;
But that's just really FYI.
You may pass the attributes name as a String to the method like this:
function reusableFunction($data, $resultcontainer) {
$resultdata = $data + 17;
array_push($this->{$resultcontainer}, $resultdata);
}
//..somewhere else..
$this->reusableFunction($data, 'result2Container')
Some php experts wrote some texts about "why you shouldn't use byReference in php".
Another solution would be to define the containers as an array. Then you can pass an "key" to the method that is used to store the result in the array. Like this:
private $results = array();
function reusableFunction($data, $resIdx) {
$resultdata = $data + 17;
array_push($this->$results[$resIdx], $resultdata);
}
//..somewhere else..
$this->reusableFunction($data, 'result2Container');
//..or pass a number as index..
$this->reusableFunction($data, 1);

Find the name of a calling var

Anyone has an idea if this is at all possible with PHP?
function foo($var) {
// the code here should output the value of the variable
// and the name the variable has when calling this function
}
$hello = "World";
foo($hello);
Would give me this output
varName = $hello
varValue = World
EDIT
Since most people here 'accuse' me of bad practices and global variables stuff i'm going to elaborate a little further on why we are looking for this behaviour.
the reason we are looking at this kind of behaviour is that we want to make assigning variables to our Views easier.
Most of the time we are doing this to assign variables to our view
$this->view->assign('products', $products);
$this->view->assign('members', $members);
While it would be easier and more readable to just be able to do the following and let the view be responsible to determining the variable name the assigned data gets in our views.
$this->view->assign($products);
$this->view->assign($members);
Short answer: impossible.
Long answer: you could dig through apd, bytekit, runkit, the Reflection API and debug_backtrace to see if any obscure combination would allow you to achieve this behavior.
However, the easiest way is to simply pass the variable name along with the actual variable, like you already do. It's short, it's easy to grasp, it's flexible when you need the variable to have a different name and it is way faster than any possible code that might be able to achieve the other desired behavior.
Keep it simple
removed irrelevant parts after OP edited the question
Regardless of my doubt that this is even possible, I think that forcing a programmer on how to name his variables is generally a bad idea. You will have to answer questions like
Why can't I name my variable $arrProducts instead of $products ?
You would also get into serious trouble if you want to put the return value of a function into the view. Imagine the following code in which (for whatever reason) the category needs to be lowercase:
$this->view->assign(strtolower($category));
This would not work with what you're planning.
My answer therefore: Stick to the 'verbose' way you're working, it is a lot easier to read and maintain.
If you can't live with that, you could still add a magic function to the view:
public function __set($name, $value) {
$this->assign($name, $value);
}
Then you can write
$this->view->product = $product;
I don't think there is any language where this is possible. That's simply not how variables work. There is a difference between a variable and the value it holds. Inside the function foo, you have the value, but the variable that held the value is not available. Instead, you have a new variable $var to hold that value.
Look at it like this: a variable is like a bucket with a name on it. The content (value) of the variable is what's inside the bucket. When you call a function, it comes with its own buckets (parameter names), and you pour the content of your bucket into those (well, the metaphor breaks down here because the value is copied and still available outside). Inside the function, there is no way to know about the bucket that used to hold the content.
What you're asking isn't possible. Even if it was, it would likely be considered bad practice as its the sort of thing that could easily get exploited.
If you're determined to achieve something like this, the closest you can get would be to pass the variable name as a string and reference it in the function from the $GLOBALS array.
eg
function this_aint_a_good_idea_really($var) {
print "Variable name: {$var}\n";
print "Variable contents: {$GLOBALS[$var]}\n";
}
$hello="World";
this_aint_a_good_idea_really('hello');
But as I say, that isn't really a good idea, nor is it very useful. (Frankly, almost any time you resort to using global variables, you're probably doing something wrong)
Its not impossible, you can find where a function was invoked from debug_backtrace() then tokenize a copy of the running script to extract the parameter expressions (what if the calling line is foo("hello $user, " . $indirect($user,5))?),
however whatever reason you have for trying to achieve this - its the wrong reason.
C.
Okay, time for some ugly hacks, but this is what I've got so far, I'll try to work on it a little later
<?php
class foo
{
//Public so we can test it later
public $bar;
function foo()
{
//Init the array
$this->bar = array();
}
function assign($__baz)
{
//Try to figure out the context
$context = debug_backtrace();
//assign the local array with the name and the value
//Alternately you can initialize the variable localy
//using $$__baz = $context[1]['object']->$__baz;
$this->bar[$__baz] = $context[1]['object']->$__baz;
}
}
//We need to have a calling context of a class in order for this to work
class a
{
function a()
{
}
function foobar()
{
$s = "testing";
$w = new foo();
//Reassign local variables to the class
foreach(get_defined_vars() as $name => $val)
{
$this->$name = $val;
}
//Assign the variable
$w->assign('s');
//test it
echo $w->bar['s'];
}
}
//Testrun
$a = new a();
$a->foobar();
impossible - the max. ammount of information you can get is what you see when dumping
debug_backtrace();
Maybe what you want to do is the other way around, a hackish solution like this works fine:
<?php
function assign($val)
{
global $$val;
echo $$val;
}
$hello = "Some value";
assign('hello');
Ouputs: Some value
What you wish to do, PHP does not intend for. There is no conventional way to accomplish this. In fact, only quite extravagant solutions are available. One that remains as close to PHP as I can think of is creating a new class.
You could call it NamedVariable, or something, and as its constructor it takes the variable name and the value. You'd initiate it as $products = new NamedVariable('products', $productData); then use it as $this->view->assign($products);. Of course, your declaration line is now quite long, you're involving yet another - and quite obscure - class into your code base, and now the assign method has to know about NamedVariable to extract both the variable name and value.
As most other members have answered, you are better off suffering through this slight lack of syntactic sugar. Mind you, another approach would be to create a script that recognizes instances of assign()'s and rewrites the source code. This would now involve some extra step before you ran your code, though, and for PHP that's silly. You might even configure your IDE to automatically populate the assign()'s. Whatever you choose, PHP natively intends no solution.
This solution uses the GLOBALS variable. To solve scope issues, the variable is passed by reference, and the value modified to be unique.
function get_var_name(&$var, $scope=FALSE) {
if($scope) $vals = $scope;
else $vals = $GLOBALS;
$old = $var;
$var = $new = 'unique'.rand().'value';
$vname = FALSE;
foreach ($vals as $key => $val) {
if($val === $new) $vname = $key;
}
$var = $old;
return $vname;
}
$testvar = "name";
echo get_var_name($testvar); // "testvar"
function testfunction() {
$var_in_function = "variable value";
return get_var_name($var_in_function, get_defined_vars());
}
echo testfunction(); // "var_in_function"
class testclass {
public $testproperty;
public function __constructor() {
$this->testproperty = "property value";
}
}
$testobj = new testclass();
echo get_var_name($testobj->testproperty, $testobj); // "testproperty"

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

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
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]);
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!
Array Dereferencing is possible as of PHP 5.4:
http://svn.php.net/viewvc?view=revision&revision=300266
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.
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);
}
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.
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();
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];
}
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
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 :)
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];
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];
}
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 :(
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. ;)
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";
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.
After further research I believe the answer is no, a temporary variable like that is indeed the canonical way to deal with an array returned from a function.
Looks like this will change starting in PHP 5.4.
Also, this answer was originally for this version of the question:
How to avoid temporary variables in PHP when using an array returned from a function
Previously in PHP 5.3 you had to do this:
function returnArray() {
return array(1, 2, 3);
}
$tmp = returnArray();
$ssecondElement = $tmp[1];
Result: 2
As of PHP 5.4 it is possible to dereference an array as follows:
function returnArray() {
return array(1, 2, 3);
}
$secondElement = returnArray()[1];
Result: 2
As of PHP 5.5:
You can even get clever:
echo [1, 2, 3][1];
Result: 2
You can also do the same with strings. It's called string dereferencing:
echo 'PHP'[1];
Result: H
If it is just aesthetic, then the Object notation will work if you return an object. As far as memory management goes, no temporary copy if made, only a change in reference.
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
There are three ways to do the same thing:
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.
A lazy way using current and array_slice:
$first = current(array_slice($foo->getBarArray(),0,1));
$second = current(array_slice($foo->getBarArray(),1,1));
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);
Does this work?
return ($foo->getBarArray())[0];
Otherwise, can you post the getBarArray() function? I don't see why that wouldn't work from what you posted so far.
You could use references:
$ref =& myFunc();
echo $ref['foo'];
That way, you're not really creating a duplicate of the returned array.

Any way to access array directly after method call? [duplicate]

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
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]);
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!
Array Dereferencing is possible as of PHP 5.4:
http://svn.php.net/viewvc?view=revision&revision=300266
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.
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);
}
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.
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();
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];
}
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
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 :)
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];
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];
}
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 :(
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. ;)
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";
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.
After further research I believe the answer is no, a temporary variable like that is indeed the canonical way to deal with an array returned from a function.
Looks like this will change starting in PHP 5.4.
Also, this answer was originally for this version of the question:
How to avoid temporary variables in PHP when using an array returned from a function
Previously in PHP 5.3 you had to do this:
function returnArray() {
return array(1, 2, 3);
}
$tmp = returnArray();
$ssecondElement = $tmp[1];
Result: 2
As of PHP 5.4 it is possible to dereference an array as follows:
function returnArray() {
return array(1, 2, 3);
}
$secondElement = returnArray()[1];
Result: 2
As of PHP 5.5:
You can even get clever:
echo [1, 2, 3][1];
Result: 2
You can also do the same with strings. It's called string dereferencing:
echo 'PHP'[1];
Result: H
If it is just aesthetic, then the Object notation will work if you return an object. As far as memory management goes, no temporary copy if made, only a change in reference.
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
There are three ways to do the same thing:
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.
A lazy way using current and array_slice:
$first = current(array_slice($foo->getBarArray(),0,1));
$second = current(array_slice($foo->getBarArray(),1,1));
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);
Does this work?
return ($foo->getBarArray())[0];
Otherwise, can you post the getBarArray() function? I don't see why that wouldn't work from what you posted so far.
You could use references:
$ref =& myFunc();
echo $ref['foo'];
That way, you're not really creating a duplicate of the returned array.

Categories