1.命名空间自动加载
在3.2版本中不需要手动加载类库文件,可以很方便的完成自动加载。
系统可以根据类的命名空间自动定位到类库文件,例如定义了一个类Org\Util\Auth类:
namespace Org\Util; class Auth { }
保存到ThinkPHP/Library/Org/Util/Auth.class.php
这样我们就可以直接实例化了,
new \Org\Util\Auth();
实例化之后系统会自动加载
ThinkPHP/Library/Org/Util/Auth.class.php
框架Liberary目录下的命名空间都可以自动识别和定位,如下
Library 框架类库目录
│ ├─Think 核心Think类库包目录
│ ├─Org Org类库包目录
│ ├─ ... 更多类库目录
Library目录下的子目录都是一个根命名空间,就是说Think,Org下的类都可以自动加载
new Think\Cache\Driver\File(); new Org\Util\Auth(); new Org\Io\File();
都可以自动加载对应的类库文件。
我们还可以在Liberary目录下面任意增加新的目录,就会自动注册成为一个新的根命名空间,如下:
'AUTOLOAD_NAMESPACE' => array( 'My' => THINK_PATH.'My', 'One' => THINK_PATH.'One',)
配置了上面的AUTOLOAD_NAMESPACE之后可以实例化下面的类库
new My\Net\IpLocation(); new One\Util\Log();
自动加载下面的类库文件
ThinkPHP/My/Net/IpLocation.class.php
ThinkPHP/One/Util/Log.class.php
如果命名空间不在Library目录下面,并且没有定义对应的AUTO_LOADNAMESPACE参数的话则会当做模块的命名空间自动加载,例如
new Home\Model\UserModel(); new Home\Event\UserEvent();
这跳跃有点大,刚才讲的还是Liberary下的命名空间,现在又扯到Application下的。
由于ThinkPHP/Library目录下面不存在Home目录,也没在AUTOLOAD_NAMESPACE参数定义Home命名空间,所以就把Home当成模块命名空间来识别,所以会自动加载
Application/Home/Model/UserModel.class.php Application/Home/Event/UserEvent.class.php
这些命名空间貌似都是ThinkPHP\Liberary目录下的,这个目录下的东西一般不会修改的啊,不明白为什么没有说Application目录下的命名空间。
2.类库映射
定义了较多的命名空间效率会有所影响,可以给常用的类库定义类库映射,命名空间映射相当于给类文件定义了一个别名,例如:
Think\Think::addMap('Think\Log',THINK_PATH.'Think\Log.php');
Think\Think::addMap('Org\Util\Array',THINK_PATH.'Org\Util\Array.php');
那这段应该写在哪里呢,文档没有说清楚。也可使用addMap方法批量导入类库映射定义,如下:
$map = array('Think\Log'=>THINK_PATH.'Think\Log.php','Org\Util\Array'=>THINK_PATH.'Org\Util\Array.php');Think\Think::addMap($map);
文档中依旧没有说明这段应该写在什么地方,是config.php还是入口文件里呢,捉急啊。
3.类库加载的优先级
在实际的类库加载过程中,往往会涉及到自动加载优先级的问题,以Test\MyClass为例,自动加载的优先级顺序如下:
1.判断是否注册了Test\MyClass类库映射,如果有则自动加载类库映射定义的文件,
2.判断是否存在Liberary\Test目录,有则以该目录为初始目录加载
3.判断是否注册了Test根命名空间,有则以注册的目录为初始目录加载
4.以上都不成立则以Test模块模块经行初始目录加载,
4.手动加载第三方类库
使用第三方类库的时候可能出现以下情况,不符合ThinkPHP命名空间和后缀,没有使用命名空间或者命名空间和路径不一致,我们可以使用手动导入的方式加载。
我们使用import方法导入类库,如下:
// 导入Org类库包Library/Org/Util/Date.class.php类库 import("Org.Util.Date"); // 导入Home模块下面的 Application/Home/Util/UserUtil.class.php类库 import("Home.Util.UserUtil"); // 导入当前模块下面的类库 import("@.Util.Array"); // 导入Vendor类库包 Library/Vendor/Zend/Server.class.php import('Vendor.Zend.Server');
对于import方法,系统会自动识别导入类库文件的位置,ThinkPHP可以自动识别的类库包括Think,Org,Com,Behavior,Vendor,以及Liberary目录下的子目录,这不扯犊子啊,Think,Org,Com,Behavior,Vendor就在ThinkPHP\Liberary下,文档中所说的Liberary目录是指那个目录呢?哦,有可能文档中所说的是Liberary目录下自己新建的目录,有可能。
如果在Liberary目录下新建了一个Test目录,并创建了一个UserTest.class.php文件可以这样导入:
import('Test.UserTest');
注意如果没有使用namespace来定义命名空间的话,实例化的时候需要使用根命名空间,如下:
import('Test.UserTest'); $test = new \UserTest();
按照系统规则,import方法是无法导入具有点号的类库文件,因为点号会直接转化为斜线,例如如果我们定义了一个User.Info.class.php文件的话采用import("Org.User.Info");方式加载就会出现错误,导致我们加载到的不是Org/User.Info.class.php文件,而是Org/User/Info.class.php文件,这种情况下我们使用import("Org.User#Info");方式导入,这个就是说文件名中的点号用#代替。
大多数情况下import可以自动识别导入类库文件的位置,特殊情况下需要第二个参数来指定起始导入的路径,例如:要导入当前文件所在目录下的RBAC/AccessDecisionManager.class.php 文件,可以使用import("RBAC.AccessDecisionManager",dirname(__FILE__)); 。 如果要导入的文件后缀不是class.php而是.php,可以使用第三个参数import("RBAC.AccessDecisionManager",dirname(__FILE__),".php");
如果第三方的类库放在Vendor目录下,以.php为文件后缀,也没有采用命名空间可以采用系统内部的Vendor函数简化导入,例如我们要把Zend的Filter\Dir.php放到Vendor目录下面,这个时候Dir文件的路径就是Vendor\Zend\Filter\Dir.php,使用Vendor方法导入如下:
Vendor('Zend.Filter.Dir');
Vendor方法也可以支持和import一样的基础路径和文件后缀参数,如下:
Vendor('Zend.Filter.Dir',dirname(__FILE__),'.class.php');
感觉高上大的,这些貌似是对系统进行扩展的时候使用的比较多。