PHP自动加载类__autoload()浅谈
在面向对象编程中,都是以对象为单位的操作,如果我有两个不同的类,类A和类B,在同一个文件里,实例化对象,就能在这个文件同时调用类A和类B的函数
1 <?php 2 #a.php 3 4 class A{ 5 public function funA() 6 { 7 echo 'The class:'.__class__.'<br/>'; 8 } 9 } 10 11 class B{ 12 public function funB() 13 { 14 echo 'The class:'.__class__.'<br/>'; 15 } 16 } 17 $a = new A(); 18 $b = new B(); 19 $a->funA(); //The class:A 20 $b->funB(); //The class:B
两个类都在同一个文件,所有能运行成功,但现在大部分应用都分MVC,不同类专门处理特定的事物,比如C(Controller),只执行与事物有关的逻辑操作,这些文件很明显分属于不同目录下:
|—root
|—controller
|—controllerA.php
|—model
|—modelA.php
|—view
|—viewA.php
这时我要在modelA.php里怎么引用controllerA.php的函数呢?这就用到__autoload()了。
1 <?php 2 #保存在MyClass.php 3 4 class MyClass { 5 6 public function getNamespace() 7 { 8 return get_class($this); 9 } 10 }
现在我们在同级目录下引用这个类
1 <?php 2 3 function __autoload($name) 4 { 5 $file = realpath(__DIR__).'/'.$name.'.php'; 6 if(file_exists($file)) 7 { 8 require_once($file); 9 if(class_exists($name,false)) 10 { 11 return true; 12 } 13 return false; 14 } 15 return false; 16 } 17 18 $obj = new MyClass(); 19 echo $obj->getNamespace(); //输出 MyClass;
当你引用不存在的类时,__autoload就会被调用,并且你的类名会被作为参数传送过去(当你同时使用命名空间,包含命名空间部分会一起作为参数传送)。
下面我们把命名空间和自动加载类合并使用
命名空间,PHP从5.3开始支持命名空间(namespace),这个在C语言里非常常见,刚开始我不理解,直到我完整接触一个项目,需要加载在不同目录下Class时,恍然大悟。OK,下面讲一讲自己的理解吧。
用不同的命名空间区别相同的函数名,同时命名空间也可以作为引入类文件的路径。
(在WEB项目中,当在client输入一个url时,一般会有一个入口文件,在这个文件里解析你要调用的controller,以及传递的参数,然后动态的加载相应类文件,这其实就牵扯到一点路由规则,当然还有另外一种,在项目初始化之初就把所有类文件全部加载在内存中,这样,每次请求响应都不用再加载,常驻内存后响应要快点。)
1 <?php 2 #首先建立一个MyClass目录,在该目录下新MyClass.php文件,代码如下。 3 4 namespace MyClass; 5 6 class MyClass { 7 8 public function getNamespace() 9 { 10 return get_class($this); 11 } 12 }
1 <?php 2 #在跟MyClass目录同级的目录下,新建一个文件,内容如下 3 function __autoload($name) 4 { 5 $class_path = str_replace('\\',DIRECTORY_SEPARATOR,$name); //把表示命名空间的分割符号,转换成表示目录结构的斜线 6 $file = realpath(__DIR__).'/'.$class_path.'.php'; 7 if(file_exists($file)) 8 { 9 require_once($file); //引入文件 10 if(class_exists($name,false)) //带有命名空间的类名 11 { 12 return true; 13 } 14 return false; 15 } 16 return false; 17 } 18 echo MyClass\MyClass::getNamespace(); //输出: MyClass\MyClass;
这样非常容易避免了,当一个项目非常大时,不停的require文件。
让我们再思考,有没有更工程化的解决方案?当然有,我们可以建立自己的 Autoload 类,在这个类里面自动加载不同的类(可以包含命名空间),需要引用其他类的文件,只需要显示写入这个 Autoload 类即可。
具体实现放在下一篇博客 ^_^ .( http://www.cnblogs.com/CpNice/p/4369399.html )