the array_push(mainArr, subAssociativeArr) does not work when it is inside a function. I need some help with this code:
$store=array();
$samsung=array('id'=>'10','name'=>'samsung');
$sony=array('id'=>'11','name'=>'sony');
function addOne($store, $element){
array_push($store, $element);
}
addOne($store, $samsung);
var_dump($store); //output: empty array
however it works fine if without function; like the following:
$store=array();
$samsung=array('id'=>'10','name'=>'samsung');
$sony=array('id'=>'11','name'=>'sony');
array_push($store, $samsung);
var_dump($store); //output: array is added
so, what is the problem???
You forgot to return
function addOne($store, $element){
$store[]=$element;
return $store;
}
$store = addOne($store, $samsung);
You could also pass by reference if you want to (which is more in line with the code you have):
function addOne(&$store, $element){
$store[]=$element;
}
addOne($store, $samsung);
Note the &. Instead of copying the inputs, this is more like a pointer to the original variable, so you can update it directly. Ether way is fine here, it's a matter of developers choice really. For example it can be very easy to mix the two:
//Don't do this
function addOne(&$store, $element){ //returns null
$store[]=$element;
}
$store = addOne($store, $samsung); //sets $store to null
Which you probably don't want to do, so I can see an argument for both ways. Unless you have super big array, it probably doesn't matter much. It's very easy to forget that a random function is pass by reference.
So use whatever method makes more sense to you.
P.S. - I refuse to use array_push, it's ugly and I don't like it :). Doing $store[]=$element; is the same as array_push($store,$element), except it avoids an unnecessary function call.
Cheers.
When it's in a function, you have a different scope. While the parameters to your addOne function have the same name, they are actually copies of the variables passed, not references to them.
So when you array_push() in a function, you're only affecting the variables in that function's scope, not the outer scope.
You can either return $store, or pass the variables by reference.
If you want it to work within a function you need a reference to the variable. A reference in PHP is defined as & and they are similar to "pointers" in C or C++.
Try this:
function addOne(&$store, $element){
array_push($store, $element);
}
addOne($store, $samsung);
A PHP reference is an alias, which allows two different variables to write to the same value. As of PHP 5, an object variable doesn't contain the object itself as value anymore. It only contains an object identifier which allows object accessors to find the actual object. When an object is sent by argument, returned or assigned to another variable, the different variables are not aliases: they hold a copy of the identifier, which points to the same object.
http://www.php.net/manual/en/language.oop5.references.php
Related
Bear with me, I'm learning.
I often see snippets like the one below:
<?p
$imageArray = get_field('image_field');
$imageAlt = $imageArray['alt'];
$imageURL = $imageArray['url'];
?>
It is pedagogical and clear and organized. But is it necessary to get the entire array before querying the array for values? Can I not define the variable in just a single line? Something like the below (which doesn't work, neither the other variants I have tried):
$imageAlt = get_field('image_field', ['alt']);
$imageURL = get_field('image_field', ['url']);
Yes, you can.
As of PHP 5.4 it is possible to array dereference the result of a function or method call directly. Before it was only possible using a temporary variable. - Source
$imageAlt = get_field('image_field')['alt'];
https://eval.in/548036
The question you are asking can be answered by asking 2 questions:
Is it doable ?
Is it a good idea to do it that way ?
Is it doable ?
Yes! You do not have to store the array in a variable and re-use it later.
For instance, you could do:
$imageAlt = get_field('image_field')['alt'];
Note: This will work in PHP 5.4+ and is called: Array dereferencing.
But that is not the only consideration...
Is it a good idea to do it that way ?
No. It's not a good idea in many cases. The get_field() function, depending on your context, is probably doing a lot of work and, each time you call it, the same work is don multiple times.
Let's say you use the count() function. It will count the number of items in an array. To do that, it must iterate through all items to get the value.
If you use the count() function each time you need to validate number of items in an array, you are doing the task of counting each and every time. If you have 10 items in your array, you probably won't notice. But if you have thousands of items in your array, this may cause a delay problem to compute your code (a.k.a. it will be slow).
That is why you would want to do something like: $count = count($myArray); and use a variable instead of calling the function.
The same applies to your question.
While PHP 5.4+ allows you to directly dereference a function return value like this:
get_field('image_field')['alt']
...in this particular case I would not suggest you do so, since you're using two values from the resulting array. A function call has a certain overhead just in itself, and additionally you don't know what the function does behind the scenes before it returns a result. If you call the function twice, you may incur a ton of unnecessary work, where a single function call would have done just as well.
This is not to mention keeping your code DRY; if you need to change the particulars of the function call, you now need to change it twice...
PHP allows you to play around quite a bit:
function foo(){
return array('foo' => 1, 'bar' => 2);
}
Option 1
echo foo()['foo']; // 1
# Better do this if you plan to reuse the array value.
echo ($tmp = foo())['foo']; // 1
echo $tmp['bar']; // 2
It is not recommended to call a function that returns an array, to specifically fetch 1 key and on the next line doing the same thing.
So it is better to store the result of the function in a variable so you can use it afterwards.
Option 2
list($foo, $bar) = array_values(foo());
#foo is the first element of the array, and sets in $foo.
#bar is the second element, and will be set in $bar.
#This behavior is in PHP 7, previously it was ordered from right to left.
echo $foo, $bar; // 12
Option 3
extract(foo()); // Creates variable from the array keys.
echo $foo, $bar;
extract(get_field('image_field'));
echo $alt, $url;
Find more information on the list constructor and extract function.
As I understand, when you pass a variable to a function, and if you don't use reference sign (&) , it means any changes inside your function will not affect to your variable outside the function. In other words, it means the compiler will make a copy of the outside variable to use inside function, doesn't it?
But when I run these testing code, it does not happen like that.
Can anyone explain me what I miss here? Thank you
My test code: the expected result should be 3, but it becomes 1?
function test($arr2) {
foreach($arr2 as &$item) {
$item = 1;
}
}
$arr = array(2);
foreach($arr as &$item2) {
$item2 = 3;
}
test($arr);
print_r($arr);
This issue has been solved a few times before you've asked this (#1). The issue is due to the fact that:
Reference of a $value and the last array element remain even after the
foreach loop. It is recommended to destroy it by unset().
Reference: PHP foreach()
You need to unset the last $item2 after your foreach:
foreach ($arr as &$item2) {
$item2 = 3;
}
unset($item2);
This is quite interesting, it seems like the behavior of array are the same as objects in php in which new array still holds the copy of the members identifier (which points to the same value as the array it was copied from).
As of PHP 5, an object variable doesn't contain the object itself as value anymore. It only contains an object identifier which allows object accessors to find the actual object. When an object is sent by argument, returned or assigned to another variable, the different variables are not aliases: they hold a copy of the identifier, which points to the same object.
PHP Manual - Objects and references
Even though you are not passing $arr as Reference variable, you are still accessing $arr elements as References in function test(). So anything that changes in function will effect outside function too.
If you are looking to change $arr ( which has been passed as $arr2 in test function ) only in test function, then remove &from $item
$youtubes = array("lNT4H39G2rw","pF2_qvdm8DQ","_8ytwhhJwco","K16ZRFWR2Mc","9WuPxe7zc6Q","rXZIIclPnd0","J8ZwyN6E3_Q","OEWJbsh0z-4","o62-X0stdFM","aIIiww2Neq0","5TJc-VbNYg0","MYQa1Tgw_z8","alxzFm-bqug","UmI7oyllrlY","RGKFXDHFmn4");
function randomFromArray($data) {
global $$data;
echo $$data[rand(0,count($youtubes)-1)];
}
randomFromArray("youtubes");
I am trying to get this to work as a function, so I can enter the array name as a parameter. It is then supposed to echo a random entry from the array. The bit where it gets the random entry from array works on its own if I substitute it straight in, but I can't seem to get it working as a function.
Any help?
You're using the variable name $youtubes in your randomFromArray function in the call to count (but the variable is not available under that name there).
Btw., why don't you pass in (a reference to) the array instead of its name? Would be much tidier than using global $$data; The following code uses a reference to avoid copying the array (but remember that then, the outside array could be changed from inside the method):
$youtubes = // ...
function randomFromArray(&$data) {
echo $data[rand(0,count($data)-1)];
}
randomFromArray($youtubes);
dont call the function randomFromArray("youtubes"); in this way you call the function with youtubes parametar like a string. and inside the function itself you dont have a $youtubes variable. call the function like this randomFromArray($youtubes);
hope this would help
You are passing the string 'youtubes' into the function, not the array. You want to pass in the name of the array:
randomFromArray($youtubes);
$youtubes = array("lNT4H39G2rw","pF2_qvdm8DQ","_8ytwhhJwco","K16ZRFWR2Mc","9WuPxe7zc6Q","rXZIIclPnd0","J8ZwyN6E3_Q","OEWJbsh0z-4","o62-X0stdFM","aIIiww2Neq0","5TJc-VbNYg0","MYQa1Tgw_z8","alxzFm-bqug","UmI7oyllrlY","RGKFXDHFmn4");
function randomFromArray($data) {
echo $data[rand(0,count($data)-1)];
}
randomFromArray($youtubes);
There are some things fundamentally wrong here.
global $$data
Why is there a double $ sign? And where would this data be coming from?
echo $$data[rand(0,count($youtubes)-1)];
Your function doesn't know the variable $youtubes, since you have never defined it inside of the function. All your function knows is the $data variable that you are passing to it.
randomFromArray("youtubes"); You are passing a string to your function, rather then your array. You probably want this instead:
randomFromArray($youtubes); // Pointing to your actual array, rather then a string
Try reading up on PHP functions first before attempting to use them as you're lacking a lot of basic knowledge about them.
After you put a ; after global $$data, you can try this: $f = $$data; and then echo $f[rand(..)]; if you really want to use names instead variables as others suggested. And if you do that you can use the string (or $f) further in the function code.
I know that prepending a '&' to your PHP variable sets up a reference to the original variable instead of copying its value like so:
$original = 'apples';
$secondary = &$original;
$original = 'oranges';
echo $secondary; // 'oranges'
If it works this way, why not just use the original variable then?
Passing by reference is useful and necessary when passing a variable as a parameter to a function, expecting that variable to be modified without a copy being created in memory. Many of PHP's native array_*() functions operate on array references, for example.
This function, for example, receives an array reference and appends an element onto the original array. If this was done without the & reference, a new array copy would be created in scope of the function. It would then have to be returned and reassigned to be used.
function add_to_an_array(&$array)
{
// Append a value to the array
$array[] = 'another value';
}
$array = array('one', 'two', 'three');
add_to_an_array($array);
print_r($array);
Array
(
[0] => one
[1] => two
[2] => three
[3] => another value
)
$original = 'apples';
function foo($word) {
$word = 'oranges';
}
foo($original);
echo $original; // apples, because only local $word was changed, not $original.
foo(&$original);
echo $original; // oranges, because $original and $word are the same
Pass by reference is really a cop out and goes against good encapsulation. If you need to manipulate a variable in that way, it probably should belong to a class as a member variable and then does not need to be passed to the function. Good OO design would usually make member variables immutable with a "final" keyword, but PHP doesn't have this. It's not intuitive that passing a variable to a function might change it's value which is why it should be avoided in most cases.
Also going to a more full OO design prevents you have having method signatures that are long and complex with many optional parameters that are difficult to re-factor.
A more interesting use of the is when it's used in the formal argument to a function
foo($a);
...
function foo (&$a) {
....
}
this allows you to modify a in the function.
There are many uses for references.
You can pass a reference to a variable to a function so you can change the value inside the function
You can use references to create linked lists
etc...
Just keep in mind that they're there, and you'll surely find an application for them when the time comes and you face a problem that can be solved with references.
Check out the following article for other ideas and uses of references:
http://www.elated.com/articles/php-references/
So, I need the actual variable name "varName" from global space. This function is actually a method inside a class.
Code is arbitrary for simplicity
$varName = 'what ever';
public function save($var)
{
$i[varName goes here] = $var;
}
I don't know if this is even possible, but I think maybe with a callback?
If it's a global variable, you might be able to find out the original name with:
$varname = array_search($var, $GLOBALS);
But that's not overly reliable; a best guess. If two global variables would contain the same value, you would just receive the name of either of them.
Read about $GLOBALS variable in the documentation.
This is probably what you need. Depending on the way you determine which variable you need, you can for example user array_search() to find the proper name based on the value.
Caution: $GLOBALS is about global scope's variables.
EDIT:
But this would be still a guess. You may try the following method to determine the name of the passed variable with ~100% certainty:
Pass variable to the method with reference.
Use array_search() for finding the name of the variable. If only one key matches it, you have your name. If not, go to the next step.
Save the initial value of the variable and save the list of positions at which you have found matching elements.
Change the variable's value into new one. Perform another search based on new value and get positions that are also in the list of positions from point no. 3.
At this point you have probably found the name of the variable you are looking for.
But...
Is it really needed? I suggest that you should look for simpler solution, some better encapsulation of your code.
Ps. array_search() actually returns no more than one key (see documentation). You should know that and make searching for multiple results a little more sophisticated to not skip the correct one if more than one variable matches your search criteria. (EDIT2: As mario suggested, array_intersect($GLOBALS, array($var)) will suffice)
In C, you would use a macro. I don't think there's an equivalent in PHP.
You could pass the name of the variable to the function as a string, then in the function get the variable's value from GLOBALS or eval it.
Thanks for the solution!
Here is my test:
<?php
$varName = 'what ever';
function save($var)
{
$i[array_search($var, $GLOBALS)] = $var;
print_r($i);
}
save($varName);
?>
prints:
Array
(
[varName] => what ever
)