软件设计 2017-04-23
我们使用另一个文件定义的一个class的时候,传统的情况下需要require XXX.php
//Good.php <?php class Good{ //...... } //use.php <?php require 'Good.php'; //包含进来文件 $good = new Good(); //现在可以使用Good类
但是写require真的很烦!!现在可以使用一个自动加载函数,发现类没有被定义的时候自动根据我们定义的规则帮我们去require需要的文件。
//Good.php <?php class Good{ //...... } //use.php <?php function __autoload($className){ require $className . '.php'; //定义包含的规则 } $good = new Good(); //可以使用Good类,发现没有定义,会自动调用__autoload函数,现在'Good'作为参数传入了__autoload函数,去包含需要的文件
__autoload函数不能解决所有的问题,现在的项目已经非常复杂,光一个autoload函数已经不能满足需要了,因为可能不同的模块使用了不同的自动加载规则。
spl_autoload_register将函数注册到SPL autoload函数队列中,它实际上创建了 __autoload 函数的队列
,按定义时的顺序逐个执行。相比之下,__ autoload() 只可以定义一次。
bool spl_autoload_register ([ callable $autoload_function [, bool $throw = true [, bool $prepend = false ]]] )
欲注册的自动装载函数。如果没有提供任何参数,则自动注册 autoload 的默认实现函数spl_autoload()。
此参数设置了 autoload_function 无法成功注册时, spl_autoload_register()是否抛出异常。
如果是 true,spl_autoload_register() 会添加函数到队列之首,而不是队列尾部。
sql_autoload_resister('load_function'); //函数名 sql_autoload_resister(array('load_object', 'load_function')); //类和静态方法 sql_autoload_resister('load_object::load_function'); //类和方法的静态调用 //php 5.3之后,也可以像这样支持匿名函数了。 spl_autoload_register(function($className){ if (is_file('./lib/' . $className . '.php')) { require './lib/' . $className . '.php'; } });
note:使用了spl_autoload_register之后原来的__autoload函数就失效了,如果需要继续使用,需要显示的注册它
if (function_exists('__autoload')) { spl_autoload_register('__autoload'); } //。。。。。。 spl_autoload_register('your_autoload_function'); //现在注册另一个
是否继续在自动加载函数队列中查找不取决于加载函数的返回值和是否require了文件,只有真正require需要的文件才会停止
//Good.php位于app文件夹下 <?php class Good{ //...... } //Another.php,位于use同级文件夹下 <?php class Another{ } //use.php <?php function load1($className) { echo "load1\n"; if (file_exists($className.'.php')) { echo 'found: '.$className.PHP_EOL; require $className; } else { echo 'not found: '.$className.PHP_EOL; } } function load2($className) { echo "load2\n"; require 'Another.php'; echo 'require another class'.PHP_EOL; return true; } function load3($className) { echo "load3\n"; if (file_exists('app/'.$className.'.php')) { echo 'found '.$className.PHP_EOL; require 'app/'.$className.'.php'; } else { echo 'not found: '.$className.PHP_EOL; } } spl_autoload_register('load1'); spl_autoload_register('load2'); spl_autoload_register('load3'); $a = new Good();
输出如下
load1 not found: Good load2 require another class load3 found Good
可以使用spl_autoload_functions()
获得注册的所有函数
Array ( [0] => load1 [1] => load2 [2] => load3 )
取消注册的自动加载函数spl_autoload_unregister
spl_autoload_unregister('load1');
spl_autoload()是__autoload()函数的默认实现
提供了autoload()的一个默认实现。如果不使用任何参数调用 spl_autoload_register() 函数,则以后在进行 autoload() 调用时会自动使用此函数。
完整的规范请参考PSR-4: Autoloader
标准的类名应该具有下列形式
\<NamespaceName>(\<SubNamespaceNames>)*\<ClassName>
需要强调的:
当根据命名空间载入文件时候:
采用了匿名函数的方式
<?php /** * An example of a project-specific implementation. * * After registering this autoload function with SPL, the following line * would cause the function to attempt to load the \Foo\Bar\Baz\Qux class * from /path/to/project/src/Baz/Qux.php: * * new \Foo\Bar\Baz\Qux; * * @param string $class The fully-qualified class name. * @return void */ spl_autoload_register(function ($class) { // project-specific namespace prefix $prefix = 'Foo\\Bar\\'; // base directory for the namespace prefix $base_dir = __DIR__ . '/src/'; // does the class use the namespace prefix? $len = strlen($prefix); if (strncmp($prefix, $class, $len) !== 0) { // no, move to the next registered autoloader return; } // get the relative class name $relative_class = substr($class, $len); // replace the namespace prefix with the base directory, replace namespace // separators with directory separators in the relative class name, append // with .php //下边这一行很关键 $file = $base_dir . str_replace('\\', '/', $relative_class) . '.php'; // if the file exists, require it if (file_exists($file)) { require $file; } });
参考资料:
<?php. if (!empty($_POST)) {. $data1 = $_POST["data1"];$data2 = $_POST["data2"];$fuhao = $_POST["fuh