我不明白 PHP 参考资料

I don't understand PHP references

<?
$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);

?>

对于我熟悉的语言(Javascript、C#、C),我希望$map包含

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

而是包含

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

这似乎不直观。我需要如何修改代码才能return预期的结果?

根据评论中的要求,这里是 Javascript 中产生所需和预期结果的等效代码:

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);

好的,我已经自己弄明白了。在典型的 PHP 方式中,您必须使用一些无意义的奥术构造才能使其正常工作。特别是你必须使用 $GLOBALS 而不是 global 来让它产生与任何其他语言产生的结果相同的结果。

代码如下:

<?
$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);
?>

您可以使用 class 来实现这一点。

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

用法:

$map = new Map();

$map->setCursor('key_a');
$map->write('Hello');
$map->write('World');

$map->setCursor('key_b');
$map->write('Foobar');

// or in fluent style :

$map->setCursor('key_a')
    ->write('Hello')
    ->write('Again')
    ->setCursor('key_b')
    ->write('Bazqux');

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

输出

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"
  }
}

演示(PHP 8.1):https://3v4l.org/de6tv#v8.1.1