Correcting teacher:天蓬老师
Correction status:qualified
Teacher's comments:命名空间是一个非常重要的概念, 是php发展史上的里程碑事件
<?php
// 命名空间
// 1. 安徽省合肥市小树小站
// 2. 湖南省长沙市小树小站
// 3. 浙江省宁波市小树小站
// php5.3-: 全局成员默认定义在全局空间中
// 全局成员: 类, 接口, 函数, 常量(访问不受作用域限制)
// anhui_hefei_changjianglu, jiangshu_nanjin_changjianglu
// app_controller_User.php
// 引入组件类:app_controller_User.php
// 声明命名空间: namespace
namespace 安徽省\合肥市;
echo __NAMESPACE__ . '<br>';
class Demo
{
const ROAD_NAME = '小树小站(HF)';
}
// ::class: 获取类的完整名称(带上空间)
echo Demo::class, '<br>';
// 1. 从根空间/全局空间开始: 绝对路径, C:\\a\b\c\d.txt
// 根空间/全局空间:用反斜线表示:\
echo \安徽省\合肥市\Demo::ROAD_NAME . '<br>';
// 2. 从当前空间开始, 可以省略当前空间名称: 非限定名称
echo Demo::ROAD_NAME . '<br>';
echo '<hr>';
namespace 湖南省\长沙市;
echo __NAMESPACE__ . '<br>';
class Demo
{
const ROAD_NAME = '小树小站';
}
// ::class: 获取类的完整名称(带上空间)
echo Demo::class, '<br>';
echo __NAMESPACE__ . Demo::ROAD_NAME , '<br>';
// 访问另一个空间中的成员,必须使用"完全限定名称":类似于绝对路径
echo \安徽省\合肥市\Demo::ROAD_NAME . '<br>';
echo '<hr>';
namespace 浙江省\宁波市;
echo __NAMESPACE__ . '<br>';
class Demo
{
const ROAD_NAME = '小树小站';
}
// ::class: 获取类的完整名称(带上空间)
echo Demo::class, '<hr>';
namespace 江苏省;
// namespace 江苏省\南京市 中的类常量
// 1. 完全限定名称
echo \江苏省\南京市\Demo::ROAD_NAME . '<br>';
// 2. 如果在当前空间下访问, 那么当前的空间名称可以省略
// 在类名前出现了空间,但不是从根空开始,这叫:"限定名称"
echo 南京市\Demo::ROAD_NAME . '<br>';
namespace 江苏省\南京市;
class Demo
{
const ROAD_NAME = '小树小站';
}
// 1. 非限定名称
// 成员前面不能有任何的命名空间,不能有"\", 理解成文件当前路径
// echo Demo::ROAD_NAME;
// 2. 限定名称
// 成员名称前面至少要一个命名空间, 至少要有一个反斜线\, 且不能在首位, 理解成:相对路径
// echo 南京市\Demo::ROAD_NAME;
// 3. 完全限定名称
// 总是从根空间开始,第一个字符一定是反斜线,根空间, 理解成绝对路径
// echo \江苏省\南京市\Demo::ROAD_NAME
<?php
// 全局成员有哪些?
// 全局成员四大家族: 类, 接口, 函数, 常量
// 1. 接口
interface iTest
{
}
// 2. 类
class Demo
{
}
// 3. 函数
function my_func()
{
}
// 4. 常量
const APP_NAME = '进销存';
-------------------------------
// 创建命名空间
// 在同一个脚本中, 创建多个命名空间
namespace one;
// 1. 接口
interface iTest
{
}
// 2. 类
class Demo
{
}
// 3. 函数
function my_func()
{
}
// 4. 常量
const APP_NAME = '多用户进销存';
// 第二个空间
namespace two;
// 1. 接口
interface iTest
{
}
// 2. 类
class Demo
{
}
// 3. 函数
function my_func()
{
}
// 4. 常量
const APP_NAME = '进销存';
echo __NAMESPACE__;
echo APP_NAME , '<br>';
// 完全限定名称
echo \one\APP_NAME, '<br>';
// 这种语法, 只能创建命名空间, 不能创建匿名空间
// 匿名空间就是默认空间就是根空间/全局空间
// namespace \;
-------------------------
// 创建命名空间
// 在同一个脚本中, 创建多个命名空间, 包括全局空间
namespace one
{
// 1. 接口
interface iTest
{
}
// 2. 类
class Demo
{
}
// 3. 函数
function my_func()
{
}
// 4. 常量
const APP_NAME = '多用户进销存';
}
// 第二个空间
namespace two
{
// 1. 接口
interface iTest
{
}
// 2. 类
class Demo
{
}
// 3. 函数
function my_func()
{
}
// 4. 常量
const APP_NAME = '进销存';
}
// 声明一个全局,匿名的
namespace
{
// 完全限定名称
echo one\APP_NAME;
}
-----------------------------------------------------
// namespace 写在第一行
namespace ns1
{
// Test:非限定名称,此时会自动将当前空间名称加上去
// echo Test::App;
// echo \ns1\Test::App;
// 类
echo \Test::APP, '<br>';
echo \implode('---', [1,2,3,4]), '<br>';
// 当前空间下面没有, 到全局找
function implode ($str, $arr)
{
return sprintf('<pre>%s%s</pre>',$str,print_r($arr, true));
}
const E_ALL = 'Hello';
echo \E_ALL;
}
// 全局空间
namespace
{
class Test
{
const APP = '在线商城';
}
}
-------------------------------------------------
// 命名空间的别名
namespace ns1;
class T1
{
// ...
}
echo \ns2\T2::index(), '<br>';
echo \ns2\T3::cate(), '<hr>';
namespace ns2;
class T2
{
public static function index()
{
return '首页';
}
}
class T3
{
public static function cate()
{
return '频道页1111';
}
}
namespace ns3;
// use 用来声明空间别名,use 默认就是从根空开始
// 1. 空间级的别名
// 给外部的空间起了一个别名, ns2 ===> s
use ns2 as s;
echo s\T2::index(), '<br>';
echo s\T3::cate(), '<hr>';
// 2. 类级的别名
// 给外部空间中的类,起一个别名
// use ns2\T2 as T2;
// use ns2\T3 as T3;
// echo T2::index(), '<br>';
// echo T3::cate(), '<hr>';
// 类别名与原始类名相同, 此时可以省略类别名
// use ns2\T2;
// 因为当前类中与有一个与之冲突的类名T2
use ns2\T2 as T;
use ns2\T3;
// use function ....;
// use constant .... ;
echo T2::index(), '<br>';
echo T::index(), '<br>';
echo T3::cate(), '<hr>';
class T2
{
public static function index()
{
return '首页NS3-T2';
}
}
<?php
require 'inc/lib/Demo1.php';
require 'inc/lib/Demo2.php';
require 'inc/lib/Demo3.php';
use inc\lib\Demo1;
use inc\lib\Demo2;
use inc\lib\Demo3;
echo Demo1::class, '<br>';
echo Demo2::class, '<br>';
echo Demo3::class, '<br>';
-------------------------------------------------
// 自动加载的预备知识
// str_replace($search, $subject, $str);
// DIRECTORY_SEPARATOR : 目录分隔符, 随系统自动变化, linux,windows中有所区别
echo __DIR__; // 返回当前脚本所在的路径
echo '<hr>';
$className = 'inc\lib\Demo1';
//1. 应该将类名中的命名空间的分隔符转为目录分隔符
$path = str_replace('\\', DIRECTORY_SEPARATOR, $className);
echo $path, '<hr>';
// 2. 生成真正要加载的类文件名称
$file = __DIR__ . DIRECTORY_SEPARATOR . $path . '.php';
echo $file, '<br>';
// 3. 加载这个文件
require $file;
use inc\lib\Demo1;
echo Demo1::say();
-----------------------------------------
**// 如果想实现自动加载,需要满足二个条件
**// 1. 命名空间必须和类文件所在的绝对路径一一对应
**// 2. 当前类名称与当前的类文件的名称完全一致******
namespace inc\lib;
class Demo1
{
public static function say()
{
return 'Hello PHP中文网';
}
}
------------------------------------
namespace inc\lib;
class Demo2
{
}
------------------------------------
namespace inc\lib;
class Demo3
{
}
-------------------------------------
try {
spl_autoload_register(function($className){
//1. 应该将类名中的命名空间的分隔符转为目录分隔符
$path = str_replace('\\', DIRECTORY_SEPARATOR, $className);
// 2. 生成真正要加载的类文件名称
$file = __DIR__ . DIRECTORY_SEPARATOR . $path . '.php';
// 3. 加载这个文件
require $file;
});
} catch (Exception $e) {
die($e->getMessage());
}
--------------------------------------------
// 封装自动加载器
require 'autoload.php';
use inc\lib\Demo1;
use inc\lib\Demo2;
use inc\lib\Demo3;
echo Demo1::say();
echo Demo2::class, '<br>';
echo Demo3::class;
本次课程老师着重讲解了命名空间的声明、创建、别名及具体的应用场景,尤其是通过实际案例解释说明了自动加载器的封装方法及步骤,让我们从底层原理上去理解命名空间相关内容的重要性,也有助于对后续相关知识的深入学习,收获很大。