0

I am experimenting with JSON and PHP

I create an (nested) object in Javascript like

var obj2={user:{name:"will"}, age:27, country:"UK"};

I turn it to JSON and send it via AJAX/POST to an php file

hr.send("firstname="+JSON.stringify(obj2));

There, I decode it,

$a=$_POST['firstname']; $b=json_decode($a,true);

so its like Array ( [user] => Array ( [name] => will ) [age] => 27 [country] => UK )

Now, if I do

echo $b[user][name];

I will get "will"

How can I still get the same result, but without knowing the names of the keys? Do something like echo $b[0][0]; and still output "will"?

Thanks

slevin
  • 4,166
  • 20
  • 69
  • 129
  • 1
    You construct it using the key names to make it easier to access by key name later. `[user][name]` means more to most people than `[0][0]`. – AbraCadaver May 05 '14 at 17:38
  • possible duplicate of [Accessing an associative array by integer index in PHP](http://stackoverflow.com/questions/4769148/accessing-an-associative-array-by-integer-index-in-php) – adeneo May 05 '14 at 17:47
  • @adeneo Is slightly different because my question has nested arrays. – slevin May 05 '14 at 18:11

4 Answers4

1

I'm not sure why you'd want to do this. The whole point of associative arrays in PHP is to easily "associate" the indexes to their values. The key names gives a hint on what that particular index contains. By converting the array into a numeric indexed one, you will lose the information.

If that's not an issue, you can re-index the array first in order to be able to access the array values based on their numeric offsets. Use array_values() to re-index the array and then access the values based on numeric offsets (as opposed to keys):

$array = array_values($b['user']);
echo $array[0]; // => 'Will'
Amal Murali
  • 75,622
  • 18
  • 128
  • 150
  • That is greate, but how can I do it without using the `user` key? Something like `$array = array_values($b[0]);` ? Thanks – slevin May 05 '14 at 18:08
  • @slevin: Certainly possible, but **why** do you want to do it? – Amal Murali May 05 '14 at 18:12
  • Is not working by setting `array_values($b[0]);`. No particular reason. As I said "I am experimenting with JSON and PHP". I wanna explore the potencials. – slevin May 05 '14 at 18:14
1

You can use array_keys for that, it returns a new array with all the keys indexed by integers

$keys = array_keys($b);
$user = $b[$keys[0]];

$keys2 = array_keys($user);
$name  = $user[$keys2[0]]; // "will";
adeneo
  • 312,895
  • 29
  • 395
  • 388
  • You're setting the value of `$b[$keys[0]]` to `will`. The OP wants to retrieve the name, not store: "*How can I still get the same result, but without knowing the names of he keys?*". – Amal Murali May 05 '14 at 17:42
  • @AmalMurali - Doesn't matter, it was just to show what the value is, I can comment it out if it looks better. – adeneo May 05 '14 at 17:43
  • @adeneo That is greate, but how can I do it without using the `user` key? Something like `$keys = array_keys($b[0]);` Thanks – slevin May 05 '14 at 18:09
  • @slevin - You'd just do it twice. – adeneo May 05 '14 at 18:19
1

Do you mean this?

$b = array( 'user' => array ( 'name' => 'will' ), 'age' => 27);

echo current(current($b)); // 'will'

This assumes the internal "array pointer" hasn't been moved before. See current for details.

A more flexible would be a function that picks the n-th element:

function nth($ary, $position) {
    return array_values($ary)[$position];
}

Example:

$b = array( 'user' => array ( 'name' => 'will' , 'lastname' => 'smith'), 'age' => 27);
print nth(nth($b, 0), 1); // smith
gog
  • 10,367
  • 2
  • 24
  • 38
  • Very interesting. It works. You method requires few lines, but is not flexible because if my array was like ` var obj2={user:{name:"will", lastname:"smith"}, age:27, country:"UK"};` I cannot find a way to print `smith`. adeneo's method requires many more lines but is flexible because I can replace `$name = $user[$keys2[1]];` and get "smith" .Anyhow, those are just experiments, so thank you very much – slevin May 05 '14 at 18:54
  • I think you have to replace `return array_values($ary[$position]);` I test it several times, changing it and does not work. i dont get an echo, but also no errors in the console. Weird – slevin May 05 '14 at 20:46
  • @slevin: IIRC, this syntax (indexing a function result) is new in php 5.4 (?), in older versions you have to use a temp variable. – gog May 05 '14 at 21:24
0

You should not go via JSON or by associative arrays. Theoretically associative arrays do not guarantee that the order will be preserved.

This approach will only be useful if you can assume a standard order of fieldnames for each object.

Create a standard list of fieldnames that will be used when sending and receiving.

$objectsTypes = array('user','task')
$fieldsUser = array('firstname','lastname','age');

Then send the data in the correct order. Example using GET (POST could also work the same way):

?data[0][0]=Maxwell&data[0][1]=Smart&data[0][2]=35&data[1]=AnswerShoePhone

When processing the data you know which position to expect each variable. You could hard code the positions, or detect them dynamically.

echo $_GET['data'][0][0];//Maxwell
echo $_GET['data'][0][1];//Smart
echo $_GET['data'][1];//AnswerShoePhone

$indexOfUser = array_search('user',$objectsTypes);
$indexOfLastname = array_search('lastname',$fieldsUser);
echo $_GET['data'][ $indexOfUser ][ $indexOfLastname ];//Smart

If you want to support a collection of objects (e.g. multiple users) you can nest everything one level deeper. e.g.

?data[0][0][0]=Maxwell
&data[0][0][1]=Smart
&data[0][1][0]=Agent
&data[0][1][1]=99

$users = $_GET['data'][ $indexOfUser ]
pythonjsgeo
  • 5,122
  • 2
  • 34
  • 47