namespace 防止重名
首先,namespace就是为了解决项目中类的重名问题。 了解了目的后,就可以知道namespace的影响就 仅仅是限制在和类名相关的操作上。
1)、namespace后命名的定义不区分大小写。
这就是要求我们在定义命名空间的时候要注意别定义了相同命名空间。以下就是等效的命名空间
namespace one; namespace One; namespace ONE;
2)、没有定义命名空间,就默认理解为使用顶级命名空间。new类时,可以在类前加上反斜杠 \ ,也可以不加。
在命名空间中的定义中,针对没有命名空间的php文件,会默认虚拟一个顶层命名空间 \ 。
class Person{ function __construct(){ echo 'I am one!'; } } new Person(); //输出 I am one!; new \Person(); //输出 I am one!;
3)、如果一个类在定义的时候指定了命名空间,new类时,一定要带上指定的命名空间。
这个意思是如果这个类指定了命名空间,那么相当于在整个项目中这个类必须以命名空间的方式被声明和使用。 不能单独只依靠类名来调用了。 可以理解成名称替换,这个替换就是命名空间设计的初衷,防止类名重复。
//1.php namespace one; class Person{ function __construct(){ echo 'I am one!'; } } new \one\Person(); //输出 I am one!; new \Person(); //代码报错:Fatal error: Class 'Person' not found
4)、命名空间声明后的代码便属于这个命名空间,即使有include或require也不影响(重点是对后半句的理解,具体看代码)。
//name.php namespace test; require_once './1.php'; new \one\Person(); //成功,输出 I am one!; new \Person(); //代码报错:Fatal error: Class 'Person' not foundnew Person(); //代码报错:Fatal error: Class 'test\Person' not found
注意后另个错误,第一个错误解释器会去顶层命名空间寻找,显然不能找到抛出错误;第二个会从默认的test命名空间中寻找。
5)、namespace里不包含类名称,即使存在与类名称同名的部分,那也不代表类。new类时,还是得将这部分带上。
namespace里不要带类名称就好。
//name.php namespace test\person; class Person{ function __construct(){ echo 'I am test!'; } } new \test\person\Person(); //命名空间里person无法代表类名
6)、一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。
namespace test; require './1.php'; class Person{ function __construct(){ echo 'I am test!'; } } namespace testNew; class Person{ function __construct(){ echo 'I am testNew!'; } } new \one\Person(); //输出 I am one!; new Person(); //这里结果会是什么,自己猜猜看
总结一下:对于namespace 的掌握就是记住以下几点:
一个目的: 解决重名问题 两个默认: 默认顶层虚拟;默认当前空间寻找; 一个符号: "\"
use 简写类名
use 关键字是用来导入命名空间的,在命名空间字符串过长时,使用use可以相应的缩短命名空间。
1)、new类时,最前面无需用反斜杠。此外,use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。
namespace animal\dog; class Life{ function __construct(){ echo 'dog life!'; } } namespace animal\cat; class Life{ function __construct(){ echo 'cat life!'; } } new Life(); //按照代码执行顺序,这里默认animal\cat这个命名空间 cat life! new \animal\dog\Life(); //dog life! use animal\dog; new dog\Life(); //dog life! use animal\dog as d; new d\Life(); //dog life!
使用use后,new类时,最前面没有反斜杠。
没使用use时,命名空间最前面有反斜杠
use后没有as时,缩短的命名空间默认为最后一个反斜杠后的内容。如上的:
use animal\dog; 相当于 use animal\dog as dog;
2)、namespace后面不建议加类名,但use后可以。 。
namespace animal\dog; class Life{ function __construct(){ echo 'dog life!'; } } namespace animal\cat; class Life{ function __construct(){ echo 'cat life!'; } } use animal\dog\Life as dog; new dog();
如上所示,use后加上类名后,就相当于把类改了个名称:由Life改为dog了。
使用use后,这个昵称对应的类只能归当前命名空间占有,其它命名空间下不允许存在该类。
简单总结一下:
namespace就是划分领域的作用,代表这些东西是属于某个命名空间下的。
use就是起小名的作用,不论写起来还是说起来都可以省不少事儿。
psr-2的相关规定 :
命名空间(namespace)的声明后面必须有一行空行。 所有的导入(use)声明必须放在命名空间(namespace)声明的下面。 一句声明中,必须只有一个导入(use)关键字。 在导入(use)声明代码块后面必须有一行空行。
require 导入文件
通过上面的介绍,我们了解到了类的名称在使用时候的方法。但是无论namespace 还是use 都不能真的找到这个php文件把代码引入,可以看上面的每段代码都有require 的使用。下面看一个例子
//1.php <?php $b = require('ext.php'); echo "---------\r\n"; echo $_SERVER['SCRIPT_FILENAME']; //ext.php <?php echo $_SERVER['SCRIPT_FILENAME']; echo 'I am ext!'; 执行1.php,输出结果: ./1.php I am ext! --------- ./1.php
从这里可以看到require导入后,代码识别的脚本是导入后的。从这个角度也可以部分理解require是对导入文件直接替换。
但是当有命名空间就不一样了。并不是简单替换,而是引入保存了命名空间的属性。
手动引入会使得开发者崩溃的,这时候命名空间和导入就可以结合起来。
psr-4
在说啥是PSR-[0-4]规范的之前,我觉得我们有必要说下它的发明者和规范者:PHP-FIG,它的网站是:www.php-fig.org。
FIG 是 Framework Interoperability Group(框架可互用性小组)的缩写,由几位开源框架的开发者成立于 2009 年,从那开始也选取了很多其他成员进来,虽然不是 “官方” 组织,但也代表了社区中不小的一块。组织的目的在于:以最低程度的限制,来统一各个项目的编码规范,避免各家自行发展的风格阻碍了程序设计师开发的困扰,于是大伙发明和总结了PSR,PSR是Proposing a Standards Recommendation(提出标准建议)的缩写,PSR-[0-4] 规范如下:
PSR-0 (Autoloading Standard) 自动加载标准 (已废弃) PSR-1 (Basic Coding Standard) 基础编码标准 PSR-2 (Coding Style Guide) 编码风格向导 PSR-3 (Logger Interface) 日志接口 PSR-4 (Improved Autoloading) 自动加载的增强版,可以替换掉PSR-0了。
虽然psr-0 已经被废弃,但是还是应该先看psr-0协议:
1. 一个完全合格的namespace和class必须符合这样的结构:“\< Vendor Name>(< Namespace>)*< Class Name>” 2. 每个namespace必须有一个顶层的namespace("Vendor Name"提供者名字) 3. 每个namespace可以有多个子namespace 4. 当从文件系统中加载时,每个namespace的分隔符(/)要转换成 DIRECTORY_SEPARATOR(操作系统路径分隔符) 5. 在类名中,每个下划线(_)符号要转换成DIRECTORY_SEPARATOR(操作系统路径分隔符)。在namespace中,下划线(_)符号是没有(特殊) 意义的。 6. 当从文件系统中载入时,合格的namespace和class一定是以 .php 结尾的 7. verdor name,namespaces,class名可以由大小写字母组合而成(大小写敏感的)
psr-1 规范
1. PHP源文件必须只使用 <?php 和 <?= 这两种标签。 2. 源文件中php代码的编码格式必须是不带字节顺序标记(BOM)的UTF-8。 3. 一个源文件建议只用来做声明(类(class),函数(function),常量(constant)等)或者只用来做一些引起副作用的操作(例如:输出信 息,修改.ini配置等),但不建议同时做这两件事。 4. 命名空间(namespace)和类(class) 必须遵守PSR-0标准。 5. 类名(class name) 必须使用骆驼式(StudlyCaps)写法 (注:驼峰式(cameCase)的一种变种,后文将直接用StudlyCaps表示)。 6. 类(class)中的常量必须只由大写字母和下划线(_)组成。 7. 方法名(method name) 必须使用驼峰式(cameCase)写法。
psr-4
1. 废除了PSR-0中_就是目录分割符的写法,_下划线在完全限定类名中是没有特殊含义了。 2. 类文件名要以 .php 结尾。 3. 类名必须要和对应的文件名要一模一样,大小写也要一模一样。
自动加载
spl_autoload_register 函数的功能就是把传入的函数(参数可以为回调函数或函数名称形式)注册到 SPL __autoload 函数队列中,并移除系统默认的 __autoload() 函数。
一旦调用 spl_autoload_register() 函数,当调用未定义类时,系统就会按顺序调用注册到 spl_autoload_register() 函数的所有函数,而不是自动调用 __autoload() 函数。
如果命名能遵守统一的约定,就可以让自动加载器自动解析判断类文件所在的路径。接下来要介绍的PSR-4 就是一种被广泛采用的约定方式。
new 百度\李彦宏(); // 限定类名 new \百度\李彦宏(); // 完全限定类名
如果一个文件中包含命名空间,它必须在其它所有代码之前声明命名空间。
在当前命名空间没有声明的情况下,限定类名和完全限定类名是等价的。因为如果不指定空间,则默认为全局(\)。
=================PSR-4规范==================
PSR-4 是关于由文件路径自动载入对应类的相关规范,规范规定了一个完全限定类名需要具有以下结构:
\<顶级命名空间>(\<子命名空间>)*\<类名>
如果继续拿上面的例子打比方的话,顶级命名空间相当于公司,子命名空间相当于职位,类名相当于人名。那么李彦宏标准的称呼为 "百度公司 CEO 李彦宏"。
PSR-4 规范中必须要有一个顶级命名空间,它的意义在于表示某一个特殊的目录(文件基目录)。子命名空间代表的是类文件相对于文件基目录的这一段路径(相对路径),类名则与文件名保持一致(注意大小写的区别)。
举个例子:在全限定类名 \app\view\news\Index 中,如果 app 代表 C:\Baidu,那么这个类的路径则是 C:\Baidu\view\news\Index.php
PHP实例化一些类的时候为啥要加上 \
实例化对象前面加\表示的是,在命名空间中使用原生的类,如果没有使用命名空间的话,可以把前面的\给删除掉
将php原生语句实例化SphinxClient对象移植到yii2框架中报错 原生语句中这样写: $s = new SphinxClient(); 框架中应该加入反斜杠,这样写: $s = new \SphinxClient(); 其他php内置对象实例化一样参考上述方法。 和命名空间有关,因为原生的php没有用到命名空间,框架中启用了,会当前命名空间中寻找这个类,找不到会报错。 tp5 new 实例化 加反斜杠 和不加反斜杠的区别 thinkphp5遇到 实例化类问题 new \className();和 new className();的区别 new className(); 不带反斜杠, 会报错 。 new \className(); 带反斜杠, 就好了 。带反斜杠应该是:引用包含的文件路径require_once("vendor/taobaokeapi/tbk.php"); 就可以了 如果controller里面没有这个类,调用自己包含的文件 实例化是就带反斜杠 ,如果有就不需要反斜杠
参考:
php 中namespace、use 、require 和自动加载
本文为崔凯原创文章,转载无需和我联系,但请注明来自冷暖自知一抹茶ckhttp://www.cksite.cn