设为首页 收藏本站
查看: 709|回复: 0

[经验分享] 设计PHP自动类装载功能

[复制链接]

尚未签到

发表于 2017-3-30 09:19:56 | 显示全部楼层 |阅读模式
  在使用面向对象方法做PHP开发时,可能会经常使用到各个路径中的类文件,这就需要大量的 include 或 require,而 PHP 提供了一个比较快捷的方式,就是利用函数 __autoload 可以编程实现动态的类装载功能,这样就不需要手动的编写大量include 或 require,好了,下面切入正题。
  设计思路:如果想实现自动类装载功能,就必须使用 PHP 提供的 __autoload 函数,该函数只有一个参数,即我们在程序编写时所涉及到的类名称,当函数被调用时,我们要做的就是利用传入的类名加载这个类所在的文件。
  第一个问题就是,我们如何得知类属于哪个文件名呢?在做 Java 或 .Net 程序时,整个运行的程序会根据类名在内存中查找对应的类型信息(常常会伴随着命名空间作为限定),内存的类型信息来自于应用程序初始化时的类文件装载,这点与 PHP 是有区别的,PHP 程序不会装载所有内容,它只是在代码运行到某处需要装载必要的文件时才会发出装载请求。暂时抛弃何时装载这个问题,再次回到装载类文件,不管是 .Net 还是 Java,它们在装载类型信息的时候,都是类名查找类型信息的,从这点看来 __autoload 采用的也是相同的方法,但是 PHP 在定义类时并不要求文件名与类名保持一致,这就有可能造成文件与类杂乱无章,给类装载实现带来麻烦,所以有必要人为的规定类定义与其所在的文件需要采用相同的名称,或者两者之间按照某种规则可以互相映射,这样就很容易。
  第二个问题,类所在的文件名已经可以确定,但是这个文件是属于哪个目录呢?Java 可以根据包名来进行查找,.Net 有命名空间,虽然新版本的 PHP 引入了命名空间的概念,但是既存的服务器也许会因为多种原因不能为每个客户提供最新的环境,所以还是得从 PHP 本身下手比较实用。虽然没有命名空间,但是可以借鉴操作系统的环境变量概念,将不同的路径名放入环境变量中,这样就可以从环境变量中读取各个目录,然后找到目标类所在的文件。
  一、类名与文件名映射
  这一步要做的就是定义文件名与类名映射规则,类名采用驼峰命名法,即类名的每个单词首字母需大写,而文件的命名则采用全部单词小写,单词之间以下划线分割,后缀名为 .class.php 。
  二、在环境变量中进行路径遍历
  仿照 UNIX 或 Windows 的环境变量的定义方式,将多个文件夹以分号或冒号分隔,罗列在 CLASSPATH 中。当程序读取时,可以将文件夹路径放入数组中。
  三、开始装载
  调用函数 require 或 include 并利用组合好的文件路径进行文件装载,但是有两处需要注意,首先需要判断组合好的路径是否有效,其次,文件成功装载后,为了效率问题,可以马上退出 __autoload 函数。
  define(CLASSPATH, dirname(__FILE__).'/entity'.':'.dirname(__FILE__).'/meta');function __autoload($classname) {
$filename = strtolower(preg_replace('/(?<=/B)([A-Z])/s', '_$1', $classname)) . ".class.php";
foreach (preg_split('/:/',CLASSPATH) as $cp) {
if (file_exists("$cp/$filename")) {
require_once ("$cp/$filename");
break;
}
}
}
  四、启用自动类装载功能
  主动式:将该函数直接或间接包含在当前文件中,之后无论在文件何处编写代码,类文件都可以自动装载。
  被动式:将该函数直接或间接包含在当前文件中,以当前文件为主控制程序,然后调用其它业务实现,这样在其他业务实现文件中就无需考虑类装载的问题了。
  
DSC0000.gif
  在图中采用的是主动式,question_parser.php 通过创建 meta 中存放的类,这些类又调用 entity 中的内容,这个过程仅仅在 question_parser.php 包含了定义 __autoload 的 question_sysext.php,关系图如下:

question_parser.php -> question_sysext.php
||
//
meta* => entity*
  五、扩展思考
  如果文件名与类名无任何关联性的话,可以装载 CLASSPATH 中定义的文件夹中所有 *.php 文件或是像例子那样装载 *.class.php 。
  缓存类装载,当成功装载一个类所在的文件后,可以将类名与文件名记录下来以便下次使用,这样就无需每次都进行循环遍历,在某些情况下可以节省查找时间。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-357399-1-1.html 上篇帖子: 值得研究的PHP主流FrameWork框架 下篇帖子: 如何编译PHP源代码(ZEND)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表