首页 > PHP资讯 > PHP培训技术 > 在ZendFramework中自动加载

在ZendFramework中自动加载

PHP培训技术

介绍
自动加载是一种机制,这种机制可以在你的PHP代码中无需手动设置依赖的文件。每一个 ? the PHP自动加载手册中都强调,一旦自动加载器被定义,它“在你试图使用一个还没被定义的类或接口时将被自动调用”
使用自动加载,你无需担心一个类在你的项目中的什么地方。使用良好定义的自动加载,你无需担心一个类文件相对于当前类文件的什么位置;你只要简单的使用这个类,自动加载器将会执行文件查找任务。
另外,自动加载,因为它直到最后一刻才载入并确信匹配只出现一次,是一次巨大的性能提升——特别是在你部署之前如果花时间清除require_once()调用的时候
ZendFramework鼓励使用自动加载,并提供许多工具提供库代码和应用程序代码的自动加载。这个教程覆盖了这些工具,也告诉你如何高效的使用它们。
目标与设计
类的命名约定
为了明白ZendFramework中的自动加载,首先你需要明白类名和类文件的关系。
ZendFramework从PEAR中借鉴了一个思想,即类名和文件系统是一个1:1的关系。为了解决文件路径,简单的将下划线”_”替换为目录分隔 符,然后加上后缀“.php”。比如,“Foo_Bar_Baz”将对应文件系统中的”Foo/Bar/Baz.php”。假设该类也可以通过PHP的 include_path设置来解决,它允许include()和require()在include_path中通过相对路径寻找文件名
另外,每一个PEAR及PHP项目,我们使用并推荐为你的代码使用供应商(vendor)或者项目前缀。这意味着你写的所有类将分享同一个类前缀;比 如,在ZendFramework 中的所有代码有“Zend_”前缀。这个命名约定帮助防止命名冲突。在ZendFramework中,我们经常称之为“命名空间”前缀;注意不要把它与 PHP的本地命名空间混淆(be careful not toconfuse it with PHP’s native namespace implementation)。
ZendFramework在内部遵循这些简单的规则。我们的代码标准鼓励你这样做,就像对所有的库代码一样。
自动加载器的协定和设计
Zend Framework的自动加载支持,首先由Zend_Loader_Autoloader提供,有下面的目标和设计元素:
·提供命名空间匹配。如果类的命名空间前缀不在注册的命名空间列表中,则立即返回FALSE。这样就可以比较乐观的匹配,就像会退到其他的自动加载器 (Thisallows for more optimistic matching, as well as fallback to otherautoloaders.)
·允许自动加载器作为一个备份的自动加载器。在一个团队可能分布很广泛,或者使用一个未确定的命名空间前缀设置的情况下,自动加载器应该仍然被设置的以便它试图去匹配任何命名空间前缀。注意,这种做法是不推荐的,因为它会导致不必要的查找
·允许触发错误抑制。我们感觉到——伟大的PHP社区也是这样的——错误抑制是一个坏主意。它昂贵并且覆盖非常真实的应用程序问题。所以,默认情况下,它应该是关的。然而,如果开发者坚持打开它,我们也允许这么做。
·允许指定为自动加载自定义回调。一些开发者不想去使用Zend_Loader::loadClass()去自动加载,但是仍然想去使用ZendFramework的机制。Zend_Loader_Autoloader允许为自动加载指定一个候选的回调
·允许操作SPL自动加载链。这样做的目的是允许指定另外的自动加载器——比如,类的资源加载器没有与文件系统有1:1的映射关系——在主ZendFramework自动加载器之前或之后被注册
自动加载器的基本用法
既然我们已经懂得了什么是自动加载,并懂得了Framework自动加载解决办法的目标和设计。下面让我们开看看怎么去使用Zend_Loader_Autoloader。
在最简单的情况下,你只需要require这个类,然后实例化它,因为Zend_Loader_Autoloader是一个单态(singleton)的(因为SPL自动加载器是一个单个资源的原因),我们使用getInstance()去获取一个实例。
require_once ‘Zend/Loader/Autoloader.php’;
Zend_Loader_Autoloader::getInstance();
默认情况下,这将允许你载入任何带有”Zend_” 或者”ZendX_”的类命名空间前缀的类,只要它们在你的include_path里
如果你有其他的命名空间前缀要去使用会发生什么?最好的、最简单的方法是在实例上调用registerNamespace()方法
require_once ‘Zend/Loader/Autoloader.php’;
$loader = Zend_Loader_Autoloader::getInstance();
$loader->registerNamespace(‘Foo_’);
$loader->registerNamespace(array(‘Foo_’,'Bar_’));
或者,你可以告诉Zend_Loader_Autoloader去担当一个“后备(fallback)”自动加载器。这意味着它将不管命名空间前缀都将去处理任何类。
$loader->setFallbackAutoloader(true);
警告
不要使用后备(fallback)自动加载器
当试图去使用Zend_Loader_Autoloader作为后备自动加载器时,我们不推荐这样做。
内部的,Zend_Loader_Autoloader 使用Zend_Loader::loadClass()来导入类。那个方法使用include()试图导入给定的类文件,如果不成功include()将 返回一个布尔量FALSE,而且发布一个PHP警告。后者实际上可能会导致一些问题:
如果display_errors是启用的,警告将包含在输出中
一来你已经选择的error_reporting级别,它可能也会弄乱你的日志
你能够压制错误信息(Zend_Loader_Autoloader文档详细介绍这个),但是注意当display_errors是启用的,压制仅仅是相关的;错误日志将也会总是显示消息。因为这些原因,我们推荐总是设置能被自动加载器意识到的命名空间前缀
注: 命名空间前缀vs PHP 命名空间
在写这个教程的时候,PHP5.3已经发布了,在这个版本下,PHP现在已经官方支持命名空间了。
然而,Zend Framework在日期上早于PHP5.3建立,命名空间同样也是这样。在ZendFramework中,我们指的“命名空间”是实践上的命名空间,即 带有厂商(vendor)“命名空间”为前缀的类。举例来说,所有的ZendFramework类名称都以“Zend_”为前缀——那就是我们的厂商 (vendor)“命名空间”
ZendFramework计划在将来版本中的自动加载器中提供本地PHP命名空间支持。并且,它的自己的library将在2.0.0版本中使用命名空间
如果你有一个希望使用Zend Frameworkd自定义的自动加载器——也许你也使用一个第三方库中的自动加载器——你可以使用Zend_Loader_Autoloader的 pushAutoloader()和unshiftAutoloader()方法来管理。这些方法将相应的在后面或前面(appendor prepend)添加自动加载器到一个被称为前执行Zend Framework的内部自动载入机制链(These methodswill append or prepend, respectively, autoloaders to a chain thatis called prior to executing Zend Framework’s internal autoloadingmechanism)。这种方法具有以下优点:
每种方法接受可选的第二个参数:类命名空间前缀。这可以用来指示给定的自动加载器应该仅仅在寻找带有指定类前缀的类时被使用。如果处理的类没有那个前缀,自动加载器将被跳过——这将导致性能改进
如果你需要操作spl_autoload()的注册表,任何自动加载器即指向实例方法的回调可能会造成问题(any autoloadersthat are callbacks pointing to instance methods can poseissues),因为spl_autoload_functions()不返回确切的同样回调。Zend_Loader_Autoloader没 有那样的限制。
管理这种方式的自动加载器可以使任何有效的PHP回调(Autoloaders managed this way may be anyvalid PHP callback)。
// Append function ‘my_autoloader’ to the stack,
// to manage classes with the prefix ‘My_’:
$loader->pushAutoloader(‘my_autoloader’,'My_’);

// Prepend static method Foo_Loader::autoload() to the stack,
// to manage classes with the prefix ‘Foo_’:
$loader->unshiftAutoloader(array(‘Foo_Loader’,'autoload’), ‘Foo_’);
资源自动加载
如果你通读autoloader的设计目标,在那节的最后一点指出解决方法应包括这个情况。ZendFramework用Zend_Loader_Autoloader_Resource做这些事情
资源仅仅是一个对应组件命名空间(其加在自动加载器命名空间之后)的名字和路径(其是相对于自动加载器基路径)。在动作中,我们将象下面这样做:
$loader = new Zend_Application_Module_Autoloader(array(
‘namespace’=> ‘Blog’,
‘basePath’  => APPLICATION_PATH .’/modules/blog’,
));
一旦你在合适的位置有了加载器,你就需要将许多的它知道的资源类型通知它(you then need to inform it ofthe various resource types it’s awareof)。这些资源类型是简单的子树(subtree)和前缀的配对

举例来说,考虑一下下面的树
path/to/some/resources/
|– forms/
|   `–Guestbook.php       // Foo_Form_Guestbook
|– models/
|   |– DbTable/
|  |   `–Guestbook.php   // Foo_Model_DbTable_Guestbook
|   |–Guestbook.php       // Foo_Model_Guestbook
|   `–GuestbookMapper.php  //Foo_Model_GuestbookMapper
我们第一步是创建资源加载器:
$loader = new Zend_Loader_Autoloader_Resource(array(
‘basePath’  =>’path/to/some/resources/’,
‘namespace’=> ‘Foo’,
));
下一步,我们需要去定义一些资源类型。
Zend_Loader_Autoloader_Resourse::addResourceType()有三个参数:资源“类型”(任意字符串)、基路 径下的可能存在资源类型的路径和为资源类型使用的组件前缀。在上面的树中,我们有三个资源类型:表单(在“forms”子目录中,带有一个组件前缀 “Form”)、模型(在“models”子目录中,带有一个组件前缀“Model”)和dbtable(在“models/DbTable”子目录中, 带有“Model_DbTable”组件前缀)。我们像下面这样定义它们
$loader->addResourceType(‘form’, ‘forms’,'Form’)
->addResourceType(‘model’, ‘models’, ‘Model’)
->addResourceType(‘dbtable’, ‘models/DbTable’,'Model_DbTable’);
一旦定义了,我们能够简单的使用下面的类
$form     = new Foo_Form_Guestbook();
$guestbook = new Foo_Model_Guestbook();
注:模块(module)资源的自动加载
ZendFramework的MVC层鼓励使用“模块(modules)”,它是在你的站点中自包含的应用程序。默认情况下模块典型的有许多资源类 型,ZendFramework甚至为模块推荐一个标准的目录布局。资源自动载入器因此在这个范例中是非常有用的——那么的有用以至于,当你为你的模块 (module)创建扩展于Zend_Application_Module_Bootstrap的一个引导类(bootstrapclass)时,默认 情况下它们是启用的。更多的信息请参考Zend_Loader_Autoloader_Module 文档。
结论
ZendFramework鼓励使用autoloading,甚至在Zend_Application中默认初始化它。希望这个教程最大程度的提供给你需 要使用的Zend_Loader_Autoloader的信息以及通过附加自定义的自动加载器或者资源自动加载器来扩展它的功能。

PHP培训技术

本文由欣才IT学院整理发布,未经许可,禁止转载。
支持32不支持0