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 相关文章推荐
COM in PHP (winows only)
Oct 09 PHP
PHP 类型转换函数intval
Jun 20 PHP
php set_time_limit(0) 设置程序执行时间的函数
May 26 PHP
shopex中集成的站长统计功能的代码简单分析
Aug 11 PHP
如何使用PHP批量去除文件UTF8 BOM信息
Aug 05 PHP
php检测iis环境是否支持htaccess的方法
Feb 18 PHP
php数组索引与键值操作技巧实例分析
Jun 24 PHP
Symfony2框架创建项目与模板设置实例详解
Mar 17 PHP
详解PHP实现定时任务的五种方法
Jul 25 PHP
PHP实现从PostgreSQL数据库检索数据分页显示及根据条件查找数据示例
Jun 09 PHP
详解PHP神奇又有用的Trait
Mar 25 PHP
使用git迁移Laravel项目至新开发环境的步骤详解
Apr 06 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+js实现图片的上传、裁剪、预览、提交示例
2013/08/27 PHP
php多文件上传实现代码
2014/02/20 PHP
跟我学Laravel之请求(Request)的生命周期
2014/10/15 PHP
浅析ThinkPHP缓存之快速缓存(F方法)和动态缓存(S方法)(日常整理)
2015/10/26 PHP
Smarty日期时间操作方法示例
2016/11/15 PHP
PHP封装的PDO数据库操作类实例
2017/06/21 PHP
将查询条件的input、select清空
2014/01/14 Javascript
JQuery给网页更换皮肤的方法
2015/05/30 Javascript
jQuery实现指定内容滚动同时左侧或其它地方不滚动的方法
2015/08/08 Javascript
JS中innerHTML和pasteHTML的区别实例分析
2016/06/22 Javascript
Javascript将JSON日期格式化
2016/08/23 Javascript
浅析如何利用angular结合translate为项目实现国际化
2016/12/08 Javascript
javascript图片预览和上传(兼容IE)
2017/03/15 Javascript
微信小程序自定义模态对话框实例详解
2017/08/16 Javascript
对vue 键盘回车事件的实例讲解
2018/08/25 Javascript
Vuejs监听vuex中值的变化的方法示例
2018/12/02 Javascript
JS实现的检验身份证格式并输出出生日期,年龄,性别,出生地示例
2019/05/17 Javascript
vue2 中二级路由高亮问题及配置方法
2019/06/10 Javascript
JS实现页面跳转与刷新的方法汇总
2019/08/30 Javascript
Vue Router 实现动态路由和常见问题及解决方法
2020/03/06 Javascript
基于JavaScript实现贪吃蛇游戏
2020/03/16 Javascript
前端使用crypto.js进行加密的函数代码
2020/08/16 Javascript
python日志记录模块实例及改进
2017/02/12 Python
python3中的md5加密实例
2018/05/29 Python
jupyter lab的目录调整及设置默认浏览器为chrome的方法
2020/04/10 Python
scrapy中如何设置应用cookies的方法(3种)
2020/09/22 Python
Python Web项目Cherrypy使用方法镜像
2020/11/05 Python
详解用 python-docx 创建浮动图片
2021/01/24 Python
CSS超出文本指定宽度用省略号代替和文本不换行
2016/05/05 HTML / CSS
中科前程Java笔试题
2016/11/20 面试题
洗煤厂厂长岗位职责
2014/01/03 职场文书
军神教学反思
2014/02/04 职场文书
总经理检讨书
2014/09/15 职场文书
工程技术员岗位职责
2015/04/11 职场文书
Java基于字符界面的简易收银台
2021/06/26 Java/Android
Redis 中使用 list,streams,pub/sub 几种方式实现消息队列的问题
2022/03/16 Redis