PHP进阶学习之命名空间基本用法分析


Posted in PHP onJune 18, 2019

本文实例讲述了PHP进阶学习之命名空间基本用法。分享给大家供大家参考,具体如下:

前言

命名空间(namespace),在编程语言中,是对作用域的一种特殊的抽象.它表示着一个标识符的可见范围。一个标识符可在多个命名空间中定义,它在不同命名空间中的含义是互不相干的。这样,在一个新的命名空间中可定义任何标识符,它们不会与任何已有的标识符发生冲突,因为已有的定义都处于其他命名空间中。

在PHP中也存在命名空间的用法,由它控制可见范围的这个标识符一般指的就是类和函数。

一、PHP命名空间基础

从广义上来说,命名空间是一种封装事物的方法。在很多地方都可以见到这种抽象概念。例如PHP的类名是不可以重复的,但是经常我们需要引入一些第三方的类库,常常类名就会在项目中产生重复冲突,所以,命名空间就是解决这个冲突的一种方法。

在PHP5.3以后,就已经引入了命名空间(namespace)的概念,即同个命名空间下的类名不能重复,不同命名空间下可以存在同名的类。

这样,在引入第三方类库的时候,只有各个类库的命名空间不一样,就不会产生冲突。

所以根据官方所说,在PHP中,命名空间用来解决在编写类库或应用程序时创建可重用的代码如类或函数时碰到的两类问题:

1、用户编写的代码与PHP内部的类/函数/常量或第三方类/函数/常量之间的名字冲突。
2、为很长的标识符名称(通常是为了缓解第一类问题而定义的)创建一个别名(或简短)的名称,提高源代码的可读性。

需要注意的是:

  • 同个文件下可以存在多个命名空间;
  • 不同命名空间内的类可以相互调用。

PHP进阶学习之命名空间基本用法分析

二、PHP命名空间的用法

1、定义

命名空间的定义采用关键字namespace,定义方式如下:

namespace example

则该命名空间下的类都归属于该命名空间,example命名空间下的类不能重名。

或者可以定义多级命名空间:

namespace example\test\demo

则改命名空间下的类全归属于example\test\demo命名空间。

定义后的命名空间可以用_​_​NAMESPACE_​_​魔法变量来获取当前命名空间。

2、引入

引入命名空间使用关键字use,可以通过多个use在一个文件中引入多个命名空间:

use example;
use example\test\demo;

需要使用到哪个命名空间的类和方法,则use哪个命名空间,前提是这些命名空间的实际文件地址已经包含进来了,或者说能实现自动的类加载了。

3、实例化

在程序中实例化并使用某个命名空间下的类方法,同样使用new关键字进行实例化,但是需要在类名前面加上命名空间前缀。

例如:

$class = new example\a();//实例化example命名空间下的a类
$class = new example\test\demo\b(); //实例化example\test\demo命名空间下的b类

如果在文件前面已经引入了这些命名空间,则可以不需要类的前缀:

use example;
use example\test\demo;
$class = new a();//实例化example命名空间下的a类
$class = new b(); //实例化example\test\demo命名空间下的b类

注:如果use的时候是use example\test;则在实例化b类时要带上相对命名空间路径(注意不是实际文件路径),即new demo\b();

当然所有的实例化都可以直接使用绝对路径形式,即在命名空间前面加\字符,如new \example\test\demo\b();这样就采用了绝对路径形式实例化了b类。

4、别名

在用namespace定义命名空间的时候,为了避免之后引用的时候命名空间过长,可以在定义时采用as关键字为一个命名空间指定别名

namespace example\test\demo as testDemo;

这样在之后引用或实例化的时候就可以new testDemo\<类名>();

三、基于PSR4的命名空间规范

由于方法、类在不同项目中命名空间定义不一致,第三方类库的命名空间也定义不一致,所以相关php组织出台了一套约定俗成的规范,即PSR4规范,

用来规范命名空间的定义规则。

具体规范如下:

1. 一个完整的类名需具有以下结构:

\<命名空间>(\<子命名空间>)*\<类名>
    1. 完整的类名 必须 要有一个顶级命名空间,被称为 "vendor namespace";
    2. 完整的类名 可以 有一个或多个子命名空间;
    3. 完整的类名 必须 有一个最终的类名;
    4. 完整的类名中任意一部分中的下滑线都是没有特殊含义的;
    5. 完整的类名 可以 由任意大小写字母组成;
    6. 所有类名都 必须 是大小写敏感的。

2. 当根据完整的类名载入相应的文件

    (1). 完整的类名中,去掉最前面的命名空间分隔符,前面连续的一个或多个命名空间和子命名空间,作为「命名空间前缀」,其必须与至少一个「文件基目录」相对应;
    (2). 紧接命名空间前缀后的子命名空间 必须 与相应的「文件基目录」相匹配,其中的命名空间分隔符将作为目录分隔符。
    (3). 末尾的类名 必须 与对应的以 .php 为后缀的文件同名。
    (4). 自动加载器(autoloader)的实现 一定不可 抛出异常、一定不可 触发任一级别的错误信息以及 不应该 有返回值。

看起来很复杂,其实规范的要点就是,命名空间的路径要与当前文件的路径相对应,这样规范了所有项目命名空间的定义准则,虽然PHP官方没有

强制规定,但如今许多开源项目都已经约定俗成地使用了,这种规范便于查找命名空间下的类所在的路径。

例如,文件目录a/b/c下有d.php,则在a目录下的的文件引入d的类时,应该是use b/c或use /a/b/c;(绝对路径形式)

