关于php对象的引用传值与cow问题记录

in 学习笔记 with 0 comment 访问: 2,036 次

问题缘起

发这篇文章其实挺羞愧的,应该是自己的基础不够扎实,我记得好久之前(应该是初学的时候)是知道这个事情的,各种赋值引用都自己测试过,但是苦于一直没有使用到,忘光了。于是写下这篇文章给自己个教训。

测试数据:

mysql.png

这里我只用这三条数据进行测试,来说明php对象的引用传值。

代码案例:

class Litblc {

    private $init;

    public function index ()
    {
        $this->init = Classroom::where('school_id', 6);
        $tree = $this->init;

        $a = $tree->where('name', 101)->get();
        $b = $tree->where('name', 102)->get();

        return $a;
    }
}

Output:

[{"id":19,"school_id":6,"building_id":10,"name":"101","created_at":"2016-04-19 09:33:51","updated_at":"2016-04-19 09:33:51","grade_name":""}]

那么此时如果return $b会返回什么呢? 我们先注销$a的赋值查看输出:

class Litblc {

    private $init;

    public function index ()
    {
        $this->init = Classroom::where('school_id', 6);
        $tree = $this->init;

        //$a = $tree->where('name', 101)->get();
        $b = $tree->where('name', 102)->get();

        return $b;
    }
}

Output:

[{"id":20,"school_id":6,"building_id":10,"name":"102","created_at":"2016-04-19 09:34:11","updated_at":"2016-04-19 09:34:11","grade_name":""}]

到此都是正常的,那么最后我们把$a的注释打开,输出$b :

class Litblc {

    private $init;

    public function index ()
    {
        $this->init = Classroom::where('school_id', 6);
        $tree = $this->init;

        $a = $tree->where('name', 101)->get();
        $b = $tree->where('name', 102)->get();

        return $b;
    }
}

Output :

[]

为什么会这样呢?其实这个时候的$b已经变成了
$b = $tree->where('name', 101)->where('name', 102)->get();,
所以返回是空。

总结:

一般我们在普通赋值中,都会触发php的cow机制,但是:

  1. 在php5以后,所有对象都是引用传递,除非显式调用clone $object。
  2. 即使赋值给其它变量,也是引用。
  3. 所以,应尽量避免函数内操作外部对象。

课后作业:

请问下面代码会输出什么?欢迎在下方评论写下你的答案。

class Litblc {

    private $init;

    public function index ()
    {
        $this->init = Classroom::where('school_id', 6);
        $tree = $this->init;
        $tree2 = clone $this->init;

        $a = $tree->where('name', 101)->get();
        $b = $tree2->where('name', 102)->get();

        return $b;
    }
}

扩展 :
PHP底层分析: 关于写时复制(cow)
php manual: 对象和引用

赞赏支持
Responses