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。