该篇属于《Laravel底层核心技术实战揭秘》这一课程《laravel底层核心概念解析》这一章的扩展阅读。由于要真正学好laravel底层,有些PHP相关的知识必须得了解,考虑到学员们的基础差异,为了避免视频当中过于详细而连篇累牍,故将一些laravel底层实现相关的PHP知识点以文章形式呈现,供大家预习和随时查阅。

不讲理论!不讲理论!不讲理论!(重要的事情说三遍)

<?php
class A {

    public static function who() {
        echo __CLASS__;
    }
		
    public static function test() {
        self::who();
    }
}
  1. class A中,定义一个static method(静态方法或者说类方法) who()
  2. 通过__CLASS__来输出调用该方法的class name,
  3. 又定义了一个静态方法test(),
  4. 通过self关键词来调用who()

这个时候我们执行A::test(),那么肯定会输出A.

现在呢,我们再创建一个class B,让它去扩展A:

class B extends A {
    public static function who() {
        echo __CLASS__;
    }
}

然后我们执行B::test(),这个时候会输出什么呢?

A

对,还是A,因为self关键词只能取到定义当前方法所在的类,或者说它只能取到自己所在的那个类。

好吧,B肯定有点小失望~test()是在你A里面定义的,但是B::test(),这个时候可是我B实际调用的test()方法啊,实际运行的不应该是我B吗?

“借了你的鸡,下了个蛋,就跟我没关系了?谁养的来? ”
“这还真不好说。。。”
“那娶了个媳妇,生了个孩子,孩子还属于娘家吗?”
“有道理!”

于是,A做出了一定的妥协:

class A {
    public static function who() {
        echo __CLASS__;
    }
    public static function test() {
        static::who(); // 后期静态绑定
    }
}

现在我们执行B::test(),这个时候会输出什么呢?

B

也就是说,我们可以用一个static关键词,来获取到运行当中、实际调用这个静态方法的类。如果只是需要获取静态方法调用的类名,那么你也可以使用get_called_class().

好了,这玩意儿有什么用呢?

<?php

class Model
{
    public static function create(array $attributes = [])
    {
        $model = new static($attributes);

        $model->save();

        return $model;
    }
}

class Task extends Model
{
    
}

Task::create([
	'title'=>'学习laravel',
	'author'=>'pilishen'
]);

当执行Task::create()的时候,因为extendsModel,所以就到了Model里的create方法,由于$model = new static($attributes);使用了static关键词,所以此时也就相当于是执行了new Task();,也就是借助static静态绑定,我们在laravel里的自己创建的各个model,就可以共用一系列提前定义好的方法,同时在实际调用的时候,又将结果或过程只作用于自己,从而实现了一个典型的active record design pattern

当然,类似的在laravel里多了去了,更详细的我们会在《Laravel底层核心技术实战揭秘》里阐述。