Blogger Information
Blog 38
fans 0
comment 0
visits 23437
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
细说命名空间--2018-9-7
晓明的博客
Original
574 people have browsed it

一.命名空间的相关定义和解释

     /*
 * 命名空间
 * 先理解一个重要概念:代码复用
 * 我们学习面向对象编程的终极目标是什么? "代码复用"
 *
 * 一、彻底理解代码复用机制?
 * **到目前为止,我们已经学到的代码复用的实现手段
 * 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;}

运行实例 »

点击 "运行实例" 按钮查看在线实例


Correction status:qualified

Teacher's comments:
Statement of this Website
The copyright of this blog article belongs to the blogger. Please specify the address when reprinting! If there is any infringement or violation of the law, please contact admin@php.cn Report processing!
All comments Speak rationally on civilized internet, please comply with News Comment Service Agreement
0 comments
Author's latest blog post