Correcting teacher:天蓬老师
Correction status:qualified
Teacher's comments:能完全 把命名空间理解 , 也不简单
非限定名称
完全限定名称
非完全限定名称
全局成员的四大家族: 类, 接口, 函数和常量.
namespace ns1 {
require('../../out.php');
class Demo1
{
public static $prop1 = 'hello';
public static function func1()
{
return __METHOD__;
}
}
// 在当前命名空间中使用本命名空间的成员, 可以省略当前空间名称, 即使用非限定名称即可.
/* Demo1::$prop1 等效于 \ns1\Demo1::$prop1 */
echobr(Demo1::$prop1);
/* Demo1::func1() 等效于 \ns1\Demo1::func1() */
echobr(Demo1::func1());
/* result:
hello
ns1\Demo1::func1
*/
}
namespace ns2\ns2_1 {
const PI = 3.14;
class Demo1
{
public static $prop = 'hi';
public static function func1()
{
return __METHOD__;
}
}
}
namespace ns2 {
// 访问其他命名空间中的成员, 需要使用完全限定名称
echobr(\ns1\Demo1::$prop1);
echobr(\ns1\Demo1::func1());
/* result:
hello
ns1\Demo1::func1
*/
// 访问具有层级关系的下级命名空间中的成员时, 可以使用非完全限定名称
echobr(ns2_1\Demo1::$prop);
echobr(ns2_1\Demo1::func1());
echobr(ns2_1\PI);
/* result:
hi
ns2\ns2_1\Demo1::func1
3.14
*/
}
__NAMESPACE__
.namespace
关键字创建命名空间创建命名空间的语法
创建语法 1:
namespace 命名空间名称;
// do something...
这种方式只能创建命名空间, 不能创建匿名空间. 匿名空间就是默认空间, 根空间, 全局空间.
/* 创建命名空间 */
namespace ns1;
// do something...
/* 这样创建匿名空间会报错 */
namespace ;
// can not do something...
创建语法 2:
namespace 命名空间名称 {
// do something...
}
这种方式可以创建命名空间和匿名空间
/* 创建命名空间 */
namespace ns1 {
// do something...
}
/* 创建全局空间 */
namespace {
// 这里是全局空间
}
/* 全局空间 */
namespace {
$username = '张三';
function sayHello($username)
{
echobr('hello ' . $username);
}
class Demo
{
public static $prop = 'hello';
}
}
/* 非全局命名空间 */
namespace np1 {
// 当前命名空间中并没有$username变量, PHP会到全局空间中去找该变量
echobr($username);
/* result: 张三 */
// 跟变量类似
sayHello('James');
/* result: hello James */
// 当前控件没有Demo类, 但PHP也不会到全局空间中查找, 直接报错
echobr(Demo::$props);
/* result: Fatal error: Uncaught Error: Class 'np1\Demo' not found in D:\phpstudy_pro\WWW\php11\PHP\0505\homework\homework.php:112 Stack trace: #0 {main} thrown in D:\phpstudy_pro\WWW\php11\PHP\0505\homework\homework.php on line 112 */
}
/* 命名空间中有跟根空间同名的成员 */
namespace np2 {
CONST NAME = 'lisi';
function sayHello($username) {
echobr('hi ' . $username);
}
class Demo {
public static $prop = 'hi';
}
// 当前命名空间中已有相关成员的情况
/* 使用当前命名空间中的常量 */
echobr(NAME);
/* 使用根空间中的同名常量 */
echobr(\NAME);
/* result:
lisi
全局
*/
/* 使用当前命名空间的函数 */
sayHello('Marry');
/* 使用根空间中的同名函数 */
\sayHello('Lily');
/* result:
hi Marry
hello Lily
*/
/* 使用当前命名空间中的类 */
echobr(Demo::$prop);
/* 使用根空间中的同名类 */
echobr(\Demo::$prop);
/* result:
hi
hello
*/
}
use
关键字来声明空间别名. use
默认从根空间开始. 使用as
关键字来指定空间/成员别名。声明语法:
/* 为名称空间起别名 */
use 命名空间名称 as 别名名称;
/* 为名称空间的成员其别名 */
/* 1. 类 */
use 省略第一个\的完全限定名称类名/非完全限定名称类名 as 别名名称;
/* 或者 */
use 省略第一个\的完全限定名称类名/非完全限定名称类名;
/* 2. 函数 */
use function ... as ...;
/* 或者 */
use function ...;
/* 3. 常量 */
use constant ... as ...;
/* 或者 */
use constant ...;
示例:
namespace ns1\test1 {
class Demo {
public static $username = '张三';
}
class Demo1 {
public staitc $username = '李四';
}
}
namespace ns2 {
// 给命名空间起别名
use ns1\test1 as nt1;
// 给命名空间中的类起别名
use ns1\test1\Demo1 as Demo1;
// 当别名跟类名相同时, 可以省略别名
use ns1\test1\Demo;
// 使用别名简化调用
echobr('姓名: ' . nt1\Demo1::$username);
/* result:
李四
*/
// 给类起别名
echobr('姓名: ' . Demo1::$username);
echobr('姓名: ' . Demo::$username);
/* result:
姓名: 李四
姓名: 张三
*/
}
实现类自动加载的条件
命名空间必须跟类文件的绝对路径一一对应。
当前类的名称必须跟当前文件的名称完全一致。
类自动加载的目的是要省略使用
require
引入各种文件。
一般把实现类自动加载的函数用系统函数 spl_autoload_register()函数进行注册。当代码中使用到未被加载的类时,PHP 会自动调用由 spl_autoload_register()函数注册的函数去尝试加载这个类。
类自动加载示例:
// autoload.php
// 封装自动加载器
try {
// 系统函数: spl_autoload_register(): 注册执行加载类的函数
spl_autoload_register(function ($className) {
// 1. 将类名中的反斜线改为当前系统中的目录分隔符
$path = str_replace('\\', DIRECTORY_SEPARATOR, $className);
// echobr($path);
// 2. 生成真正要加载的类文件名称
$file = __DIR__ . DIRECTORY_SEPARATOR . $path . '.php';
// echobr($file);
// 3. 加载这个文件
require $file;
});
} catch (Exception $e) {
die($e->getMessage());
}
// Demo1.php
namespace tool;
class Demo1 {
public static function func1() {
return __METHOD__;
}
public static function echobr($str = '') {
echo $str . '<br>';
}
}
namespace work;
// 1. 加载自动加载器文件
require('autoload.php');
// 2. 使用use为待加载的类起别名
use tool\Demo1;
// 3. 使用待加载的类
Demo1::echobr(Demo1::func1());
/* 成功执行需加载类的方法,即自动加载生效。
result: tool\Demo1::func1 */