命名空间的意义:
命名空间最主要的目的就是解决函数或者类重名的问题,一般的来说如果函数或者类名冲突的话,比如一个common函数 分别是home和admin下面的 如果都定义为common就会重名 一般的来说会会重构函数名,认为的这样定义:home_common和admin_common来解决重名的问题;
这样明显函数名的字符变多了,如果在项目开始的时候就注意到这个问题就可以免函数或者类重名咯,还有一个办法就是使用命名空间。、
注:在php5.3之后const也可以用在类的外部使用,在命名空间中const是针对当前空间的,define是针对全部的,一下提到的都是const;
命名空间的概念:
命名空间是把代码中不同的函数,类划分到一个空间中,空间与空间之间没有影响,这个就类似于“封装”的概念;
创建一个命名空间:
创建一个命名空间需要使用namespace关键字
例如下面的:
<?php
namespace China; //创建一个名为China的命名空间
//注意在当前脚本文件的第一个命名空间的前面是不能有任何代码的
function Common(){return 1000;} //在当前的命名空间下面定义了一个名为common的函数
一个脚本文件可以创建多个命名空间,就只要求第一个前面不能有任何逻辑代码
<?php
//创建一个名为'Article'的命名空间
namespace Article;
//此Comment属于Article空间的元素
class Comment { }
//创建一个名为'MessageBoard'的命名空间
namespace MessageBoard;
//此Comment属于MessageBoard空间的元素
class Comment { }
?>
在不同的命名空间之间不能调用其他命名空间内的元素,如果调用要用命名空间的语法,
<?php
namespace China; //创建一个名为China的命名空间
//注意在当前脚本文件的第一个命名空间的前面是不能有任何代码的
class Common{}; //在当前的命名空间下面定义了一个名为common的类
namespace meiguo;
class Common{};
$com = new Common(); //在meiguo的命名空间下
$comm =new \China\Common(); //在China下面的common 使用语法是\空间名\元素名
除了类之外对函数和对常量的用法也是一致的
<?php
namespace China; //创建一个名为China的命名空间
//注意在当前脚本文件的第一个命名空间的前面是不能有任何代码的
const PATH = '/China';
function Getinfo(){return 1000;}
class Common{}; //在当前的命名空间下面定义了一个名为common的类
namespace meiguo;
const PATH = '/meiguo';
function Getinfo(){return 300;}
class Common{};
//调用当前空间的常量 函数 类
echo PATH;
echo Getinfo();
$com = new Common();
//调用China下面的常量 函数 类
echo \China\PATH;
echo \China\Getinfo();
$comm =new \China\Common();
子空间:
命名空间的语法和文件路径的语法是一样的,它允许我们自定义子空间来描述各个空间之间的关系
比如说home 和admin都是在shop项目的下面的
<?php
namespace shop\China; //创建一个名为China的命名空间
//注意在当前脚本文件的第一个命名空间的前面是不能有任何代码的
const PATH = '/China';
function Getinfo(){return 1000;}
class Common{}; //在当前的命名空间下面定义了一个名为common的类
namespace shop\meiguo;
const PATH = '/meiguo';
function Getinfo(){return 300;}
class Common{};
//调用当前空间的常量 函数 类
echo PATH;
echo Getinfo();
$com = new Common();
//调用China下面的常量 函数 类
echo \shop\China\PATH;
echo \shop\China\Getinfo();
$comm =new \shop\China\Common();
公共空间:
在命名空间引入一个脚本,这个脚本是不属于这个命名空间的,
<?php
namespace shop\China; //创建一个名为China的命名空间
//注意在当前脚本文件的第一个命名空间的前面是不能有任何代码的
require("./login.php");
echo Getinfo();
//$fun = new common(); //这样不行 会出现致命错误
$fun = new \common(); //调用公共空间的时候 就直接在前面加上 /就可以咯 否则PHP解析器会认为我们想要调用当前空间下的元素
注:可能加上\的目的就是为了区分是不是调用外部的函数(个人推论)
命名空间的专业术语:
在识别名和导入之前要知道 三种命名空间的术语,以及PHP解释器怎么解释他们的
1.非限定名称,或不包含前缀的类名称,例如 $comment = new Comment();。如果当前命名空间是shop\China,Comment将被解析为shop\China\Comment。如果使用Comment的代码不包含在任何命名空间中的代码(全局空间中),则Comment会被解析为Comment。
2.限定名称,或包含前缀的名称,例如 $comment = new China\Comment();。如果当前的命名空间是Blog,则Comment会被解析为shop\China\Comment。如果使用Comment的代码不包含在任何命名空间中的代码(全局空间中),则Comment会被解析为Comment。
3.完全限定名称,或包含了全局前缀操作符的名称,例如 $comment = new \homeComment();。在这种情况下,Comment总是被解析为代码中的文字名(literal name)home\Comment。
2.限定名称,或包含前缀的名称,例如 $comment = new China\Comment();。如果当前的命名空间是Blog,则Comment会被解析为shop\China\Comment。如果使用Comment的代码不包含在任何命名空间中的代码(全局空间中),则Comment会被解析为Comment。
3.完全限定名称,或包含了全局前缀操作符的名称,例如 $comment = new \homeComment();。在这种情况下,Comment总是被解析为代码中的文字名(literal name)home\Comment。
下面是应用的几个例子:
<?php
//创建空间Blog
namespace Blog;
class Comment { }
//非限定名称,表示当前Blog空间
//这个调用将被解析成 Blog\Comment();
$blog_comment = new Comment();
//限定名称,表示相对于Blog空间
//这个调用将被解析成 Blog\Article\Comment();
$article_comment = new Article\Comment(); //类前面没有反斜杆\
//完全限定名称,表示绝对于Blog空间
//这个调用将被解析成 Blog\Comment();
$article_comment = new \Blog\Comment(); //类前面有反斜杆\
//完全限定名称,表示绝对于Blog空间
//这个调用将被解析成 Blog\Article\Comment();
$article_comment = new \Blog\Article\Comment(); //类前面有反斜杆\
//创建Blog的子空间Article
namespace Blog\Article;
class Comment { }
?>
导入和取别名:
别名和导入可以看做是调用命名空间的一种快捷方式,但是PHP不支持导入函数或者常量
<?php
namespace Blog\Article;
class Comment { }
//创建一个A空间
namespace A;
//导入一个命名空间
use Blog\Article;
//导入命名空间后可使用限定名称调用元素
$article_comment = new Article\Comment();
//为命名空间使用别名
use Blog\Article as Arte;
//使用别名代替空间名
$article_comment = new Arte\Comment();
//导入一个类
use Blog\Article\Comment;
//导入类后可使用非限定名称调用元素
$article_comment = new Comment();
//为类使用别名
use Blog\Article\Comment as Comt;
//使用别名代替空间名
$article_comment = new Comt();
?>
<?php
namespace Blog\Article;
class Comment { }
namespace A;
class Comment { }
Class Comt { }
//导入一个类
//use Blog\Article\Comment;
//$article_comment = new Comment(); //与当前空间的Comment发生冲突,程序产生致命错误
//为类使用别名
use Blog\Article\Comment as Comt;
$article_comment = new Comt(); //与当前空间的Comt发生冲突,程序产生致命错误
use Blog\Article\Comment as Comtt;
$article_comment = new Comtt(); //这样名称不一样就不会报错了
动态调用:
namespace Blog\Article;
const PATH = '/Blog/article';
class Comment { }
//namespace关键字表示当前空间
echo namespace\PATH; ///Blog/article
$comment = new namespace\Comment();
//魔法常量__NAMESPACE__的值是当前空间名称
echo __NAMESPACE__; //Blog\Article
//可以组合成字符串并调用
$comment_class_name = __NAMESPACE__ . '\Comment';
$comment = new $comment_class_name();