四、注意点

1、代码复用类Trait也符合命名空间的规范,即通过命名空间下Trait类不能重名;
2、虽然PSR4规定了命名空间路径与文件路径需要相对应,但是运行php时命名空间路径与文件路径是没有任何关系的,例如a/b/c下的文件类d,命名空间可以写成a1/b1/c1/d;只不过现在的许多开源框架在实现类自动加载的时候把两者规范为一致,否则会出现类文件加载到了,但是命名空间却加载不到的情况。
3、在命名空间内部,所有的没有根据导入规则转换的限定名称均会在其前面加上当前的命名空间名称。例如,在命名空间A\B内部调用C\D\e(),则C\D\e()会被转换为A\B\C\D\e()。
4、在命名空间内部(例如A\B),对非限定名称的函数调用是在运行时解析的。例如对函数foo()的调用是这样解析的:
(1)在当前命名空间中查找名为A\B\foo()的函数
(2)尝试查找并调用全局(global)空间中的函数foo()。
5、在命名空间(例如A\B)内部对非限定名称或限定名称类(非完全限定名称)的调用是在运行时解析的。下面是调用new C()及new D\E()的解析过程:new C()的解析:
(1)在当前命名空间中查找A\B\C类。
(2)尝试自动装载类A\B\C。

以上内容引用了PSR4文档地址:http://www.php-fig.org/psr/psr-4/

希望本文所述对大家PHP程序设计有所帮助。

PHP 相关文章推荐
PHP的FTP学习(一)
Oct 09 PHP
我的论坛源代码(十)
Oct 09 PHP
关于PHP5 Session生命周期介绍
Mar 02 PHP
深入解析yii权限分级式访问控制的实现(非RBAC法)
Jun 13 PHP
ThinkPHP CURD方法之field方法详解
Jun 18 PHP
PHP使用range协议实现输出文件断点续传代码实例
Jul 04 PHP
PHP图片处理之图片旋转和图片翻转实例
Nov 19 PHP
php通过递归方式复制目录和子目录的方法
Mar 13 PHP
修改Laravel5.3中的路由文件与路径
Aug 10 PHP
Yii2 hasOne(), hasMany() 实现三表关联的方法(两种)
Feb 15 PHP
PHP获取文本框、密码域、按钮的值实例代码
Apr 19 PHP
ThinkPHP实现转换数据库查询结果数据到对应类型的方法
Nov 16 PHP
PHP进阶学习之反射基本概念与用法分析
Jun 18 #PHP
Laravel使用RabbitMQ的方法示例
Jun 18 #PHP
thinkphp整合系列之极验滑动验证码geetest功能
Jun 18 #PHP
PHP Trait代码复用类与多继承实现方法详解
Jun 17 #PHP
php设计模式之装饰模式应用案例详解
Jun 17 #PHP
php设计模式之策略模式应用案例详解
Jun 17 #PHP
PHP实现将上传图片自动缩放到指定分辨率,并保持清晰度封装类示例
Jun 17 #PHP
You might like
在PHP中使用XML
2006/10/09 PHP
《PHP边学边教》(02.Apache+PHP环境配置――下篇)
2006/12/13 PHP
UCenter Home二次开发指南
2009/05/28 PHP
PHP原理之异常机制深入分析
2010/08/08 PHP
PHP中使用mktime获取时间戳的一个黑色幽默分析
2012/05/31 PHP
jquery 日期分离成年月日的代码
2010/05/14 Javascript
js特效,页面下雪的小例子
2013/06/17 Javascript
jquery自定义下拉列表示例
2014/04/25 Javascript
js获取所有checkbox的值的简单实例
2016/05/30 Javascript
Jquery实现上下移动和排序代码
2016/10/17 Javascript
jQuery中extend函数简单用法示例
2017/10/11 jQuery
对vue里函数的调用顺序介绍
2018/03/17 Javascript
解决Nodejs全局安装模块后找不到命令的问题
2018/05/15 NodeJs
JS中FormData类实现文件上传
2020/03/27 Javascript
python3图片转换二进制存入mysql
2013/12/06 Python
Python随机生成信用卡卡号的实现方法
2015/05/14 Python
python结合opencv实现人脸检测与跟踪
2015/06/08 Python
深入浅析ImageMagick命令执行漏洞
2016/10/11 Python
python如何制作缩略图
2019/04/30 Python
在python下使用tensorflow判断是否存在文件夹的实例
2019/06/10 Python
安装Pycharm2019以及配置anconda教程的方法步骤
2019/11/11 Python
python 实现屏幕录制示例
2019/12/23 Python
澳大利亚正品化妆品之家:Cosmetic Capital
2017/07/03 全球购物
SheIn沙特阿拉伯:女装在线
2020/03/23 全球购物
自考生自我鉴定范文
2013/10/01 职场文书
行政人事经理职位说明书
2014/03/05 职场文书
三分钟自我介绍演讲稿
2014/08/21 职场文书
励志演讲稿3分钟
2014/08/21 职场文书
2014年重阳节老干部座谈会上的讲话稿
2014/09/25 职场文书
思想纪律作风整顿剖析材料
2014/10/11 职场文书
机关职员工作检讨书
2014/10/23 职场文书
奖学金个人总结
2015/03/04 职场文书
房贷工资证明范本
2015/06/12 职场文书
新年祝酒词大全
2015/08/11 职场文书
2015中秋祝酒词
2015/08/12 职场文书
基于Redis zSet实现滑动窗口对短信进行防刷限流的问题
2022/02/12 Redis