laravel中用到的面向对象的高级特性

本文介绍了PHP中的自动加载机制,包括__autoload()函数及spl_autoload_register()的使用,并对比了它们与require/include的区别。此外,还探讨了后期静态绑定(late static binding)的概念及其在实践中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.PHP文件的自动加载

<?php
function __autoload($class_name)
{
    $name = strtolower($class_name);
    $path = "../includes/{$name}.php";

    if(file_exists($path)){
         require_once($path);
        }else{
            die("the file {$class_name} could not be found");
        }
}

由于只能定义一个autoload,php7.2即将废弃此函数,推荐使用spl_autoload_register()

//使用匿名函数来autoload
spl_autoload_register(function($class_name){
    require_once('...');
});


//使用一个全局函数
function Custom()
{
    require_once('...');
}
spl_autoload_register('Custom');

//使用一个class当中的static方法
class MyCustomAutoloader
{
    static public function myLoader($class_name)
    {
        require_once('...');        
    }
}

//传array进来,第一个是class名,第二个是方法名
spl_autoload_register(['MyCustomAutoloader','myLoader']); 

//甚至也可以用在实例化的object上
class MyCustomAutoloader
{
    public function myLoader($class_name)
    {
    }
}

$object = new MyCustomAutoloader;
spl_autoload_register([$object,'myLoader']); 

使用autoload,无论是__autoload(),还是spl_autoload_register(),相比于require或include,好处就是autoload机制是lazy loading,也即是并不是你一运行就给你调用所有的那些文件,而是只有你用到了哪个,比如说new了哪个文件以后,才会通过autoload机制去加载相应文件

//加载器实例
class autoloader {
  public static $loader;
  public static function init() {
    if (self::$loader == NULL)
      self::$loader = new self ();
    return self::$loader;
  }
  public function __construct() {
    spl_autoload_register ( array ($this, 'model' ) );
    spl_autoload_register ( array ($this, 'helper' ) );
    spl_autoload_register ( array ($this, 'controller' ) );
    spl_autoload_register ( array ($this, 'library' ) );
  }
  public function library($class) {
    set_include_path ( get_include_path () . PATH_SEPARATOR . '/lib/' );
    spl_autoload_extensions ( '.library.php' );
    spl_autoload ( $class );
  }
  public function controller($class) {
    $class = preg_replace ( '/_controller$/ui', '', $class );
    set_include_path ( get_include_path () . PATH_SEPARATOR . '/controller/' );
    spl_autoload_extensions ( '.controller.php' );
    spl_autoload ( $class );
  }
  public function model($class) {
    $class = preg_replace ( '/_model$/ui', '', $class );
    set_include_path ( get_include_path () . PATH_SEPARATOR . '/model/' );
    spl_autoload_extensions ( '.model.php' );
    spl_autoload ( $class );
  }
  public function helper($class) {
    $class = preg_replace ( '/_helper$/ui', '', $class );
    set_include_path ( get_include_path () . PATH_SEPARATOR . '/helper/' );
    spl_autoload_extensions ( '.helper.php' );
    spl_autoload ( $class );
  }
}
//call
autoloader::init ();

2.静态调用绑定(late static binding)

<?php
class A {

    public static function who() {
        echo __CLASS__;
    }

    public static function test() {
        self::who();
    }
}

在class A中,定义一个static method(静态方法或者说类方法) who()
通过CLASS来输出调用该方法的class name,
又定义了一个静态方法test(),
通过self关键词来调用who()
这个时候我们执行A::test(),那么肯定会输出A.

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

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

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

A

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

如果用静态绑定就是B了,上代码

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

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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

少林码僧

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值