Note that there are some explanatory texts on larger screens.

plurals
  1. POPHP 5: return by ref method produces unexpected results
    primarykey
    data
    text
    <p>I created a simple class to manage a tree data structure which seemed to behave strangely (code to follow). When it became apparent that this was not a mistake by me I created a test case which produced equally puzzling behavior. This is the same in 5.3 and 5.4.</p> <p>This is my test case:</p> <pre><code>&lt;?php class testcaseA { public function __construct($one=0, $two=1, $three=2) { $this-&gt;obj = new testcaseB($one++, $three, $two); } public function &amp;get($what){ return $this-&gt;obj-&gt;get($what); } } class testcaseB { public function __construct($one, &amp;$two, &amp;$three) { $this-&gt;one=$one; $this-&gt;two=$two; $this-&gt;three=$three; echo "\$one={$one}"; } public function &amp;get($what){ echo "&lt;p&gt;You asked for $what. $what ain't no country I ever heard of.&lt;br /&gt;"; echo "Check: [{$this-&gt;one}], {$this-&gt;two}, {$this-&gt;three}. Is this thing on?&lt;/p&gt;"; $this-&gt;obj[$what] = new testcaseB($this-&gt;one++,$this-&gt;two,$this-&gt;three); return $this-&gt;obj[$what]; } } ini_set('display_errors',1); error_reporting(E_ALL); $bob = new testcaseA(); $bob-&gt;get("What")-&gt;get("Spam")-&gt;get("America"); $bob-&gt;get("What")-&gt;get("EU")-&gt;get("France"); echo "&lt;pre&gt;"; print_r($bob); </code></pre> <p>Now the output that I expected was to see the value for $one increment 1,2,3,1,2,3 and produce a tree shape.</p> <p>This is the output I actually got:</p> <pre><code>$one=0 You asked for What. What ain't no country I ever heard of. Check: [0], 2, 1. Is this thing on? $one=0 You asked for Spam. Spam ain't no country I ever heard of. Check: [0], 2, 1. Is this thing on? $one=0 You asked for America. America ain't no country I ever heard of. Check: [0], 2, 1. Is this thing on? $one=0 You asked for What. What ain't no country I ever heard of. Check: [1], 2, 1. Is this thing on? $one=1 You asked for EU. EU ain't no country I ever heard of. Check: [1], 2, 1. Is this thing on? $one=1 You asked for France. France ain't no country I ever heard of. Check: [1], 2, 1. Is this thing on? $one=1 testcaseA Object ( [obj] =&gt; testcaseB Object ( [one] =&gt; 2 [two] =&gt; 2 [three] =&gt; 1 [obj] =&gt; Array ( [What] =&gt; testcaseB Object ( [one] =&gt; 2 [two] =&gt; 2 [three] =&gt; 1 [obj] =&gt; Array ( [EU] =&gt; testcaseB Object ( [one] =&gt; 2 [two] =&gt; 2 [three] =&gt; 1 [obj] =&gt; Array ( [France] =&gt; testcaseB Object ( [one] =&gt; 1 [two] =&gt; 2 [three] =&gt; 1 ) ) ) ) ) ) ) ) </code></pre> <p>This confused me at first but I wondered if maybe the chained usage was setting values in a way I was not expecting.</p> <p>So I tried this which I added after the previous code:</p> <pre><code>...same classes and initial code as before... $a=$bob-&gt;get("What"); $b=$a-&gt;get("Spam"); $c=$b-&gt;get("America"); //$bob-&gt;get("What") $d=$a-&gt;get("EU"); $e=$d-&gt;get("France"); print_r($bob); </code></pre> <p>This produced a different but still unpredictable set of results.</p> <pre><code>You asked for What. What ain't no country I ever heard of. Check: [2], 2, 1. Is this thing on? $one=2 You asked for Spam. Spam ain't no country I ever heard of. Check: [2], 2, 1. Is this thing on? $one=2 You asked for America. America ain't no country I ever heard of. Check: [2], 2, 1. Is this thing on? $one=2 You asked for EU. EU ain't no country I ever heard of. Check: [3], 2, 1. Is this thing on? $one=3 You asked for France. France ain't no country I ever heard of. Check: [3], 2, 1. Is this thing on? $one=3testcaseA Object ( [obj] =&gt; testcaseB Object ( [one] =&gt; 3 [two] =&gt; 2 [three] =&gt; 1 [obj] =&gt; Array ( [What] =&gt; testcaseB Object ( [one] =&gt; 4 [two] =&gt; 2 [three] =&gt; 1 [obj] =&gt; Array ( [Spam] =&gt; testcaseB Object ( [one] =&gt; 3 [two] =&gt; 2 [three] =&gt; 1 [obj] =&gt; Array ( [America] =&gt; testcaseB Object ( [one] =&gt; 2 [two] =&gt; 2 [three] =&gt; 1 ) ) ) [EU] =&gt; testcaseB Object ( [one] =&gt; 4 [two] =&gt; 2 [three] =&gt; 1 [obj] =&gt; Array ( [France] =&gt; testcaseB Object ( [one] =&gt; 3 [two] =&gt; 2 [three] =&gt; 1 ) ) ) ) ) ) ) ) </code></pre> <p>This is still not the behavior that I am after but it is closer. What I need is to use a chain of objects to traverse the tree (as with the first case), a pointer to the values $two and $three which in the real case are arrays and not swapped about. What I don't want to do is copy objects needlessly.</p> <p>On the other hand I do need to have all the objects share a single pair of variables which they all use.</p> <p>My guess is that the method <code>get()</code> could afford to be <code>byval</code> rather than <code>byref</code> although instinctively this seems wrong. </p> <p>Can anyone explain what the <code>$one</code> value is doing?</p> <p>Also can anyone help me understand the behavior of the first test case especially to the values in the array the first time?</p> <p><strong>UPDATE</strong></p> <p>Making use of the awesome suggestions our test case now looks like:</p> <pre><code>class testcaseA { public function __construct($one=0, $two=1, $three=2) { $this-&gt;obj = new testcaseB(++$one, $three, $two); } public function &amp;get($what){ return $this-&gt;obj-&gt;get($what); } } class testcaseB { public function __construct($one, &amp;$two, &amp;$three) { $this-&gt;one=$one; $this-&gt;two=$two; $this-&gt;three=$three; echo "[New:\$one={$one}]:"; } //public function &amp;get($what){ public function &amp;get($what){ //echo "&lt;p&gt;You asked for $what. $what ain't no country I ever heard of.&lt;br /&gt;"; echo "Get:{$what}:[{$this-&gt;one}]&lt;br /&gt;"; if(!isset($this-&gt;obj[$what])){ $this-&gt;obj[$what] = new testcaseB(++$this-&gt;one,$this-&gt;two,$this-&gt;three); } return $this-&gt;obj[$what]; } } echo "STARTING:&lt;br /&gt;"; ini_set('display_errors',1); error_reporting(E_ALL); echo "REALLY STARTING:&lt;br /&gt;"; echo "&lt;pre&gt;"; echo "&lt;p&gt;One at a time:&lt;/p&gt;"; $bob = new testcaseA(); $a=$bob-&gt;get("What"); $b=$a-&gt;get("Spam"); $c=$b-&gt;get("America"); $d=$a-&gt;get("EU"); $e=$d-&gt;get("France"); echo "&lt;br /&gt;"; print_r($bob); echo "&lt;p&gt;Chained:&lt;/p&gt;"; $bobby = new testcaseA(); $bobby-&gt;get("What")-&gt;get("Spam")-&gt;get("America"); $bobby-&gt;get("What")-&gt;get("EU")-&gt;get("France"); echo "&lt;br /&gt;"; print_r($bob); </code></pre> <p>The out put of which is:</p> <pre><code>STARTING: REALLY STARTING: One at a time: [New:$one=1]:Get:What:[1] [New:$one=2]:Get:Spam:[2] [New:$one=3]:Get:America:[3] [New:$one=4]:Get:EU:[3] [New:$one=4]:Get:France:[4] [New:$one=5]: testcaseA Object ( [obj] =&gt; testcaseB Object ( [one] =&gt; 2 [two] =&gt; 2 [three] =&gt; 1 [obj] =&gt; Array ( [What] =&gt; testcaseB Object ( [one] =&gt; 4 [two] =&gt; 2 [three] =&gt; 1 [obj] =&gt; Array ( [Spam] =&gt; testcaseB Object ( [one] =&gt; 4 [two] =&gt; 2 [three] =&gt; 1 [obj] =&gt; Array ( [America] =&gt; testcaseB Object ( [one] =&gt; 4 [two] =&gt; 2 [three] =&gt; 1 ) ) ) [EU] =&gt; testcaseB Object ( [one] =&gt; 5 [two] =&gt; 2 [three] =&gt; 1 [obj] =&gt; Array ( [France] =&gt; testcaseB Object ( [one] =&gt; 5 [two] =&gt; 2 [three] =&gt; 1 ) ) ) ) ) ) ) ) Chained: [New:$one=1]:Get:What:[1] [New:$one=2]:Get:Spam:[2] [New:$one=3]:Get:America:[3] [New:$one=4]:Get:What:[2] Get:EU:[3] [New:$one=4]:Get:France:[4] [New:$one=5]: testcaseA Object ( [obj] =&gt; testcaseB Object ( [one] =&gt; 2 [two] =&gt; 2 [three] =&gt; 1 [obj] =&gt; Array ( [What] =&gt; testcaseB Object ( [one] =&gt; 4 [two] =&gt; 2 [three] =&gt; 1 [obj] =&gt; Array ( [Spam] =&gt; testcaseB Object ( [one] =&gt; 4 [two] =&gt; 2 [three] =&gt; 1 [obj] =&gt; Array ( [America] =&gt; testcaseB Object ( [one] =&gt; 4 [two] =&gt; 2 [three] =&gt; 1 ) ) ) [EU] =&gt; testcaseB Object ( [one] =&gt; 5 [two] =&gt; 2 [three] =&gt; 1 [obj] =&gt; Array ( [France] =&gt; testcaseB Object ( [one] =&gt; 5 [two] =&gt; 2 [three] =&gt; 1 ) ) ) ) ) ) ) ) </code></pre> <p>The output numbers seem right but the <code>$one</code> are off in the stack. </p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload