博客列表 >PHP命名空间分级管理及trait类的使用场景--2019年10月10日

PHP命名空间分级管理及trait类的使用场景--2019年10月10日

Victor的博客
Victor的博客原创
2019年10月16日 02:15:441774浏览

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就像实现某类功能的组件,可以更灵活的复用自定义功能,而不必局限与继承关系上。




声明:本文内容转载自脚本之家,由网友自发贡献,版权归原作者所有,如您发现涉嫌抄袭侵权,请联系admin@php.cn 核实处理。
全部评论
文明上网理性发言,请遵守新闻评论服务协议