从 PHP 5.3.0 开时,PHP增加了一个叫后期静态绑定的功能,用于在继承范围内引用静态调用的类,即在类的继承过程中,使用的类不再是当前类,而是调用的类。后期静态绑定使用关键字 static 来实现,通过这种机制,static:: 不再被解析为定前方法所在的类,而是在实际运计算得到的,即为运行时最初调用的类。虽然将其称为 “后期静态绑定” 但它不仅限制于静态方法的调用。比如

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?php
class A {
public static function call () {

echo "class A"."<br>";

public static function test () {

self::call();

static::call();

}

}
class B extends A {
public static function call () {

echo "class B"."<br>";

}

}
B::test();
输出:class A
class B

通过上述实例可以看出,在调用 test() 函数时, self:: 是直接调用本类中的方法,而 static 是根据调用 test() 函数的类来决定 static:: 的值,因此 static 的值只有在调用时才能确定下来,而 self 则是在定义时就确定下来的。需要注意的是,static 并不限于静态方法调用,通用使用于非静态函数的东南亚用,调用的方式同上数静态函数一样,是在调用动态确定的。
下面给出非静态方法调用的实例。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<?php
class A {
public function call () {

echo "instance from A"."<br>";

}

public function test () {

self::call ();

static::call();

}

}
class B extends A {
public function call() {

echo "instance from B". "<br>";

}

}
$b = new B();
$b->test();
输出:
instance from A
instance from B

后期静态绑定还可以用于对象实例化中,同上内容一样,在实例化对象时, static 会根据运行时调用的类来决定实例化对象,而 self 是根据所在位置的类来决定实例化对象,下面给出一个具体实例。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?php
class A
{
public static function create()

{

$self = new self();

$static = new static();

return array($self,$static);

}

}
class B extends A
{
}
$arr = B::create();
foreach($arr as $value){
var_dump($value);

}
输出:object(A)[1]
object(B)[2]

在 Laravel 框架中,以上三种使用方法经常可以遇到,下面是 Laravel 框架中 Illuminate\Database\Eloquent\Model 类的部分代码,该类中大量使用了后期静态绑定,如 $model = new static($attributes)return static::create($attributes)等,因为该类为抽象类,所以它的实现类在调用这些函数时,最种动态绑定的都是实现类,而费这个 Model 抽象类。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
文件:Illuminate\Database\Eloquent\Model.php
<?php
// 保存模型类实例中的数据并返回该模型类实例
public static function create(array $attributes = [])
{
$model = new static($attributes);

$model->save();

return $model;

}
// 获取第一个符合条件的数据或创建一个新的
public static function firstOrCreate(array $attributes)
{
if(!is_null($instance = static::where($attributes)->first()){

return $instance:

}

return static::create($attributes);

}