<?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>";
?>