什么是命名空间?
参考:http://php.net/manual/zh/language.namespaces.rationale.php
(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
命名空间提供了一种将相关的类、函数和常量组合到一起的途径。
未引入命名空间时的解决类冲突的做法
通过require 引入需要用到的类
src/Person.php
<?php
class Person
{
protected $name;
public function __construct($name)
{
$this->name = $name;
}
}
src/Business.php
<?php
class Business
{
protected $staff;
public function __construct(Staff $staff)
{
$this->staff = $staff;
}
public function hire(Person $person)
{
$this->staff->add($person);
}
}
src/Staff.php
<?php
class Staff
{
protected $members = [];
public function add(Person $person)
{
$this->members[] = $person;
}
}
require 'src/Person.php';
require 'src/Business.php';
require 'src/Staff.php';
$liang = new Person('liang');
$staff = new Staff();
$business = new Business($staff);
$business->hire($liang);
var_dump($staff);
PHP的自动加载 spl_autoload_register
spl_autoload_register函数是实现自动加载未定义类功能的的重要方法。
自动加载就是我们new一个类时PHP会自动帮我们加载依赖的类。
参考http://php.net/manual/zh/function.spl-autoload-functions.php
上面的例子可以简化成这样
spl_autoload_register(function($classNmae){
require 'src/' . $classNmae . '.php';
});
$liang = new Person('liang');
$staff = new Staff();
$business = new Business($staff);
$business->hire($liang);
var_dump($staff);
利用PSR4规范进行自动加载
什么是PSR4规范
PSR4描述了从文件路径自动加载类的规范。
-
术语“类”指的是类,接口,特征和其他类似结构。
-
完全限定的类名具有以下形式:
-
\<NamespaceName>(\<SubNamespaceNames>)*\<ClassName>
-
完全限定的类名必须具有顶级命名空间名称,也称为“供应商命名空间”。
-
完全限定的类名可以具有一个或多个子命名空间名称。
-
完全限定的类名必须具有终止类名。
-
下划线在完全限定类名的任何部分都没有特殊含义。
-
完全限定类名中的字母字符可以是小写和大写的任意组合。
-
必须以区分大小写的方式引用所有类名。
-
-
当从完全限定类名载入文件时:
- 在完全限定类名中,连续的一个或几个子命名空间构成的命名空间前缀(不包括顶级命名空间的分隔符),至少对应着至少一个基础目录。
- 在「命名空间前缀」后的连续子命名空间名称对应一个「基础目录」下的子目录,其中的命名 空间分隔符表示目录分隔符。子目录名称必须和子命名空间名大小写匹配;
- 终止类名对应一个以 .php 结尾的文件。文件名必须和终止类名大小写匹配;
-
自动载入器的实现不可抛出任何异常,不可引发任何等级的错误;也不应返回值;
利用composer完成自动加载
- 给src/Person.php src/Business.php src/Staff.php加上namespace liang
- 编写composer.json文件
{
"autoload":{
"psr-4":{
"liang\\" : "src/"
}
}
}
“liang\” : “src/” 根据psr4规范将命名空间liang 映射到 src路径
-
执行 composer dump-autoload 命令
会生成vendor目录
-
在sample.php中
require 'vendor/autoload.php'
即可利用psr4规范完成加载
sample.php
require 'vendor/autoload.php';
use liang\Person;
use liang\Staff;
use liang\Business;
$liang = new Person('liang');
$staff = new Staff();
$business = new Business($staff);
$business->hire($liang);
var_dump($staff);