php 中namespace、use 、require 和自动加载

image.png

namespace 防止重名

首先,namespace就是为了解决项目中类的重名问题。 了解了目的后,就可以知道namespace的影响就 仅仅是限制在和类名相关的操作上。

  • namespace后命名的定义不区分大小写。这就是要求我们在定义命名空间的时候要注意别定义了相同命名空间。以下就是等效的命名空间
namespace one;
namespace One;
namespace ONE;
  • 和Linux文件目录不同的事命名空间采用的事反斜杠 ""。
  • 没有定义命名空间,就默认理解为使用顶级命名空间。在命名空间中的定义中,针对没有命名空间的php文件,会默认虚拟一个顶层命名空间 \ 。
  • 如果一个类在定义的时候指定了命名空间,new类时,一定要带上指定的命名空间。 这个意思是如果这个类指定了命名空间,那么相当于在整个项目中这个类必须以命名空间的方式被声明和使用。 不能单独只依靠类名来调用了。 可以理解成名称替换,这个替换就是命名空间设计的初衷,防止类名重复。
//1.php   
namespace one;
class Person{
    function __construct(){
            echo 'I am one!';
        }
}
//name.php
require_once './1.php';
new \one\Person(); //输出 I am one!;使用person需要这样来声明,在项目中person的名字被固定成这个样子。
  • 在使用命名命名空间的时候,如果直接new 一个类,PHP解释器会默认尝试在当前命名空间中寻找这个类,如果能找到就new成功,如果失败就抛出错误
//1.php   
namespace one;
class Person{
   function __construct(){
           echo 'I am one!';
       }
}
//name.php
namespace test;
require_once './1.php';
new \one\Person(); //成功,输出 I am one!;
new \Person(); //代码报错:Fatal error: Class 'Person' not found
new Person(); //代码报错:Fatal error:  Class 'test\Person' not found

注意后另个错误,第一个错误解释器会去顶层命名空间寻找,显然不能找到抛出错误;第二个会从默认的test命名空间中寻找。

对于同一上面的name。php ,如果去掉了namespace test;这段会怎么样呢。结果如下,可以看到此时没有显示声明命名空间,那么久开始选用默认顶层命名空间,所以后面连个的结果是一样的。

//name.php
namespace test;
require_once './1.php';
new \one\Person(); //成功,输出 I am one!;
new \Person(); //代码报错:Fatal error: Class 'Person' not found
new Person(); //代码报错:Fatal error:  Class 'Person' not found
  • 一个php文件中可以存在多个命名空间,第一个命名空间前不能有任何代码。(这个不常用,不建议这样编码)

总结一下:对于namespace 的掌握就是记住以下几点:

一个目的: 解决重名问题
两个默认: 默认顶层虚拟;默认当前空间寻找;
一个符号:  "\"

use 简写类名

use 关键字是用来导入命名空间的,或者说就是偷懒简写类名的功能,他并不能加载文件,加载还要靠其他机制。 从上面的namespace的介绍中,我们已经可以避免重名这个现象了。但是人们总是偷懒的,每次声明一个类的时候还需要写那么长的命名空间是不能忍受的,隐藏use 和as 就登场了

use one;
require_once './1.php';
new Person();

psr-2的相关规定 :

命名空间(namespace)的声明后面必须有一行空行。
所有的导入(use)声明必须放在命名空间(namespace)声明的下面。
一句声明中,必须只有一个导入(use)关键字。
在导入(use)声明代码块后面必须有一行空行。

require 导入文件

通过上面的介绍,我们了解到了类的名称在使用时候的方法。但是无论namespace 还是use 都不能真的找到这个php文件把代码引入,可以看上面的每段代码都有require 的使用。下面看一个例子

1.php

ext.php

输出

./1.php
I am ext!
---------
./1.php
  • 从这里可以看到require导入后,代码识别的脚本是导入后的。从这个角度也可以部分理解require是对导入文件直接替换。
  • 但是当有命名空间就不一样了。并不是简单替换,而是引入保存了命名空间的属性。

手动引入会使得开发者崩溃的,这时候命名空间和导入就可以结合起来。

psr-4

在说啥是PSR-[0-4]规范的之前,我觉得我们有必要说下它的发明者和规范者:PHP-FIG,它的网站是:www.php-fig.org。就是这个联盟组织发明和创造了PSR-[0-4]规范,膜拜吧,屌丝们!

FIG 是 Framework Interoperability Group(框架可互用性小组)的缩写,由几位开源框架的开发者成立于 2009 年,从那开始也选取了很多其他成员进来,虽然不是 “官方” 组织,但也代表了社区中不小的一块。组织的目的在于:以最低程度的限制,来统一各个项目的编码规范,避免各家自行发展的风格阻碍了程序设计师开发的困扰,于是大伙发明和总结了PSR,PSR是Proposing a Standards Recommendation(提出标准建议)的缩写,截止到目前为止,总共有5套PSR规范,分别是:

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源文件必须只使用 

psr-4

1. 废除了PSR-0中_就是目录分割符的写法,_下划线在完全限定类名中是没有特殊含义了。 
2. 类文件名要以 .php 结尾。 
3. 类名必须要和对应的文件名要一模一样,大小写也要一模一样。

自动加载

由于时间原因可以暂时先看这篇博客

https://www.cnblogs.com/woider/p/6443854.html

【参考资料】

https://www.cnblogs.com/drunkhero/p/namespace.html

https://www.cnblogs.com/JohnABC/p/6595075.html

https://www.cnblogs.com/woider/p/6443854.html

https://www.php-fig.org/psr/psr-0/ psr-0 官方文档

你可能感兴趣的:(php 中namespace、use 、require 和自动加载)