1、写一个分级的命名空间,并实现类的自动加载
2、写一个trait类,理解它的功能与使用场景
【1】命名空间分级管理与类的自动加载
PHP 作为一种脚本语言,不存在程序入口,在开发中,各种初始化、业务流程都分散在各个不同的文件中,如果引用不同文件中的类,需要一堆 include 函数包含一大堆文件,这即显得笨拙,也不易于后期维护,因此,需要使用自动加载机制来完成这种引用。
实现自动加载管理,首先需要遵循相应的一些规则(主要是PSR-4):
废除了PSR-0中_就是目录分割符的写法,_下划线在完全限定类名中是没有特殊含义了。
类文件名要以 .php 结尾。
一个类存放在一个同名的文件中;
类名必须要和对应的文件名要一模一样,大小写也要一模一样。
命名空间的分层 一定要与 类文件的目录分层 完全一致。
最终实现将命名空间\类这样的类名,给转换成目录名/类名.php这样的路径,并返回完整路径。
使用自动加载需注意的细节:
____autoload函数马上要在7.2版本的PHP中弃用了,应使用spl_autoload_register()实现,它的好处是可以自定义多个autoloader;
包含spl_autoload_register()的自动加载文件,必须放在根空间下(对应系统的root目录),这样才可以管理根空间内所有的类文件;如果去加载根空间以外的类文件是会报错的。
类的自动加载不可用于PHP的CLI交互模式;
类的查找顺序:优先查找手动include或require进来的类,查找不到的情况下再采用类的自动加载机制;
如果类名比如被用于call_user_func(),则它可能包含一些危险的字符,比如 ../。 建议在这样的函数中不要使用用户的输入,起码需要验证下输入。
自动加载并不是万无一失的,有些特殊场景需单独考虑。
实例说明 (命名空间--->目录结构---->目录下类文件的对应关系):
根空间\ --------> ROOT目录 (Autoloader.php)
\inc\Controller --------> ROOT/inc/Controller目录 (Contrl.php)
\inc\model --------> ROOT/inc/model目录 (Marticle.php , Mcard.php)
\inc\view --------> ROOT/inc/view目录 (Varticle.php , Vcard.php)
实例代码:
实例 <?php class Autoloader { public static function register() { spl_autoload_register(function ($class) { $file = str_replace('\\', DIRECTORY_SEPARATOR, $class); $file = __DIR__ . '/' . $file . '.php'; if (file_exists($file)) { include $file; return true; } return false; }); } } Autoloader::register(); ?> 运行实例 » 点击 "运行实例" 按钮查看在线实例
实例 <?php namespace _1010; include 'Autoloader.php'; $a = new \inc\Controller\Contrl(); $b = new \inc\model\Marticle(); $c = new \inc\model\Mcard(); $d = new \inc\view\Varticle(); $e = new \inc\view\Vcard(); ?> 运行实例 » 点击 "运行实例" 按钮查看在线实例
【2】Trait 特性
Trait是为减少单继承语言限制,来达到多继承的效果。它可以混入不同结构独立的类中复用方法集。使用关键字“Trait”来声明,类包含的特性,Trait都支持,但不能通过自身实例化对象。
对于重名属性和方法,优先顺序是:当前类成员优先级 > Trait内成员优先级 > 所继承的父类内的成员优先级。
Trait可看作模块化的零部件,可在单个类中,用use引入多个,有成员属性冲突时,使用insteadof和as操作符解决。
以下代码演示一个Trait嵌套和混入的使用场景:
实例 <?php trait Demo1_trait { function method1() { echo 'Demo1_trait的方法:method1()'; } } trait Demo2_trait { use Demo1_trait; function method2() { echo 'Demo2_trait的方法:method2()'; } } class Demo { use Demo2_trait; } $obj = new Demo(); $obj->method1(); $obj->method2(); ?> 运行实例 » 点击 "运行实例" 按钮查看在线实例
总结:
1、使用自动加载的好处:
摆脱长长的 include() 与 require();
使用类时才会引入文件,实现了 lazy loading;
无需知道类的实际文件地址,实现了逻辑和实体文件的分离;
相比于绝对路径引入类的文件路径,自动加载机制在当类库目录名或者文件名需要更改的时候,所有include了这个文件的php文件不需要随着修改,这避免了加大源代码目录结构重构的负担;
相比于在php.ini中的include_path引入类的文件路径,自动加载的机制可以节省很多性能问题;
虽然性能和__FILE__魔术方法引入相对类路径的性能相近,但是自动加载机制可以防止或减少require_once,include_once在文件各处的随意使用,也不用计较类与类之间相互依赖的引入顺序;
可以通过带命名空间的引用和别名的方法,解决多个类重名或者同个app目录下及子目录下重名。
2、Trait就像实现某类功能的组件,可以更灵活的复用自定义功能,而不必局限与继承关系上。