命名空间(PHP 5 >= 5.3.0, PHP 7)
什么是命名空间?从广义上来说,命名空间是一种封装事物的方法。在很多地方都可以见到这种抽象概念。例如,在操作系统中目录用来将相关文件分组,对于目录中的文件来说,它就扮演了命名空间的角色。具体举个例子,文件 foo.txt 可以同时在目录/home/greg 和 /home/other 中存在,但在同一个目录中不能存在两个 foo.txt 文件。另外,在目录 /home/greg 外访问 foo.txt 文件时,我们必须将目录名以及目录分隔符放在文件名之前得到 /home/greg/foo.txt。这个原理应用到程序设计领域就是命名空间的概念。
在PHP中,命名空间用来解决在编写类库或应用程序时创建可重用的代码如类或函数时碰到的两类问题:
- 用户编写的代码与PHP内部的类/函数/常量或第三方类/函数/常量之间的名字冲突。
- 为很长的标识符名称(通常是为了缓解第一类问题而定义的)创建一个别名(或简短)的名称,提高源代码的可读性。
PHP 命名空间提供了一种将相关的类、函数和常量组合到一起的途径。
举栗子:
file.php 文件
<?php
// 使用namespace关键字定义命名空间,
// 且之前不能有东西
namespace Test;
const IN = 'oooo';
function tete()
{
return __METHOD__;
}
class lala
{
function init()
{
return __METHOD__;
}
}
autoload.php 文件
<?php
include 'file.php';
// 函数和常量是不支持use导入规则的,只有类能支持导入规则。
// 如果只是使用use Test就会报错 The use statement with non-compound name 'Test' has no effect in..
use Test\lala; // 也可以use Test\lala as lululu;
echo Test\IN."\n";
$te = new lala(); // new lululu(); // 也可以使用这样的方式来避免两个相同的类名称
总结:
- 虽然任意合法的PHP代码都可以包含在命名空间中,但只有以下类型的代码受命名空间的影响,它们是:类(包括抽象类和traits)、接口、函数和常量。
- 命名空间通过关键字namespace 来声明。如果一个文件中包含命名空间,它必须在其它所有代码之前声明命名空间,除了一个以外:declare关键字。
- 与目录和文件的关系很象,PHP 命名空间也允许指定层次化的命名空间的名称。如「namespace MyProject\Sub\Level;」
- 也可以在同一个文件中定义多个命名空间,但是要使用大括号的形式。例如:
namespace MyProject {
const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */ }
}
namespace AnotherProject {
const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */ }
}
以上这些是简单的概述,详情请移步php官网
自动加载
在编写面向对象(OOP) 程序时,很多开发者为每个类新建一个 PHP 文件。 这会带来一个烦恼:每个脚本的开头,都需要包含(include)一个长长的列表(每个类都有个文件)。例如:
<?php
include "test1.php";
include "test2.php";
include "test3.php";
......
那如何避免这种情况呢?
在 PHP 5 中,已经不再需要这样了。 spl_autoload_register() 函数可以注册任意数量的自动加载器,当使用尚未被定义的类(class)和接口(interface)时自动去加载。通过注册自动加载器,脚本引擎在 PHP 出错失败前有了最后一个机会加载所需的类。举一个栗子:
lala.php 文件
<?php
class lala
{
function init()
{
return __METHOD__;
}
}
autoload.php 文件
<?php
spl_autoload_register(function ($class_name){
// 在这里引入将要加载的类文件
// 但是有一点,加载的类文件的文件名称必须是和类名称一样
require_once $class_name.'.php';
});
$tt = new lala();
$tt->init();
现在随便一个很小的项目都需要几十个甚至几百个类,当然了不同功能的类还需要区分在不同的文件夹中,这样加载就有点麻烦了。
在这里我们引入PSR-4自动加载规范。结合上面我们所讲到的命名空间,在规范内就可以轻松解决我们内心的担忧。
.目录结构
├── App
│ └── MyClass.php
└── test.php
MyClass.php文件
<?php
namespace App;
class MyClass {
public function WhoAmI() {
return __METHOD__;
}
}
test.php文件
<?php
spl_autoload_register(function($class_name) {
require_once str_replace('\\','/',$class_name).'.php';
});
use App\MyClass as MC;
$obj = new MC();
echo $obj->WhoAmI()."\n"; // App\MyClass::WhoAmI
这只是一个简单的例子,想要了解实际项目中的自动加载的概念,可以移步composer。当然了首先要知道PSR-4的相关规范......
时2018年4月24日写