一.命名空间的相关定义和解释
/*
* 命名空间
* 先理解一个重要概念:代码复用
* 我们学习面向对象编程的终极目标是什么? "代码复用"
*
* 一、彻底理解代码复用机制?
* **到目前为止,我们已经学到的代码复用的实现手段
* 1. 函数: 代码复用最简单的方式;
* 2. 类与对象:将函数与它可能用到的数据封装到一起;
* 3. trait与接口:一种特殊的类,本质是仍是函数与数据的封装;
* 4. 常量:因为常量具有一旦定义不可修改性,可以做到一次声明,随处调用,而值不会发生变化
*
* 二、彻底理解什么是全局?
* 1.全局其它就是指当前脚本,是不能跨脚本的,更不是指整个项目
* 2.全局与局部是一对双胞胎兄弟,他们有一个共同的亲爹:作用域,都由它管着
*
* 三、彻底理解php脚本中有哪些成员?
* 1.变量:包括系统预置变量与用户自定义变量;
* 2.常量:包括系统预置常量,用户自定义常量;
* 3.函数:包括匿名函数/函数表达式/自执行函数;
* 4.类与对象:包括抽象类,接口,trait;
*
*
* 三、彻底理解什么是作用域?
******作用域主要是针对变量
*****PHP中的变量有三种作用域: 函数作用域,全局作用域,超全局作用哉;
* 1. 全局作用域: 在函数外部声明,在函数内部不能直接使用
* 注: 函数中使用全局变量必须用global声明,或者使用超全局数组:$GLOBALS
* 2. 函数作用域:也就是局部作用域,包括函数的参数以及函数内声明的变量,离开函数则自动清除;
* 3. 超全局作用域: 除了在全局有效外,在函数内也可以不用声明直接使用
*
* 四、为什么要使用命名空间?
* 1.类,函数,常量都是全局有效,包括在函数中也可以直接使用.
* 2.因此,在全局中不允许有重名的类,函数和常量。
* 3.如果想从外部导入一个函数库或类库,他们的函数名,类名极有可能与当前脚本冲突
* 4.所以,必须要有一套对于工作在全局范围内的脚本成员,进行标识符命名冲突处理的机制。
* 5.命名空间就是这样一套解决方案,他不仅可以让用户为全局成员起一个较短的名称,又解决了
* 第三方资源的引入带来的重名问题。
* 6.在没有使用任何命名空间的情部下,所有类,常量,函数全部声明在全局空间,用\表,现在我们在
* 他们之前加上反斜线\之外,你会发现,执行结果也是正确的.
*
* ******************************************************
* * 声明类,常量,函数的时候,前面不需要添加\,调用的时候才需要添加\ *
二.全局声明:类,常量,函数
<?php //一、全局声明:类,常量,函数 //1.声明类 class Demo{public $name='Peter Zhu';} //2.声明常量 const SITE = 'PHP中文网'; //3.声明函数 function add($a,$b){return $a+$b;} //二、全局访问 //1.实例化类并访问类成员 echo (new Demo())->name,'<br>'; //echo (new \Demo())->name,'<br>'; //2.访问常量 echo SITE,'<br>'; //echo \SITE,'<br>'; //3.调用函数 echo add(10,20); //echo \add(10,20); echo'<hr>'; //三、函数内访问 function test() { //1.不用声明,可直接实例化类并访问成员 echo (new Demo())->name,'<br>'; // echo (new \Demo())->name,'<br>'; //2.访问常量 echo SITE,'<br>'; // echo \SITE,'<br>'; //3.调用函数 echo add(10,20); // echo \add(10,20); //在函数内部也不能重复声明同名类,函数与常量 // class Demo{} // define('SITE','www.php.cn'); // function add($a,$b){return $a*$b;} } //全局调用 test(); //在全局不允许重复声明类,常量与函数 // class Demo{} // define('SITE','www.php.cn'); // function add($a,$b){return $a*$b;}
点击 "运行实例" 按钮查看在线实例
三.命名空间的基本使用
命名空间的声明与使用
* 1.使用关键字:namespace
* 2.php5.3+
* 3.namespace 之前不能有除了declare和注释之外的任何代码,html也不行
* 4.命名空间默认从全局开始定位,全局空间用\表示,类似于根目录
* 5.如果当前脚本声明了命名空间,则所有成员的访问,就必须使用命名空间,包括系统函数
<?php //1. 声明一个命名空间 namespace one; class Demo{public $name='Peter Zhu';} const SITE='PHP中文网'; function add($a,$b){return $a+$b;} //如果我想声明同名的类,常量与函数可以再声明一个命名空间 //2.一个脚本中允许有多个命名空间 //声明命名空间:two,使用\tow\进行引用 namespace two; //现在声明类Demo,常量SITE,函数add,则不会冲突 class Demo{public $name='朱老师';} const SITE = 'www.php.cn'; function add($a,$b){return $a+$b;} //相信大家看出来了,这非常像是在不同的目录下面,允许创建同名文件,原理是一样的 echo (new Demo)->name, '<br>'; //默认输出的是当前空间的内容 //查看一下当前的命名空间是什么?使用系统预置常量:__NAMESPACE__ echo '当前命名空间是: ',__NAMESPACE__,'<br>'; //也可以带上当前的命名空间来访问当前空间中的成员 //生成带有当前命名空间的类名 $className = __NAMESPACE__.'\Demo'; echo (new $className)->name,'<br>'; //可以带上完整的命名空间名称,从全局空间\开始,相当于从根目录开始 //专业术语: 完全限定名称 echo (new \two\Demo)->name, '<hr>'; //3.如何实现跨空间访问? //如果我们要访问空间one中的Demo类中的属性,如何操作呢? //跨空间访问,与跨目录访问文件一样,一定要带上它完整的空间路径 //例如我们要访问one空间的类Demo中的成员 echo 'one空间的类成员:',(new \one\Demo)->name,'<br>'; //4.在声明了命名空间的脚本中,如何访问系统预定义方法? //例如声明了一个单字符数组 $welcome = 'php中文网欢迎您'; \print_r($welcome); echo '<br>'; print($welcome); echo '<hr>'; //刚才我们说过,在空间中访问全局成员,必须要加\,这里没有加为什么可以? //因为如果用户没有添加,那么会首先在本空间中寻找有没有var_dump()函数, //如果没有找到,再到全局空间查找,所以不报错 //但是如果我们在当前的two空间中也创建一个var_dump()函数,则只会执行 //当前空间中用户自定义的var_dump(),系统同名函数不会被调用 function print_r($arg) { echo '我是当前空间声明的函数调用:'.$arg; } print_r($welcome); echo '<br>'; //等价调用语法: \two\print_r($welcome); //注意: 此print_r(),与系统内置的print_r()无任何关系,仅名称相同而已 //就好比,上海有条长江路,咱们合肥也有一条长江路一样,这二条路除名称一样,再无任何关系 // 上海市宝山区长江路 // 合肥市庐阳区长江路 // 相信没有人会认为这是同一条路? //事实上,这二个函数的完整调用语句应该是这样的: //1.调用系统的: \print_r($welcome); //2.调用当前空间的: \two\print_r($welcome); //尽管后面名称一样,但是归属地是不同的
点击 "运行实例" 按钮查看在线实例
四.非限定名称命名空间和限定命名空间,完全限制命名空间的区别
1.非限定名称: 空间成员名称前不使用空间前缀,类似于当前目录上访问
2.限定名称: 类似于相对路径访问
3.完全限定名称:从全局空间开始,类似于从根目录开始
<?php /* * 命名空间的分层管理 * 1.非限定名称: 空间成员名称前不使用空间前缀,类似于当前目录上访问 * 2. */ //声明命名空间one namespace one ; class Demo{public $name='Peter Zhu';} const SITE='PHP中文网'; function add($a,$b){return $a+$b;} //2.限定名称: 类似于相对路径访问 //tow\Demo 会自动加上当前空间前缀:one //最终解析为: one\two\Demo echo (new two\Demo)->name,'<br>'; //声明命名空间two,two是one的子空间 namespace one\two; class Demo{public $name='朱老师';} const SITE = 'www.php.cn'; function add($a,$b){return $a+$b;} //非限定名称:类似当前目录下访问 //在当前空间内访问不需要添加空间前缀 echo (new Demo)->name,'<br>'; //完全限定名称:从全局空间开始,类似于从根目录开始 //从当前的one\two\开始,访问另一个空间的成员,要从根开始 echo (new \one\Demo)->name;
点击 "运行实例" 按钮查看在线实例
五.namespace关键字和__NAMESPACE__常量
PHP支持两种抽象的访问当前命名空间内部元素的方法,__NAMESPACE__ 魔术常量和namespace关键字。
常量__NAMESPACE__的值是包含当前命名空间名称的字符串。在全局的,不包括在任何命名空间中的代码,它包含一个空的字符串。
__NAMESPACE__ 示例, 在命名空间中的代码
<?php namespace MyProject; echo '"', __NAMESPACE__, '"'; // 输出 "MyProject" ?> __NAMESPACE__ 示例,全局代码 <?php echo '"', __NAMESPACE__, '"'; // 输出 "" ?> 常量 __NAMESPACE__ 在动态创建名称时很有用,例如: 使用__NAMESPACE__动态创建名称 <?php namespace MyProject; function get($classname) { $a = __NAMESPACE__ . '\\' . $classname; return new $a; } ?> 关键字 namespace 可用来显式访问当前命名空间或子命名空间中的元素。它等价于类中的 self 操作符。 namespace操作符,命名空间中的代码 <?php namespace MyProject; use blah\blah as mine; // see "Using namespaces: importing/aliasing" blah\mine(); // calls function blah\blah\mine() namespace\blah\mine(); // calls function MyProject\blah\mine() namespace\func(); // calls function MyProject\func() namespace\sub\func(); // calls function MyProject\sub\func() namespace\cname::method(); // calls static method "method" of class MyProject\cname $a = new namespace\sub\cname(); // instantiates object of class MyProject\sub\cname $b = namespace\CONSTANT; // assigns value of constant MyProject\CONSTANT to $b ?> namespace操作符, 全局代码 <?php namespace\func(); // calls function func() namespace\sub\func(); // calls function sub\func() namespace\cname::method(); // calls static method "method" of class cname $a = new namespace\sub\cname(); // instantiates object of class sub\cname $b = namespace\CONSTANT; // assigns value of constant CONSTANT to $b ?>
点击 "运行实例" 按钮查看在线实例
六.使用别名导入命名空间
* use 关键字的使用
<?php /* * 使用别名导入命名空间 * use 关键字的使用 */ //1. 声明一个命名空间one namespace one ; //use one\two\three\Demo; //如果当前类也有一个同名的Demo类,怎么办?为导入的类取一个别名 use one\two\three\Demo as Demo1; //class Demo1{public $name='Peter Zhu';} class Demo{public $name='Peter Zhu';} const SITE='PHP中文网'; function add($a,$b){return $a+$b;} //在当前空间访问: one\two\three空间中类 //必须要添加很长的空间前缀 //echo (new two\three\Demo)->name; //echo (new Demo)->name; echo (new Demo1)->name; //2.声明命名空间:one\two\three namespace one\two\three; class Demo{public $name='朱老师';} const DOMAIN = 'www.php.cn'; function add($a,$b){return $a+$b;}
点击 "运行实例" 按钮查看在线实例