namespace 只是创建一个命名空间
use 只是导入一个命名空间
namespace 、use 都没有加载动作,和require、require_once、include、include_once没有关联
命名空间必须符合PSR4规范,即命名空间和文件路径要相对应
要说清楚这三个的关系,还得慢慢说。
首先说下php的命名空间:
php 命名空间中的类名可以通过三种方式引用:
1、非限定名称,或不包含前缀的类名称
例如:$a = new foo(); 或 foo::staticmethod();
如果当前命名空间是 currentnamespace,foo 将被解析为 currentnamespace\foo
如果使用 foo 的代码是全局的,不包含在任何命名空间中的代码,则 foo 会被解析为 foo
警告:如果命名空间中的函数或常量未定义,则该非限定的函数名称或常量名称会被解析为全局函数名称或常量名称
2、限定名称,或包含前缀的类名称
例如:$a = new subnamespace\foo(); 或 subnamespace\foo::staticmethod();
如果当前命名空间是 currentnamespace,foo 将被解析为 currentnamespace\subnamespace\foo
如果使用 foo 的代码是全局的,不包含在任何命名空间中的代码,则 foo 会被解析为 subnamespace\foo
3、完全限定名称,或包含了全局前缀操作符的名称
例如:$a = new \currentnamespace\foo(); 或 \currentnamespace\foo::staticmethod();
在这总情况下,foo 总是被解析为代码中的文件名 (literal name)currentnamespace\foo
namespace A;//当前命名空间
new foo(); // A\foo (实际解析结果)
new \foo(); // foo (实际解析结果)
namespace A;//当前命名空间
/* 导入命名空间 */
use X\Y\foo;
new foo(); // X\Y\foo (实际解析结果)
new \foo(); // foo (实际解析结果)
new \Z\foo(); // Z\foo (实际解析结果)
namespace A;//当前命名空间
/* 导入命名空间并且使用别名 */
use X\Y\foo as Q;
new Q(); // X\Y\foo (实际解析结果)
new \foo(); // foo (实际解析结果)
new \Z\foo(); // Z\foo (实际解析结果)
命名空间的顺序:
名称解析遵循下列规则:
接下来,说下php的自动加载机制:
在类的实例化过程中,系统做的工作大致是这样:
/* 模拟系统实例化过程 */
function instance($className)
{
// 如果类存在则返回其实例
if (class_exists($className, false)) {
return new $className();
}
// 查看 autoload 函数是否被用户定义
if (function_exists('__autoload')) {
__autoload($className); // 最后一次引入的机会
}
// 再次检查类是否存在
if (class_exists($className, false)) {
return new $className();
} else {
// 系统:我实在没辙了
throw new Exception('Class '.$className.' Not Found');
}
}
这里要特别说明下,__autoload()是魔术方法,在php源码中是个空方法!
(php 的 魔术方法基本上都是空方法,相当于一个拦截器,拦住后具体要干什么还是要自定义的,否则什么都不干)
换句话说,如果找不到类,会自动调用方法__autoload(),但仅此而已!php原本不会自动加载文件的!
要想实现真正的类自动加载,还是要重写这个方法,在里面写 require 或 include 加载语句的!
命名空间和自动加载的关系:
在类实例化过程中,如果找不到类,自动加载机制会根据命名空间组合$className,并自动调用方法__autoload(),将$className作为参数,传入__autoload()
自动加载的历史发展:
直接在文件里写多条require/include加载语句
-> __autoload() 自动加载
-> spl_autoload_register() 注册自动加载
-> composer自动加载