初初使用php的时候,引用其他类,都是首先获取类的局对路径,然后通过require_once导入。
那么在child继承parents之前,先导入parents.php
require_once realpath ( dirname ( dirname ( __FILE__ )) . ' /PParent.php ' );
class PSon extends PParent
{
function __construct(){
}
}
这样做,对于类结构简单的情况,发现不出来问题(由于当初需要速成php,完成外接的项目,所以就这样做了)
当一个php文件中需要引用的类非常多的时候,而且每次编译的时候,用不了几个类,还用上述的方法,就会导致大部分的文件导入时多余的,所以php的autoload功能(动态加载php文件)就应运而生了。
今天刚学习了这个,现在记录一下。由于我做项目用的是zend_framework,所以同时分析了zend_framework中封装的zend_loader_autoloader的实现。
首先是php5的API----》spl_autoload_register(使用于(PHP 5 >= 5.1.2))
使用的步骤如下:
1、定义autoload方法(方法名自定义就可以);
2、用spl_autoload_register注册autoload方法(可以注册多个autoload方法);
3、使用需要的类(注册autoload方法之后,调用类的时候,会自动按照autoload方法的注册顺序进行load,如果load成功,那么停止执行下一个autoload方法,否则一直到所有autoload方法执行完为止)
sample:
文件路径:
代码:
class PParent
{
function __construct(){
}
}
class PSon extends PParent
{
function __construct(){
}
}
class PDaughter extends PParent
{
function __construct(){
}
}
global $fileDir ;
$fileDir = dirname ( __FILE__ );
class autoloader
{
public static function parentLoad( $class )
{
global $fileDir ;
$classDir = realpath ( $fileDir . ' ./model/ ' . $class . ' .php ' ); // 获得类的路径
if ( file_exists ( $classDir ))
{
require_once $classDir ;
return true ;
}
else {
return false ;
}
}
public static function childLoad( $class )
{
global $fileDir ;
$classDir = realpath ( $fileDir . ' ./model/child/ ' . $class . ' .php ' ); // 获得类的路径
if ( file_exists ( $classDir ))
{
require_once $classDir ;
return true ;
}
else {
return false ;
}
}
}
spl_autoload_register( ' autoloader::parentLoad ' ); // 注册自动加载的方法
spl_autoload_register( ' autoloader::childLoad ' );
$par = new PParent(); // 使用类,前面没有显示的调用Model_PParent哦
$child = new PSon();
$daughter = new PDaughter();
zend framework对php5的autoload进行了封装,其实是对类的命名进行了规范,并实现了对应的autoload方法
现在按照zend_loader_autoloader的规范,对上面的程序进行改造。
步骤:
1、将zend framework的library导入项目(等会说导到哪个目录);
2、改类名,如A/B/C.php,则类名改成A_B_C;
3、获取zend_loader_autoloader单例,并设置namespace;
4、使用需要的类;
项目路径:
代码:
class Model_Child_PDaughter extends Model_PParent
{
function __construct(){
}
}
class Model_Child_PSon extends Model_PParent
{
function __construct(){
}
}
class Model_PParent
{
function __construct(){
}
}
global $fileDir ;
$fileDir = dirname ( __FILE__ );
$oldIncludePath = get_include_path (); // 获取旧的环境路径
$newIncludePath = implode (
PATH_SEPARATOR ,
array (
realpath ( $fileDir ) ,
realpath ( $fileDir . ' /library/ ' ) ,
$oldIncludePath ,
)
); // 新的环境路径
set_include_path ( $newIncludePath ); // 设置新的环境路径
require_once $fileDir . ' /library/zend/loader/Autoloader.php ' ; // 引入zend_loader_autoloader
$loader = Zend_Loader_Autoloader :: getInstance(); // 获取单例
$loader -> registerNamespace( ' Model_ ' ); // 注册命名空间
/* *
* 上面的$newIncludePath包含了 项目根目录$fileDir 与 项目下的library目录
* 是由于我用的
* zend_loader_autoloader的命名空间Zend_(默认的命名空间有Zend_和Zendx_)是从library开始,
* 我自定义的命名空间Model_是从 项目根目录$fileDir开始。
*
* 注意:命名空间的区分大小写,需要与类定义的大小写对应,如Model_PParent,命名空间就必须定义为Model_
*/
$par = new Model_PParent(); // 使用类,前面没有显示的调用Model_PParent哦
$child = new Model_Child_PSon();
$daughter = new Model_Child_PDaughter();
总结:
使用spl_autoload_register与zend_loader_autoloader不矛盾,因为zend_loader_autoloader也是对spl_autoload_register进行封装,总之,它们还是按照注册的顺序进行加载的。