Using arrays by reference - php

Why is the following code "crashing" in PHP?
$normal_array = array();
$array_of_arrayrefs = array( &$normal_array );
end( $array_of_arrayrefs )["one"] = 1; // choking on this one
The expected result is that the final code line appends $normal_array with key one having value 1 but there is no output what so ever, not even prints preceeding this code. In the real context of this scenario I use end() function to always append to the last array reference.

This doesn't crash, it just contains a syntax error:
end( $array_of_arrayrefs )["one"] = 1;
Unfortunately, you cannot treat function return values as arrays in PHP. You have to assign the value explicitly. Unfortunately, this doesn't work here because end makes a copy of the returned value.

Related

How to use string values from one array as indexes for another array in PHP

I've splitted a string into array, giving a delimitator. So, this new array created, will contain values that I would want to use as indexes for another given array.
Having a situation like this:
// my given array
$array['key1']['key2']['a_given_key']['some_other_given_key'] = 'blablabl';
// the value of my given array
$value = $array['key1']['key2']['a_given_key']['some_other_given_key'];
$string = "key1;key2";
$keys = explode(";", $string);
I want to call dinamically (during the execution of my PHP script) the value of the given array, but, using as indexes all the values of the array $keys, and in addition appending the indexes ['a_given_key']['some_other_given_key'] of my given array.
I hope I have been clear.
Many thanks.
To make it work you have to use references. Below code should work as you expect:
<?php
$string = "key1;key2;key3;key4";
$keys = explode(";", $string);
$array['key1']['key2']['key3']['key4']['a_given_key']['some_other_given_key'] = 'blablabl';
$ref = & $array;
for ($i=0, $c = count($keys); $i<$c ; ++$i) {
$ref = &$ref[$keys[$i]];
}
echo $ref['a_given_key']['some_other_given_key'];
$value = $ref['a_given_key']['some_other_given_key'];
echo $value;
?>
I would like to add that just after using reference you should unset it using:
unset($ref);
If you don't do this and many lines later you run for example $ref = 2; it will modify your source array so you have to remember about unsetting references just after it's no longer in use.

How does PHP determine whether a variable is an array or a string?

I'm confused as to how PHP determines whether a variable is a string or an array. It seems to depend on the operators being used.
Here's an example:
<?php
$z1 = "abc";
$out = "";
for ($i = 0; $i < strlen($z1); $i++)
{
// $out[$i] = $z1[$i];
$out = $out.$z1[$i];
}
print $out;
?>
In the above version $out becomes a string (print $z1 shows "abc"). However, if I use the first line $out[$i] = $z1[$i];, $out becomes an array.
Can someone please clarify why this happens, and if its possible to access a string's characters with square brackets without converting the output to an array?
The definition of a string in PHP is considered a set of data writen in linear format (i.e: $var = "username=SmokeyBear05,B-day=01/01/1980";)
An array however is a set of data broken down into several parts. A sort of list format if you will. As an example I've written the data string from before, into an array format...
Array(['username']=>"SmokeyBear05", ['B-day']=>"01/01/1980")
Now strings are generally defined as such: $var="Your String";
Arrays however can be written in three different formats:
$var1 = array('data1','data2','data3');
$var2 = array('part A'=>'data1','part B'=>'data2','part C'=>'data3');
The output of var1 starts the index value at 0. The output of var2 however, sets a custom index value. Now the third way to write an array (least common format) is as such:
$var[0]="data1";
$var[1]="data2";
$var[2]="data3";
This takes more work, but allows you to set the index.
Most web developers working with PHP will set data from an external source as a string to deliver it to another PHP script, and then break it down into an array using the explode() function.
When you define variable $out = "", for loop doesn't understand this variable as string value. If you set $out[$i] value, by default, it was treated as an array.
If you want to get the output result as string value, you can define $out = "a" to make sure it's a string variable.

Getting element from PHP array returned by function

