Home > OS >  I don't understand PHP references
I don't understand PHP references

Time:01-10

<?
$map = [];
$cur = null;

function write ($s) {
    global $cur;
    $cur[] = $s;
}

function set_cursor ($key) {
    global $map, $cur;
    $cur = [];
    $map [$key] = &$cur;
}

set_cursor ("key_a");
write ("Hello");
write ("World");

set_cursor ("key_b");
write ("Foobar");

var_dump ($map);

?>

From languages I am familiar with (Javascript, C#, C) I expected $map to contain

{
    "key_a": ['Hello', 'World'],
    "key_b": ['Foobar']
}

Instead it contains

{
    "key_a": ['Foobar'],
    "key_b": ['Foobar']
}

This seems unintuitive. How do I need to modify the code to return the expected result?

As per request in the comments, here is the equivalent code in Javascript that produces the desired and expected result:

var map = {};
var cur = null;

function set_cursor (key) {
    cur = [];
    map [key] = cur;
}

function write (s) {
    cur.push (s);
}

set_cursor ("key_a");
write ("Hello");
write ("World");

set_cursor ("key_b");
write ("Foobar");

console.log(map);

CodePudding user response:

OK I have figured it out myself in the meanwhile. In typical PHP fashion, you had to use some non-sensical arcane constructs to get it working. In particular you had to use $GLOBALS instead of global to get it to produce the same results that would be produced by any other language.

Here's the code:

<?
$map = [];
$cur = null;

function write ($s) {
    global $cur;
    $cur[] = $s;
}

function set_cursor ($key) {
    global $map;
    if (array_key_exists ($key, $map) == false)
        $map[ $key] = [];
    $GLOBALS["cur"] = &$map[ $key ];
}

set_cursor ("key_a");
write ("Hello");
write ("World");

set_cursor ("key_b");
write ("Foobar");

set_cursor ("key_a");
write ("Hello");
write ("Again");

set_cursor ("key_b");
write ("Bazqux");

var_dump ($map);
?>

CodePudding user response:

You could use a class to acheive this.

class Map
{
    private $map = [];
    private $cur = null;
    
    public function write(string $s): self 
    {
        $this->map[$this->cur][] = $s;
        return $this;
    }
    
    public function set_cursor(string $key): self 
    {
        $this->cur = $key;
        return $this;
    }
    
    public function getMap(): array 
    {
        return $this->map;
    }
}

Usage:

$map = new Map();


$map->set_cursor("key_a");
$map->write("Hello");
$map->write("World");

$map->set_cursor("key_b");
$map->write("Foobar");

// fluent style
$map->set_cursor("key_a")
    ->write("Hello")
    ->write ("Again");

$map->set_cursor("key_b")->write("Bazqux");

// display
var_dump($map->getMap());

output

array(2) {
  ["key_a"]=>
  array(4) {
    [0]=>
    string(5) "Hello"
    [1]=>
    string(5) "World"
    [2]=>
    string(5) "Hello"
    [3]=>
    string(5) "Again"
  }
  ["key_b"]=>
  array(2) {
    [0]=>
    string(6) "Foobar"
    [1]=>
    string(6) "Bazqux"
  }
}

  •  Tags:  
  • Related