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

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.

Related

Function with two outputs

First, let me start by saying i'm a real beginner learning mostly PHP. Understanding the patterns and semantics of programming is more important to me than just learning the syntax. I did some research for what I'm going to ask, but I couldn't find any info about it. So, I was thinking... What if I need to do the following... Give a function multiple outputs to pass in other parts of the code. What is the name of this type of functionality (if it exists)? Or If it doesn't exist, why not? And what is the best practice to achieve the same semantic?
More details:
Let's say I want to call a function with one argument and return not only the value back to that same argument call location, but also in another location or into some other part of the program. Meaning a function with two outputs in two different locations, but the second location wouldn't be a call, just an output from the call made in the first location, returned at the same time with the same value output as the first. So, not calling it twice separately... But rather calling once and outputting twice in different locations. The second output would be used to pass the result into another part of the program and therefore wouldn't be appropriate as a "call/input", but more as an "output" only from the "input" value. How can I achieve multiple outputs in functions?
If this seems like a stupid question, I'm sorry. I couldn't find the info anywhere. Thanks in advance
What you want to do is basically this (i'll make it a 'practical' example):
function add($number1, $number2)
{
$result = $number1 + $number2;
return array('number1' => $number1,'number2' => $number2,'result' => $result);
}
$add = add(5,6); // Returns array('number1' => 5, 'number2' => 6, 'result' => 11);
You now have the two arguments and the result of that function at your disposal to use in other functions.
some_function1($add['result']);
...
some_function2($add['number1']);
If the question is about returning more than one variables, it is simply:
function wtf($foobar = true) {
$var1 = "first";
$var2 = "second";
if($foobar === true) {
return $var2;
}
return $var1;
}
You can either have the function return an array of values:
function foo($bar) {
$bat = 1;
return [$bar, $bat];
}
Or you can pass an argument that tells it which value to return:
function foo($bar, $return_bar=false) {
$bat = 1;
return $return_bar ? $bar : $bat;
}

Good practice for referencing returned array values

This is something I haven't seen before but it appears to be supported and it does work, referencing the returned array key directly after the providing function is called. BUT... is this good practice? Will this be supported in the future? Does this even have a name?
<?php
function example_function() {
$return = array('part_1', 'part_2');
return $return;
}
$var = example_function()[0];
echo $var;
To get the same result I would normally do the following
$var = example_function();
$var = $var[0];
It's called Array Dereferencing. It has been available since PHP 5.4. It is acceptable to use although some might say it reduces readability.
Use it only when you are sure that you will always get array to work on. Sometimes ago I've have following code in some scraper class:
$ip = $this->getIP()[0];
I didn't check whether this function could return string and it caused some logic errors. Nowadays each time when I want to get array's item I do
$ip = $this->getIP()
if(is_array($ip)) {
$ip = $ip[0];
} else {
throw new Exception('Expects array here')
}

How do I use array_filter() for functional programming in PHP?

Say I have an array of tags
$all_tags = array('A', 'B', 'C');
And I want to create a set of URLs with $_GET variables.
I'd like the links to be:
'A' linking to "index.php?x[]=B&x[]=C"
'B' linking to "index.php?x[]=A&x[]=C"
etc. ($_GET is an array with all elements except for "current" element)
(I know there's an easier way to implement this: I'm actually simplifying a more complex situation)
I'd like to use array_filter() to solve this.
Here's my attempt:
function make_get ($tag) { return 'x[]=' . $tag; }
function tag_to_url ($tag_name) {
global $all_tags;
$filta = create_function('$x', 'global $all_tags; return ($x != $tag_name);');
return 'index.php?' . implode('&', array_map("make_get", array_filter($all_tags, "filta")));
}
print_r(array_map("", $all_tags));
But it doesn't work. I have a suspicion that maybe it has to do with how maps and filters in PHP actually mutate the data structure themselves, and return a boolean, instead of using a functional style, where they don't mutate and return a new list.
I am also interested in other ways to make this code more succinct.
Here's an alternative approach:
// The meat of the matter
function get_link($array, $tag) {
$parts = array_reduce($array, function($result, $item) use($tag)
{
if($item != $tag) $result[] = 'x[]='.$tag;
return $result;
});
return implode('&', $parts);
}
// Test driver
$all_tags = array('A', 'B', 'C');
echo get_link($all_tags, 'A');
echo "\n";
echo get_link($all_tags, 'B');
echo "\n";
echo get_link($all_tags, 'C');
echo "\n";
It's simply one call to array_reduce, and then an implode to pull the results together into a query string.
Something approaching real support for functional programming styles in PHP is very, very new--it was only in PHP 5.3 that functions became first class and anonymous functions were possible.
BTW, you should never use create_function(). What it really does is define a new function in the global namespace (which will never be garbage-collected!), and it uses eval() behind the scenes.
If you have PHP 5.3 or greater, you can do this:
$all_tags = array('A', 'B', 'C');
function is_not_equal($a, $b) {
return $a != $b;
}
function array_filter_tagname($alltags, $name) {
$isNotEqualName = function($item) use ($name){
return is_not_equal($item, $name);
};
// array_merge() is ONLY to rekey integer keys sequentially.
// array_filter() preserves keys.
return array_merge(array_filter($alltags, $isNotEqualName));
}
function make_url($arr) {
return 'input.php?'.http_build_query(array('x'=>$arr));
}
$res = array_filter_tagname($all_tags, 'B');
print_r($res);
print_r(make_url($res));
If you have a PHP < 5.3, you should use a class+object for your closures instead of create_function().
class NotEqualName {
protected $otheritem;
function __construct($otheritem) { // with PHP 4, use "function NotEqualName($otheritem) {"
$this->otheritem = $otheritem;
}
function compare($item) {
return $item != $this->otheritem;
}
}
function array_filter_tagname_objectcallback($alltags, $name) {
$isNotEqualName = new NotEqualName($name);
return array_merge(array_filter($alltags, array($isNotEqualName,'compare')));
}
In general, however, PHP is not very well suited to a functional style, and for your particular task using array_filter() is not very idiomatic PHP. array_diff() is a better approach.
Based on an answer I gave in the comments (shown here):
<?php
$all_tags = array('A', 'B', 'C');
function tag_to_url($tag_name)
{
global $all_tags;
$remaining_tags = array_diff($all_tags, array($tag_name));
return sprintf('index.php?%s',
http_build_query(array('x'=>array_values($remaining_tags))));
}
echo tag_to_url('B'); // index.php?x%5B0%5D=A&x%5B1%5D=C
// basically: index.php?x[0]=A&x[1]=C
Basically, use array_diff to remove the entry from the array (instead of filtering), then pass it off to the http_build_query to come up with a valid URL.
I'm just going to answer the "why it doesnt work" part.
$filta = create_function('$x', 'global $all_tags; return ($x != $tag_name);');
The tag_name variable is undefined in your lambda function's scope. Now, it is defined in the creating functions scope(tag_to_url). You can't exactly use the global keyword here either, because $tag_name isn't in the global scope, it is in the local tag_to_url scope. You could declare the variable in the global scope and then it could work, but considering you're fond of functional approaches, I doubt you like global variables :)
You could do trickery with string concatenation and var_export($tag_name) and pass that to create_function() if you wanted, but there's other better ways to achieve your goals.
Also, as an aside, I'm guessing you might benefit from turning up php's error reporting level while developing. php would have thrown undefined variable notices at you, which helps debugging and understanding.
// ideally set these in php.ini instead of in the script
error_reporting(E_ALL);
ini_set('display_errors', 1);

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.

PHP: Variable in a function name

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)

Categories