I'm not sure if this is possible, but I can't figure out how to do it if it is...
I want to get a specific element out of an array that is returned by a function, without first passing it into an array... like this...
$item = getSomeArray()[1];
function getSomeArray(){
$ret = Array();
$ret[0] = 0;
$ret[1] = 100;
return $ret;
}
What's the correct syntax for this?
PHP cannot do this yet, it's a well-known limitation. You have every right to be wondering "are you kidding me?". Sorry.
If you don't mind generating an E_STRICT warning you can always pull out the first and last elements of an array with reset and end respectively -- this means that you can also pull out any element since array_slice can arrange for the one you want to remain first or last, but that's perhaps taking things too far.
But despair not: the (at this time upcoming) PHP 5.4 release will include exactly this feature (under the name array dereferencing).
Update: I just thought of another technique which would work. There's probably good reason that I 've never used this or seen it used, but technically it does the job.
// To pull out Nth item of array:
list($item) = array_slice(getSomeArray(), N - 1, 1);
PHP 5.4 has added Array Dereferencing,
here's the example from PHP's Array documentation:
Example #7 Array dereferencing
function getArray() {
return ['a', 'b', 'c'];
}
// PHP 5.4
$secondElement = getArray()[0]; // output = a
// Previously
$tmp = getArray();
$secondElement = $tmp[0]; // output = a
The syntax you're referring to is known as function array dereferencing. It's not yet implemented and there's an RFC for it.
The generally accepted syntax is to assign the return value of the function to an array and access the value from that with the $array[1]syntax.
That said, however you could also pass the key you want as an argument to your function.
function getSomeArray( $key = null ) {
$array = array(
0 => "cheddar",
1 => "wensleydale"
);
return is_null($key) ? $array : isset( $array[$key] ) ? $array[$key] : false;
}
echo getSomeArray(0); // only key 0
echo getSomeArray(); // entire array
Yes, php can't do that. Bat you can use ArrayObect, like so:
$item = getSomeArray()->{1};
// Credits for curly braces for Bracketworks
function getSomeArray(){
$ret = Array();
$ret[0] = 0;
$ret[1] = 100;
return new ArrayObject($ret, ArrayObject::ARRAY_AS_PROPS);
}
Okay, maybe not working with numeric keys, but i'm not sure.
I know this is an old question, but, in your example, you could also use array_pop() to get the last element of the array, (or array_shift() to get the first).
<?php
$item = array_pop(getSomeArray());
function getSomeArray(){
$ret = Array();
$ret[0] = 0;
$ret[1] = 100;
return $ret;
}
As the others says, there is no direct way to do this, I usually just assign it to a variable like so:
$items = getSomeArray();
$item = $items[1];
function getSomeArray(){
$ret = Array();
$ret[0] = 0;
$ret[1] = 100;
return $ret;
}
I am fairly certain that is not possible to do in PHP. You have to assign the returned array to another array before you can access the elements within or use it directly in some other function that will iterate though the returned array (i.e. var_dump(getSomeArray()) ).

PHP variables: references or copies

