do array() destroy all previous values? - php

I have an $array with some values stored on it. Now, if I do :
$array=array();
all values/index are deleted? Or I need to use unset() before it?

A new array is being created with array() and this new array object is assigned to the variable $array.
The variable ($array) no longer points to the original array object -- and because PHP is a garbage collected language -- the original array object will be eligible for reclamation if (and only if) it is no longer strongly reachable from a root object. (The actual time the previous array object and objects it contained are actually deleted depends on other factors.)
Happy coding.
See PHP Garbage Collection Manual for more details -- PHP uses a hybrid GC (ref-count and cycle-breaking).

Yes the reassignment just wipes out all the data from the array. But to get clear understanding of the garbage collection please check the PHP Reference Counting Basics.

$array = array('apples', 'oranges', 'bananas');
print_r($array);
//Array ( [0] => apples [1] => oranges [2] => bananas )
$array = array();
print_r($array);
//Array ( )

Your intent would be clearer if you used something like
$array = null;
(and even clearer if you used a better name than $array!)

Related

PHP: Storing arrays within an array seems to be creating copies

This is such a basic question, but I'm unable to find a clear answer anywhere. As I have understood it, storing an object in an array should store a reference, not a copy... so any changes you make to the object subsequently should be visible when you access the object via the array.
When searching this topic, I've run across many questions asking how to store copies of objects in an array, so that this doesn't happen, and the answer is always that you need to use clone. To me, this would SEEM to indicate that by default a reference would be stored.
So I was really confused when I encountered the following behavior...
$inner = ['key1'=>"value1"];
$outer = [];
$outer['inner'] = $inner;
$inner['key2'] = "value2";
print_r($inner);
echo "<br>";
print_r($outer['inner']);
OUTPUT:
Array
(
[key1] => value1
[key2] => value2
)
Array
(
[key1] => value1
)
I've been doing pretty serious PHP coding for 2 years now, and this seems to go against everything I thought I knew about arrays, so it's really tripping me up.
Similar questions on Stack Exchange tend to get answers saying "you should refer to the documentation". But nothing I can find in the docs address this clearly.
You're just assigning the value of $inner at that time to $outer['inner']. After that, $outer['inner'] is its own array, it doesn't maintain a reference to $inner. This is expected behaviour with arrays.
From the PHP documentation on arrays:
Array assignment always involves value copying. Use the reference operator to copy an array by reference.
So if you want to maintain a reference, you need to use the reference operator:
// Set the original values
$inner = ['key1' => 'value1'];
// Assign by reference
$outer = [];
$outer['inner'] = &$inner;
// Modify the original array afterwards
$inner['key2'] = 'value2';
You will then find that $outer['inner'] maintains the reference to $inner, even though it was changed after the assignment.
print_r($inner);
print_r($outer['inner']);
They will be the same:
Array ( [key1] => value1 [key2] => value2 )
Array ( [key1] => value1 [key2] => value2 )
Note: Using references is generally not a good idea and I can't remember ever really needing them. There is a good discussion on Stack Overflow about this already.

PHP API returns an array - need to reuse it in variables

I have a PHP script that dumps data from an API.
The dump is an array
print_r($answer);
outputs
Array ( [success] => 1 [serial] => s001 [url] => http://gooole.com )
I want to have another variable called $url that holds the value url from the array (held in $answer) in PHP.
I'm unfamiliar with this.
check out extract() it will take the keys from an array, and create variable of the same name to store them in. There are a few flags you can pass it, to determine exactly what it does with things like pre-existing variables of the same name.
EDIT: as mentioned in the comments on your question, though, $url = $answer['url']; is probably the simplest way to go.

PHP array of unknown length with 0 as initial value

I have PHP $_SESSION arrays that have an undefined amount of elements. Is it possible to initialise all the values to 0, or do I have to check whether the value is NULL and then set to 0 every time I check a value?
Edit: I'm sorry for the vagueness of my question.
I have an undefined amount of levels, and I'd like to store all the scores of each level in that array. Currently my amount of levels is fixed, so I am currently just writing:
$_SESSION['totals'] = array(0,0,0,0,0);
And then when adding manipulating the data, I simply increment/add a certain amount to that element.
Now I'd prefer to have the same ease of directly incrementing/adding values to certain elements without needing to check whether a value is NULL or something like that...
Edit 2: edited my code as follows:
$_SESSION['totals'] = array();
if(array_key_exists($row['level']-1,$_SESSION['totals'])){
$_SESSION['totals'][$row['level']-1]++;
}else{
$_SESSION['totals'][$row['level']-1] = 1;
}
And it seems to work. Thanks fellas!
You can use array_fill_keys function to fill an array with specified value for defined keys:
$keys = array('foo', 'bar', 'baz');
$output = array_fill_keys($keys, 0);
Defining an array with initial values is defining an array with a length. This does not prevent you from adding or removing elements from the array:
// initial array
$myArray = [0, 0, 0, 0];
print_r($myArray); // would output Array ( [0] => 0 [1] => 0 [2] => 0 [3] => 0)
$myArray[] = 1;
print_r($myArray); // would output Array ( [0] => 0 [1] => 0 [2] => 0 [3] => 0 [4] => 1 )
$_SESSION contains only what you put into it. Just make sure you add 0 instead of null the first time you add something.
If you need to do this later, I think your design might be bad. But anyway, $_SESSION is like a normal array, so you can just use PHP's array function to traverse the array and check or change each value.
PHP arrays aren't really arrays you might know from other languages. They really are more like linked lists with hash access.
What this means is: You either know all the string array indices you want to use, and either make sure they exist, or you check their existence every time you access them which might fail.
For numeric indices, the same thing applies. You might have an array with indices 1, 2 and 4 present, but if you run over it with only a for loop, you will trigger a notice when accessing the nonexistant element 3.
Use foreach loops whenever you want to iterate arrays. Check with isset() whenever you want to document that the array value might not be present. Don't do it if you know or assume that the array element MUST be present - if not, you get the notice as a reminder that your code is working on a data structure that is NOT what you thought it is. Which actually is a good thing. Then fix it. :)
Your best bet would be to abstract your session stuff by creating facade methods, or getters and setters around the session variables rather than access them directly. This way you can return a default value if the one you're after doesn't exist.
I've used array_key_exists() to check if the index is set. If it is not, I display 0 or add store a certain value in that field, else I show the value of that index or add certain value to that field.
Credit to Sven for bringing that up.
to check what u have in your sessions, loop tru it. not sure if this is what u are asking.
foreach($_SESSION as $x=>$y)
{
if(empty($x)) { //do something }
}

Why does the sort order of multidimensional child arrays revert as soon as foreach loop used for sorting ends?

I have a very strange array sorting related problem in PHP that is driving me completely crazy. I have googled for hours, and still NOTHING indicates that other people have this problem, or that this should happen to begin with, so a solution to this mystery would be GREATLY appreciated!
To describe the problem/question in as few words as possible: When sorting an array based on values inside a multiple levels deeply nested array, using a foreach loop, the resulting array sort order reverts as soon as execution leaves the loop, even though it works fine inside the loop. Why is this, and how do I work around it?
Here is sample code for my problem, which should hopefully be a little more clear than the sentence above:
$top_level_array = array('key_1' => array('sub_array' => array('sub_sub_array_1' => array(1),
'sub_sub_array_2' => array(3),
'sub_sub_array_3' => array(2)
)
)
);
function mycmp($arr_1, $arr_2)
{
if ($arr_1[0] == $arr_2[0])
{
return 0;
}
return ($arr_1[0] < $arr_2[0]) ? -1 : 1;
}
foreach($top_level_array as $current_top_level_member)
{
//This loop will only have one iteration, but never mind that...
print("Inside loop before sort operation:\n\n");
print_r($current_top_level_member['sub_array']);
uasort($current_top_level_member['sub_array'], 'mycmp');
print("\nInside loop after sort operation:\n\n");
print_r($current_top_level_member['sub_array']);
}
print("\nOutside of loop (i.e. after all sort operations finished):\n\n");
print_r($top_level_array);
The output of this is as follows:
Inside loop before sort operation:
Array
(
[sub_sub_array_1] => Array
(
[0] => 1
)
[sub_sub_array_2] => Array
(
[0] => 3
)
[sub_sub_array_3] => Array
(
[0] => 2
)
)
Inside loop after sort operation:
Array
(
[sub_sub_array_1] => Array
(
[0] => 1
)
[sub_sub_array_3] => Array
(
[0] => 2
)
[sub_sub_array_2] => Array
(
[0] => 3
)
)
Outside of loop (i.e. after all sort operations finished):
Array
(
[key_1] => Array
(
[sub_array] => Array
(
[sub_sub_array_1] => Array
(
[0] => 1
)
[sub_sub_array_2] => Array
(
[0] => 3
)
[sub_sub_array_3] => Array
(
[0] => 2
)
)
)
)
As you can see, the sort order is "wrong" (i.e. not ordered by the desired value in the innermost array) before the sort operation inside the loop (as expected), then is becomes "correct" after the sort operation inside the loop (as expected).
So far so good.
But THEN, once we're outside the loop again, all of a sudden the order has reverted to its original state, as if the sort loop didn't execute at all?!?
How come this happens, and how will I ever be able to sort this array in the desired way then?
I was under the impression that neither foreach loops nor the uasort() function operated on separate instances of the items in question (but rather on references, i.e. in place), but the result above seems to indicate otherwise? And if so, how will I ever be able to perform the desired sort operation?
(and WHY doesn't anyone else than me on the entire internet seem to have this problem?)
PS.
Never mind the reason behind the design of the strange array to be sorted in this example, it is of course only a simplified PoC of a real problem in much more complex code.
Your problem is a misunderstanding of how PHP provides your "value" in the foreach construct.
foreach($top_level_array as $current_top_level_member)
The variable $current_top_level_member is a copy of the value in the array, not a reference to inside the $top_level_array. Therefore all your work happens on the copy and is discarded after the loop completes. (Actually it is in the $current_top_level_member variable, but $top_level_array never sees the changes.)
You want a reference instead:
foreach($top_level_array as $key => $value)
{
$current_top_level_member =& $top_level_array[$key];
EDIT:
You can also use the foreach by reference notation (hat tip to air4x) to avoid the extra assignment. Note that if you are working with an array of Objects, they are already passed by reference.
foreach($top_level_array as &$current_top_level_member)
To answer you question as to why PHP defaults to a copy instead of a reference, it's simply because of the rules of the language. Scalar values and arrays are assigned by value, unless the & prefix is used, and objects are always assigned by reference (as of PHP 5). And that is likely due to a general consensus that it's generally better to work with copies of everything expect objects. BUT--it is not slow like you might expect. PHP uses a lazy copy called copy on write, where it is really a read-only reference. On the first write, the copy is made.
PHP uses a lazy-copy mechanism (also called copy-on-write) that does
not actually create a copy of a variable until it is modified.
Source: http://www.thedeveloperday.com/php-lazy-copy/
You can add & before $current_top_level_member and use it as reference to the variable in the original array. Then you would be making changes to the original array.
foreach ($top_level_array as &$current_top_level_member) {

Can we do like this using PHP SESSION array?

Hi can we create two dimensional array using php session. If possible how to unset values randomly.
No, PHP does not implement multi-dimensional arrays. However an element of an array can be an array itself. And any PHP data item can be stored in the session (however resources become meaningless outisde the thread they were initialized in, and objects require class definitions to be referenced from the session).
e.g.
<?php
$two_d=array(
array(1,2,3),
array(4,5,6),
array(7,8,9),
array('#','.','=')
);
$two_d[3][2]='*'; // was '='
how to unset values randomly
This would be an oxymoron in a 2-dimensional array. But is perfectly valid in the context of an array of arrays:
unset($two_d[1]); // removed the whole second row from the above
unset($two_d[0][1]); // $two_d[0] is now array(1,3)
$_SESSION['whateverValue'] = Array(
1 => Array (
'a','b','c','d'
),
2 => Array (
'q','w','e','r','t'
)
);
Voila, a two-dimensional array, in a session.
The session variables are in no way special while the script is executing. Their only "magic" is that they are unserialized at session_start() and serialized at session_close()

Categories