<?php //用引用解释 /////////////////////////////////////////////////////////////// //1 引用是什么 //在 PHP 中引用意味着用不同的名字访问同一个变量内容。这并不像 C 的指针,替代的是,引用是符号表别名 //php的引用并不是C的指针,只是一个指向同一地址的变量 /////////////////////////////////////////////////////////////// //2 引用做什么 //对一个未定义的变量进行引用赋值,引用参数传递或引用返回,则会自动创建该变量 /* class MyStdClass{ }; function foo(&$val) { //var_dump($val); } foo($a); $b =array(); foo($b['b']); //var_dump(array_key_exists('b',$b)); $c = new MyStdClass; foo($c->b); //var_dump(property_exists($c,'b')); //判断对像的属性是否存在 //如果在一个函数内部给一个声明为global的变量赋于一个引用,该引用只是在函数内部可见 //可以用全局的$BLOBALS数组避免这一点 $var1 = "Example val"; $var2 = ""; function global_references($use_globals) { global $var1, $var2; if(!$use_globals){ $var2 = & $var1; //该引用只是在函数中有用 }else{ $GLOBALS['var2'] = & $var1; } } global_references(false); //echo "var2 is set to".$var2."\n\t<BR>"; global_references(true); //echo "var2 is set to".$var2."\n\t"; //把global $val;当成是$var=& $GLOBALS['var']的简写,从而将其它引用赋值给$var只改变了本地变量的引用 //如果在foreach语句中给一个具有引用的变量赋值,被引用的对像也被改变 $ref = 0; $row = & $ref; foreach (array(1,2,3) as $row) { # code... } //echo $ref; class reftest { public $a = 1; public $c = 1; public function reftest1() { $b = & $this->a; $b++; } public function reftest2() { $d = & $this->c; $d++; } } $test = new reftest(); $test->reftest1(); $test->reftest2(); //echo $test->a."<BR>"; //2 //echo $test->c; //2 $v1=0; $arrV=array(&$v1,&$v1); //foreach ($arrV as $v) //{ //$v1++; //echo $v1."\n";//现在的$v1的变量所指向的值已经是1 2了 //echo $v."\n"; //这里的$v值是还没有添自加之前的值, //} foreach ($arrV as $key => $value) { # code... $v1++; //echo $arrV[$key]."\n"; } // $arr1 = array(1); // echo "\nbefore:\n"; // echo "\$arr1[0] == {$arr1[0]}\n"; //==1 // $arr2 = $arr1; // $arr2[0]++; // echo "\nafter:\n"; // echo "\$arr1[0] == {$arr1[0]}\n"; //==1 // echo "\$arr2[0] == {$arr2[0]}\n"; //==2 // $arr3 = array(1); // $a =& $arr3[0]; // echo "\nbefore:\n"; // echo "\$a == $a\n";//==1 // echo "\$arr3[0] == {$arr3[0]}\n";//==1 // $arr4 = $arr3; // $arr4[0]++; // echo "\nafter:\n"; // echo "\$a == $a\n";//==2 // echo "\$arr3[0] == {$arr3[0]}\n"; //2 // echo "\$arr4[0] == {$arr4[0]}\n"; //2 //这个例子要小心哈 */ // function array_key_by($data, $keys, $dupl = false) // /* // * $data - Multidimensional array to be keyed // * $keys - List containing the index/key(s) to use. // * $dupl - How to handle rows containing the same values. TRUE stores it as an Array, FALSE overwrites the previous row. // * // * Returns a multidimensional array indexed by $keys, or NULL if error. // * The number of dimensions is equal to the number of $keys provided (+1 if $dupl=TRUE). // */ // { // // Sanity check // if (!is_array($data)) return null; // // Allow passing single key as a scalar // if (is_string($keys) or is_integer($keys)) $keys = Array($keys); // elseif (!is_array($keys)) return null; // // Our output array // $out = Array(); // // Loop through each row of our input $data // foreach($data as $cx => $row) // { // if (is_array($row)) // { // //$keys = array('baz'); // // Loop through our $keys // foreach($keys as $key) // { // $value = $row[$key]; //$value=baz_a; // if (!isset($last)) // First $key only // { // if (!isset($out[$value])) $out[$value] = Array(); // echo "<B>isset out--{$value}--</B>"; // $last =& $out; // Bind $last to $out // //$out['baz_a'] = array(); // //$last['baz_a'] = array(); // } // else // Second and subsequent $key.... // { // if (!isset($last[$value])) $last[$value] = Array(); // echo "<B>isset last--{$value}--</B>"; // } // // Bind $last to one dimension 'deeper'. // // First lap: was &$out, now &$out[...] // // Second lap: was &$out[...], now &$out[...][...] // // Third lap: was &$out[...][...], now &$out[...][...][...] // // (etc.) // $last =& $last[$value]; //这句不太好理解 // //$last = & $last[$value]; //就是给$last重新引用一个空的数组值 // //var_dump($last); // //echo "***"; // } // //如果$last存在 // if (isset($last)) // { // // At this point, copy the $row into our output array // if ($dupl) //如果$dupl为true // $last[$cx] = $row; // Keep previous // else // $last = $row; // Overwrite previous // } // unset($last); // Break the reference // //清空last这个副本内容 // } // else return NULL; // //echo "<BR>===================================<BR>"; // //echo "<BR>===================================<BR>"; // var_dump($out); // echo "<BR>******************************\n"; // echo "<BR>******************************<BR><BR>"; // } // // Done // return $out; // } // // A sample result set to test the function with // $data = Array(Array('name' => 'row 1', 'foo' => 'foo_a', 'bar' => 'bar_a', 'baz' => 'baz_a'), // Array('name' => 'row 2', 'foo' => 'foo_a', 'bar' => 'bar_a', 'baz' => 'baz_b'), // Array('name' => 'row 3', 'foo' => 'foo_a', 'bar' => 'bar_b', 'baz' => 'baz_c'), // Array('name' => 'row 4', 'foo' => 'foo_b', 'bar' => 'bar_c', 'baz' => 'baz_d') // ); // // First, let's key it by one column (result: two-dimensional array) // print_r(array_key_by($data, 'baz')); // echo "<BR>=====<BR>"; // echo "<BR>=====<BR>"; // // Or, key it by two columns (result: 3-dimensional array) // print_r(array_key_by($data, Array('baz', 'bar'))); // echo "<BR>=====<BR>"; // echo "<BR>=====<BR>"; // // We could also key it by three columns (result: 4-dimensional array) // print_r(array_key_by($data, Array('baz', 'bar', 'foo'))); // echo "<BR>=====<BR>"; // echo "<BR>=====<BR>"; /************************************************ function array_key_by($data, $keys, $dupl=false) { if(!is_array($data)) return null; if(is_string($keys) or is_integer($keys)) $keys = array($keys); elseif(!is_array($keys)) return null; $out = array(); foreach ($data as $cx => $row) { if(is_array($row)) { foreach($keys as $key) { $value = $row[$key]; if(!isset($last)){ if(!isset($out[$value])) $out[$value] = array(); $last = & $out; }else{ if(!isset($last[$value])) $last[$value] = array(); } echo "<BR>******<BR>"; var_dump($last[$value]); echo "<BR>******<BR>"; $last= & $last[$value]; //将last指向一个自己的一个地址 } if(isset($last)) { if($dupl) { $last[$cx] = $row; //保存 }else $last = $row; //保存 } unset($last);//删除last的指向数值的地址 }else return null; } return $out; } $data = Array(Array('name' => 'row 1', 'foo' => 'foo_a', 'bar' => 'bar_a', 'baz' => 'baz_a'), Array('name' => 'row 2', 'foo' => 'foo_a', 'bar' => 'bar_a', 'baz' => 'baz_b'), Array('name' => 'row 3', 'foo' => 'foo_a', 'bar' => 'bar_b', 'baz' => 'baz_c'), Array('name' => 'row 4', 'foo' => 'foo_b', 'bar' => 'bar_c', 'baz' => 'baz_d') ); // First, let's key it by one column (result: two-dimensional array) print_r(array_key_by($data, 'baz')); echo "<BR><BR><BR>"; // Or, key it by two columns (result: 3-dimensional array) print_r(array_key_by($data, Array('baz', 'bar'))); echo "<BR><BR><BR>"; // We could also key it by three columns (result: 4-dimensional array) print_r(array_key_by($data, Array('baz', 'bar', 'foo'))); echo "<BR><BR><BR>"; ************************************************************/ /********************************************************** class reftest { public $a = 1; public $b = 1; public function reftest1() { $c = & $this->a; $c++; } public function reftest2() { $c = & $this->b; $c++; } } $reftest = new reftest; $reftest->reftest1(); $reftest->reftest2(); echo $reftest->a."<BR>"; echo $reftest->b; **********************************************************/ /********************************************************** class foo { protected $name; function __construct($str) { $this->name = $str; } function __toString() { return "my name is ".$this->name." and i Live in ".__CLASS__.".\n"; } function setName($str) { $this->name = $str; } } class MasterOne { protected $foo; function __construct($f) { $this->foo = $f; } function __tostring() { return "master ".__CLASS__." | foo:".$this->foo."\n"; } function setFooName($str) { $this->foo->setName($str); } } class MasterTwo { protected $foo; function __construct($f) { $this->foo = $f; } function __tostring() { return "master ".__CLASS__." | foo:".$this->foo."\n"; } function setFooName($str) { $this->foo->setName($str); } } $bar = new foo('bar'); echo $bar; //bar echo "<BR><BR>"; $baz = & $bar; echo $bar; //bar echo "<BR><BR>"; $m1 = new MasterOne($bar); $m2 = new MasterTwo($bar); echo $m1; echo "<BR><BR>"; echo $m2; echo "<BR><BR>"; $bar->setName("baz"); echo $bar; echo "<BR><BR>"; echo $baz; echo "<BR><BR>"; echo $m1; echo "<BR><BR>"; echo $m2; echo "<BR><BR>"; $m2->setFooName("MasterTwo Foo"); echo $m1; echo "<BR><BR>"; echo $m2; echo "<BR><BR>"; echo $bar; echo "<BR><BR>"; echo $baz; echo "<BR><BR>"; **********************************************************/ /********************************************************** function foo(&$bar) { $bar="hello\n\t"; echo $bar; } foo($unset); echo $unset; //hello foo($set="set\n\t");//这里有点弄不懂样 echo $set; //set **********************************************************/ /////////////////////////////////////////////////////////////// //引用不是什么 // $GLOBALS['baz'] = "xxdxxd"; // function foo(&$val) // { // $var = & $GLOBALS['baz']; // } // foo($bar); // var_dump($bar); //null //这将使foo函数中的$var变量在函数调用时和$bar绑定在一起 //但接着又会重新绑定到了$GOLBALS['baz']上面, //不可能通过引用机制将$bar在函数调用范围内绑定到别的变量上面,因为在函数foo中并没有变量$bar(它被表示为$var,但是$var只有变量内容而没有调用符号表中的名字到值的绑定)。可以使用引用返回来引用被函数选择的变量 // const int c_1 = 1, c_2 = 2; // int *a = &c_1; // int *b = &c_2; // void foo(int *var) // { // var = a; // } //C的写法 // $b =1; $d = 2; // $a = & $b; // $c = & $d; // $b = & $c; // echo "a={$a}\t\n";//1 // echo "b={$b}\t\n";//2 // echo "c={$c}\t\n";//2 // echo "d={$d}\t\n";//2 // $a = (&$b); //error // $a = 0; // $b = &$a; // echo "A:";var_dump($a);echo "<BR><BR>"; //int(0) // echo "B:";var_dump($b);echo "<BR><BR>"; //int(0) // unset($b); //这里并不是直接释放$a所指向的地址,而只是释放$b这个变量 // echo "*******************************"; // echo "A:";var_dump($a);echo "<BR><BR>"; //int(0) // echo "B:";var_dump($b);echo "<BR><BR>"; //null // //所有是跟指针,也就是C里面的区别 // $a = 4; // $b = &$a; // $c = &$b; // echo "{$a}-{$b}-{$c}<BR>"; // echo $a-$b-$c; //-4(4-4-4) // echo "<BR>"; // $c = 5; // echo "{$a}-{$b}-{$c}<BR>"; // echo $a-$b-$c; //-5(5-5-5) // echo "<BR>"; // unset($a); // $c = 6; // echo "{$a}-{$b}-{$c}<BR>"; // echo $a - $b - $c; //-10 (0-6-6) // class Dog // { // var $Name; // function Dog($name) // { // $this->Name = $name; // } // public function GetName() // { // return $this->Name; // } // } // $bar = new Dog('spot'); // function foo(&$val) // { // $var = new Dog("Gypsy"); // } // foo($bar); // echo $bar->GetName(); //spot // $a = 'eh'; // $b = & $a;// $b == 'eh' // $c = & $b;// $c == 'eh' // $d = 'meh'; // echo "\$a = $a\n"; //eh // echo "\$b = $b\n"; //eh // echo "\$c = $c\n"; //eh // echo "\$d = $d\n"; //meh // //$c = & $d ; // //$c = "meh"; //这样又是不同的 // echo "\n"; // echo "\$a = $a\n"; //eh // echo "\$b = $b\n"; //eh // echo "\$c = $c\n"; //meh // echo "\$d = $d\n"; //meh // unset($a); // unset($b); // $a[1]=1; // $a[2]=&$a[1]; //$a[2]=指向了1数值地址 // $b=$a; // $b[2]=7; //这样修改,等于同时修改了$a[2]所指向的值 // //$a[2]所指向的值也是$a[1]所指向的值 // print_r($a); // echo "<BR><BR>"; // print_r($b); // class my // { // var $value; // function get1(&$ref) // { // $ref[] = &$this; //把自己的引用给了$ref的数组 // } // function get2(&$ref) // { // $ref[] = &$this; //把自己的引用给了$ref的数组 // } // function get3(&$ref) // { // $ref[] = $this; //这里只是一个copy不起做用 // } // } // $m = new my; // $m->value = 'foo'; // $m->get1($ref=array()); // $m1 = & $ref[0]; // $m1->value = 'bar'; // echo "m:".get_class($m).'->value='.$m->value."<BR><BR>"; // echo "m1:".get_class($m1).'->value='.$m1->value."<BR><BR>"; // $m->value = 'foo'; // $m->get2($m2); //$m2->value = 'bar'; //这样是错误的 $m2是一个数组,并不是一个对像 //$m2[0]->value = 'bar'; // $m2 = &$m2[0]; // $m2->value = 'bar'; // echo "m:".get_class($m).'->value='.$m->value."<BR><BR>"; // echo "m2:".get_class($m2).'->value='.$m2->value."<BR><BR>"; //它被设置为一个副本becuase不起作用 // $m->value = 'foo'; // $m->get3($m3); // $m3[0]->value = 'bar'; // echo "m:".get_class($m).'->value='.$m->value."<BR><BR>"; //my->value=bar // echo "m3:".get_class($m3[0]).'->value='.$m3[0]->value."<BR><BR>"; //my->value=bar // $b = 1; // $a =& $b; // print("<pre>"); // print("\$a === \$b: ".(($a === $b) ? "ok" : "failed")."\n"); //ok // print("unsetting \$a...\n"); // unset($a); // print("now \$a is ".(isset($a) ? "set" : "unset")." and \$b is ".(isset($b) ? "set" : "unset")."\n"); // //unset set // print("</pre>"); // $b = 1; // $a =& $b; // print("<pre>"); // print("\$a === \$b: ".(($a === $b) ? "ok" : "failed")."\n"); //ok // print("unsetting \$b...\n"); // unset($b); // print("now \$a is ".(isset($a) ? "set" : "unset")." and \$b is ".(isset($b) ? "set" : "unset")."\n"); // //set unset // print("</pre>"); $a = 3; $b =& $a; function foo (&$c) { $c = new stdClass(); } function bar () { return new stdClass(); } function &fum () { return new stdClass(); } if (!is_object($a)) { echo "\$a does not initially refer to an object<BR>"; } foo($b); //$b已经是对象了 echo "\$b ", ($a === $b)? "has not": "has", " been re-bound by foo<BR>"; if (is_object($a)) { echo "\$a now contains an object identifier<BR>"; } //$a也是对象了 $b =& bar(); //has not echo "\$b ", ($a === $b)? "has not": "has", " been re-bound by bar<BR>"; $b =& fum();//has 因为这里返回的是一个引用,而不是一个对像 //function &fun(){ ....} echo "\$b ", ($a === $b)? "has not": "has", " been re-bound by fum<BR>"; ?>