I'm confused about how PHP variable references work. In the examples below, I want to be able to access the string hello either as $bar[0] or $barstack[0][0]. It would seem that passing the array by reference in step 1 should be sufficient.
The second example does not work. $foostack[0]0] is the string hello, but $foo[0] doesn't exist. At some point, the first element of $foostack becomes a copy of $foo, instead of a reference.
The problem lies in the first line of step 2: When I push a reference on, I expect to pop a reference off. But array_pop returns a copy instead.
Others have told me that if I have to worry about references and copies, then PHP is not the right language for me. That might be the best answer I'm going to get.
FWIW, in order for var_dump to be useful, it needs to display some property that distinguishes between a reference and a copy. It does not. Maybe there's another function?
My first PHP project seems to be going badly. Can someone help shed some light on the
problems with this code?
<?php
echo "// This works!\n<br />" ;
// step 1
$bar = array() ;
$barstack = array( &$bar ) ;
// step 2
array_push( $barstack[0], 'hello' ) ;
// results
echo count( $barstack[0] ) .';' .count( $bar ) ;
echo "\n<br />// This doesn't :(\n<br />" ;
// step 1
$foo = array() ;
$foostack = array( &$foo ) ;
// step 2
$last = array_pop( $foostack ) ;
array_push( $last, 'hello' ) ;
array_push( $foostack, &$last ) ;
// results
echo count( $foostack[0] ) .';' .count( $foo ) ;
echo "\n<br />// Version:\n<br />" ;
echo phpversion() ."\n" ;
?>
The results can be viewed at the following URL:
http://www.gostorageone.com/tqis/hi.php
Version is 4.3.10. Upgrading the server is not practical.
Desired outcomes:
Explain the obvious if I've overlooked it
Is this a bug? Any workarounds?
Thanks!
-Jim
Your code works fine, there is no bug, and it is independent to PHP 4 or 5. Maybe it helps if this is simply explained to you.
Let's go through the example which does not work in your eyes, just looking what actually happens:
// step 1
$foo = array(); # 1.
$foostack = array( &$foo ); # 2.
1.: You initialize the variable $foo to an empty array.
2.: You initialize the variable $foostack to an array and the first element of the array is an alias of the variable $foo. This is exactly the same as writing: $foostack[] =& $foo;
On to the next step:
// step 2
$last = array_pop($foostack); # 3.
array_push($last, 'hello'); # 4.
array_push($foostack, &$last); # 5.
3.: You assign the last element's value of the array $foostack to $last and you remove the last element from the array $foostack. Note: array_pop returns a value, not a reference.
4.: You add 'hello' as a new element to an empty array in $last.
5.: You add &$last as a new element to $foostack;
So which variables do we have now?
First of all $foo which just contains an empty array. The last element of $foostack was once reference to it (2.), but you have removed that directly after (3.). As $foo and it's value has not been changed any longer, it's just an empty array array().
Then there is $last, which got an empty array in 3.. That's just an empty array, it's a value not a reference. In (4.) you add the string 'hello' as first element to it. $last is an array with one string element in there.
Then there is $foostack. It's an array that get's a reference to $foo in (2.), then that reference is removed in (3.). Finally an alias to $last is added to it.
This is exactly what the rest of your code outputs:
echo count($foostack[0]) .';'. count($foo);
$foostack[0] is the alias to $last - the array with the string 'hello' as only element, while $foo is just $foo, the empty array array().
It makes no difference if you execute that with PHP 4 or 5.
As you write that's "wrong", I assume you were just not able to achieve what you wanted. You're probably looking for a function that is able to return the reference to the last element of an array before removing it. Let's call that function array_pop_ref():
// step 1
$foo = array();
$foostack = array( &$foo );
// step 2
$last =& array_pop_ref($foostack);
array_push($last, 'hello');
array_push($foostack, &$last);
// results
echo count($foostack[0]) .';' .count($foo); # 1;1
The array_pop_ref function:
function &array_pop_ref(&$array)
{
$result = NULL;
if (!is_array($array)) return $result;
$keys = array_keys($array);
$end = end($keys);
if (false === $end) return $result;
$result =& $array[$end];
array_pop($array);
return $result;
}

Can I generate an array based on url path?

I have a path like:
/blog/2/post/45/comment/24
Can I have an array depends on what I have on url, like :
$arr = array('blog'=>'2','post'=>'45','comment'=>'24');
But it should depend on variable passed:
/blog/2 should produce $arr = array('blog'=>'2');
Is this possible to create dynamic array?
You could try something like this:
function path2hash($path) {
// $path contains whatever you want to split
$chunks = explode('/', $path);
$result = array();
for ($i = 0; $i < sizeof($chunks) - 1; $i+=2)
$result[$chunks[$i]] = $chunks[$i+1];
return $result;
}
You could then use parse_url to extract the path, and this function to turn it into the desired hash.
First use $_SERVER['REQUEST_URI'] to find the current path.
now, you can use explode and other string functions to produce the array...
If you need a working example, Ill try and post one.
EDIT:
$path=explode('/',$path);
$arr=array(
$path[0]=>$path[1],
$path[1]=>$path[2]);
or don't know how long it is...
$arr=array();
for ($i=0; $i+1<count($path);i+=2)
$arr[$path[$i]]=$path[$i+1];
Here's a simple example trying to solve the issue. This will put the arguments in the "arguments" array, and will contain each combination of key/value in the array. If there's an odd number of arguments, the last element will be ignored.
This uses array_shift() to remove the first element from the array, which then is used as a key in the arguments array. We then remove the next element from the array, yet again using array_shift(). If we find an actual value here (array_shift returns NULL when the array is empty), we create a entry in the arguments array.
$path = '/blog/2/post/45/comment/24';
$elements = explode('/', $path);
// remove first, empty element
array_shift($elements);
$arguments = array();
while($key = array_shift($elements))
{
$value = array_shift($elements);
if ($value !== NULL)
{
$arguments[$key] = $value;
}
}
Not really an answer per se but you may find http://www.php.net/manual/en/function.parse-url.php useful.

Categories