<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <title>References inside the constructor</title> </head> <body><div class="manualnavbar" style="text-align: center;"> <div class="prev" style="text-align: left; float: left;"><a href="oop4.magic-functions.html">The magic functions __sleep and __wakeup</a></div> <div class="next" style="text-align: right; float: right;"><a href="oop4.object-comparison.html">Comparing objects</a></div> <div class="up"><a href="oop4.html">Classes and Objects (PHP 4)</a></div> <div class="home"><a href="index.html">PHP Manual</a></div> </div><hr /><div id="oop4.newref" class="sect1"> <h2 class="title">References inside the constructor</h2> <p class="para"> Creating references within the constructor can lead to confusing results. This tutorial-like section helps you to avoid problems. <div class="informalexample"> <div class="example-contents"> <div class="phpcode"><code><span style="color: #000000"> <span style="color: #0000BB"><?php<br /></span><span style="color: #007700">class </span><span style="color: #0000BB">Foo </span><span style="color: #007700">{<br /> function </span><span style="color: #0000BB">Foo</span><span style="color: #007700">(</span><span style="color: #0000BB">$name</span><span style="color: #007700">) {<br /> </span><span style="color: #FF8000">// create a reference inside the global array $globalref<br /> </span><span style="color: #007700">global </span><span style="color: #0000BB">$globalref</span><span style="color: #007700">;<br /> </span><span style="color: #0000BB">$globalref</span><span style="color: #007700">[] = &</span><span style="color: #0000BB">$this</span><span style="color: #007700">;<br /> </span><span style="color: #FF8000">// set name to passed value<br /> </span><span style="color: #0000BB">$this</span><span style="color: #007700">-></span><span style="color: #0000BB">setName</span><span style="color: #007700">(</span><span style="color: #0000BB">$name</span><span style="color: #007700">);<br /> </span><span style="color: #FF8000">// and put it out<br /> </span><span style="color: #0000BB">$this</span><span style="color: #007700">-></span><span style="color: #0000BB">echoName</span><span style="color: #007700">();<br /> }<br /><br /> function </span><span style="color: #0000BB">echoName</span><span style="color: #007700">() {<br /> echo </span><span style="color: #DD0000">"<br />"</span><span style="color: #007700">, </span><span style="color: #0000BB">$this</span><span style="color: #007700">-></span><span style="color: #0000BB">name</span><span style="color: #007700">;<br /> }<br /> <br /> function </span><span style="color: #0000BB">setName</span><span style="color: #007700">(</span><span style="color: #0000BB">$name</span><span style="color: #007700">) {<br /> </span><span style="color: #0000BB">$this</span><span style="color: #007700">-></span><span style="color: #0000BB">name </span><span style="color: #007700">= </span><span style="color: #0000BB">$name</span><span style="color: #007700">;<br /> }<br />}<br /></span><span style="color: #0000BB">?></span> </span> </code></div> </div> </div> </p> <p class="para"> Let us check out if there is a difference between <var class="varname"><var class="varname">$bar1</var></var> which has been created using the copy <em>=</em> operator and <var class="varname"><var class="varname">$bar2</var></var> which has been created using the reference <em>=&</em> operator... <div class="informalexample"> <div class="example-contents"> <div class="phpcode"><code><span style="color: #000000"> <span style="color: #0000BB"><?php<br />$bar1 </span><span style="color: #007700">= new </span><span style="color: #0000BB">Foo</span><span style="color: #007700">(</span><span style="color: #DD0000">'set in constructor'</span><span style="color: #007700">);<br /></span><span style="color: #0000BB">$bar1</span><span style="color: #007700">-></span><span style="color: #0000BB">echoName</span><span style="color: #007700">();<br /></span><span style="color: #0000BB">$globalref</span><span style="color: #007700">[</span><span style="color: #0000BB">0</span><span style="color: #007700">]-></span><span style="color: #0000BB">echoName</span><span style="color: #007700">();<br /><br /></span><span style="color: #FF8000">/* output:<br />set in constructor<br />set in constructor<br />set in constructor */<br /><br /></span><span style="color: #0000BB">$bar2 </span><span style="color: #007700">=& new </span><span style="color: #0000BB">Foo</span><span style="color: #007700">(</span><span style="color: #DD0000">'set in constructor'</span><span style="color: #007700">);<br /></span><span style="color: #0000BB">$bar2</span><span style="color: #007700">-></span><span style="color: #0000BB">echoName</span><span style="color: #007700">();<br /></span><span style="color: #0000BB">$globalref</span><span style="color: #007700">[</span><span style="color: #0000BB">1</span><span style="color: #007700">]-></span><span style="color: #0000BB">echoName</span><span style="color: #007700">();<br /><br /></span><span style="color: #FF8000">/* output:<br />set in constructor<br />set in constructor<br />set in constructor */<br /></span><span style="color: #0000BB">?></span> </span> </code></div> </div> </div> </p> <p class="para"> Apparently there is no difference, but in fact there is a very significant one: <var class="varname"><var class="varname">$bar1</var></var> and <var class="varname"><var class="varname">$globalref[0]</var></var> are _NOT_ referenced, they are NOT the same variable. This is because "<em>new</em>" does not return a reference by default, instead it returns a copy. <blockquote class="note"><p><strong class="note">Note</strong>: <span class="simpara"> There is no performance loss (since PHP 4 and up use reference counting) returning copies instead of references. On the contrary it is most often better to simply work with copies instead of references, because creating references takes some time where creating copies virtually takes no time (unless none of them is a large array or object and one of them gets changed and the other(s) one(s) subsequently, then it would be wise to use references to change them all concurrently). </span> </p></blockquote> To prove what is written above let us watch the code below. <div class="informalexample"> <div class="example-contents"> <div class="phpcode"><code><span style="color: #000000"> <span style="color: #0000BB"><?php<br /></span><span style="color: #FF8000">// now we will change the name. what do you expect?<br />// you could expect that both $bar1 and $globalref[0] change their names...<br /></span><span style="color: #0000BB">$bar1</span><span style="color: #007700">-></span><span style="color: #0000BB">setName</span><span style="color: #007700">(</span><span style="color: #DD0000">'set from outside'</span><span style="color: #007700">);<br /><br /></span><span style="color: #FF8000">// as mentioned before this is not the case.<br /></span><span style="color: #0000BB">$bar1</span><span style="color: #007700">-></span><span style="color: #0000BB">echoName</span><span style="color: #007700">();<br /></span><span style="color: #0000BB">$globalref</span><span style="color: #007700">[</span><span style="color: #0000BB">0</span><span style="color: #007700">]-></span><span style="color: #0000BB">echoName</span><span style="color: #007700">();<br /><br /></span><span style="color: #FF8000">/* output:<br />set from outside<br />set in constructor */<br /><br />// let us see what is different with $bar2 and $globalref[1]<br /></span><span style="color: #0000BB">$bar2</span><span style="color: #007700">-></span><span style="color: #0000BB">setName</span><span style="color: #007700">(</span><span style="color: #DD0000">'set from outside'</span><span style="color: #007700">);<br /><br /></span><span style="color: #FF8000">// luckily they are not only equal, they are the same variable<br />// thus $bar2->name and $globalref[1]->name are the same too<br /></span><span style="color: #0000BB">$bar2</span><span style="color: #007700">-></span><span style="color: #0000BB">echoName</span><span style="color: #007700">();<br /></span><span style="color: #0000BB">$globalref</span><span style="color: #007700">[</span><span style="color: #0000BB">1</span><span style="color: #007700">]-></span><span style="color: #0000BB">echoName</span><span style="color: #007700">();<br /><br /></span><span style="color: #FF8000">/* output:<br />set from outside<br />set from outside */<br /></span><span style="color: #0000BB">?></span> </span> </code></div> </div> </div> </p> <p class="para"> Another final example, try to understand it. <div class="informalexample"> <div class="example-contents"> <div class="phpcode"><code><span style="color: #000000"> <span style="color: #0000BB"><?php<br /></span><span style="color: #007700">class </span><span style="color: #0000BB">A </span><span style="color: #007700">{<br /> function </span><span style="color: #0000BB">A</span><span style="color: #007700">(</span><span style="color: #0000BB">$i</span><span style="color: #007700">) {<br /> </span><span style="color: #0000BB">$this</span><span style="color: #007700">-></span><span style="color: #0000BB">value </span><span style="color: #007700">= </span><span style="color: #0000BB">$i</span><span style="color: #007700">;<br /> </span><span style="color: #FF8000">// try to figure out why we do not need a reference here<br /> </span><span style="color: #0000BB">$this</span><span style="color: #007700">-></span><span style="color: #0000BB">b </span><span style="color: #007700">= new </span><span style="color: #0000BB">B</span><span style="color: #007700">(</span><span style="color: #0000BB">$this</span><span style="color: #007700">);<br /> }<br /><br /> function </span><span style="color: #0000BB">createRef</span><span style="color: #007700">() {<br /> </span><span style="color: #0000BB">$this</span><span style="color: #007700">-></span><span style="color: #0000BB">c </span><span style="color: #007700">= new </span><span style="color: #0000BB">B</span><span style="color: #007700">(</span><span style="color: #0000BB">$this</span><span style="color: #007700">);<br /> }<br /><br /> function </span><span style="color: #0000BB">echoValue</span><span style="color: #007700">() {<br /> echo </span><span style="color: #DD0000">"<br />"</span><span style="color: #007700">,</span><span style="color: #DD0000">"class "</span><span style="color: #007700">,</span><span style="color: #0000BB">get_class</span><span style="color: #007700">(</span><span style="color: #0000BB">$this</span><span style="color: #007700">),</span><span style="color: #DD0000">': '</span><span style="color: #007700">,</span><span style="color: #0000BB">$this</span><span style="color: #007700">-></span><span style="color: #0000BB">value</span><span style="color: #007700">;<br /> }<br />}<br /><br /><br />class </span><span style="color: #0000BB">B </span><span style="color: #007700">{<br /> function </span><span style="color: #0000BB">B</span><span style="color: #007700">(&</span><span style="color: #0000BB">$a</span><span style="color: #007700">) {<br /> </span><span style="color: #0000BB">$this</span><span style="color: #007700">-></span><span style="color: #0000BB">a </span><span style="color: #007700">= &</span><span style="color: #0000BB">$a</span><span style="color: #007700">;<br /> }<br /><br /> function </span><span style="color: #0000BB">echoValue</span><span style="color: #007700">() {<br /> echo </span><span style="color: #DD0000">"<br />"</span><span style="color: #007700">,</span><span style="color: #DD0000">"class "</span><span style="color: #007700">,</span><span style="color: #0000BB">get_class</span><span style="color: #007700">(</span><span style="color: #0000BB">$this</span><span style="color: #007700">),</span><span style="color: #DD0000">': '</span><span style="color: #007700">,</span><span style="color: #0000BB">$this</span><span style="color: #007700">-></span><span style="color: #0000BB">a</span><span style="color: #007700">-></span><span style="color: #0000BB">value</span><span style="color: #007700">;<br /> }<br />}<br /><br /></span><span style="color: #FF8000">// try to understand why using a simple copy here would yield<br />// in an undesired result in the *-marked line<br /></span><span style="color: #0000BB">$a </span><span style="color: #007700">=& new </span><span style="color: #0000BB">A</span><span style="color: #007700">(</span><span style="color: #0000BB">10</span><span style="color: #007700">);<br /></span><span style="color: #0000BB">$a</span><span style="color: #007700">-></span><span style="color: #0000BB">createRef</span><span style="color: #007700">();<br /><br /></span><span style="color: #0000BB">$a</span><span style="color: #007700">-></span><span style="color: #0000BB">echoValue</span><span style="color: #007700">();<br /></span><span style="color: #0000BB">$a</span><span style="color: #007700">-></span><span style="color: #0000BB">b</span><span style="color: #007700">-></span><span style="color: #0000BB">echoValue</span><span style="color: #007700">();<br /></span><span style="color: #0000BB">$a</span><span style="color: #007700">-></span><span style="color: #0000BB">c</span><span style="color: #007700">-></span><span style="color: #0000BB">echoValue</span><span style="color: #007700">();<br /><br /></span><span style="color: #0000BB">$a</span><span style="color: #007700">-></span><span style="color: #0000BB">value </span><span style="color: #007700">= </span><span style="color: #0000BB">11</span><span style="color: #007700">;<br /><br /></span><span style="color: #0000BB">$a</span><span style="color: #007700">-></span><span style="color: #0000BB">echoValue</span><span style="color: #007700">();<br /></span><span style="color: #0000BB">$a</span><span style="color: #007700">-></span><span style="color: #0000BB">b</span><span style="color: #007700">-></span><span style="color: #0000BB">echoValue</span><span style="color: #007700">(); </span><span style="color: #FF8000">// *<br /></span><span style="color: #0000BB">$a</span><span style="color: #007700">-></span><span style="color: #0000BB">c</span><span style="color: #007700">-></span><span style="color: #0000BB">echoValue</span><span style="color: #007700">();<br /><br /></span><span style="color: #0000BB">?></span> </span> </code></div> </div> <p class="para">The above example will output:</p> <div class="example-contents screen"> <div class="cdata"><pre> class A: 10 class B: 10 class B: 10 class A: 11 class B: 11 class B: 11 </pre></div> </div> </div> </p> </div><hr /><div class="manualnavbar" style="text-align: center;"> <div class="prev" style="text-align: left; float: left;"><a href="oop4.magic-functions.html">The magic functions __sleep and __wakeup</a></div> <div class="next" style="text-align: right; float: right;"><a href="oop4.object-comparison.html">Comparing objects</a></div> <div class="up"><a href="oop4.html">Classes and Objects (PHP 4)</a></div> <div class="home"><a href="index.html">PHP Manual</a></div> </div></body></html>