ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
## 1. 什么是命名空间? 命名空间对应的英文是 namespace ,所以翻译成中文叫命名空间,在很多的语言中,都有这个 namespace ,那么它用来干嘛呢?说简单点就是为了避免代码命名重复。因为包括 php 在内的很多语言,是不允许 function name 或者 class name重复的,如果你同时 require 2 个 class ,如果调用的对应的 class name 是一样,系统是会报错的。所有,一般的对面对象的语言都会有 namespace ,用来避免这种情况出现。 php 在 5.3 之前是不支持 namespace 的,所以很多程序员的 class name 和 function name 经常会用 class_name_1 , class_name_2,class_name_3 用_隔开等类似这样的方式来避免类的重复,很是这样却不美观和优雅,而且维护起来比较费劲很难理解。于是 php在5.3 重磅突出了 namespace。 举个例子,先常规的写,不使用 namespace 现在我的同一个目录下 3 个 php 文件,分别是:index.php,name.php,gender.php。 三个文件很简单,就是输出一段很简单文字的代码。 name.php ~~~php <?php class info { public static function get_info() { echo 'hello word 1'; } } ~~~ gender.php ~~~php <?php class info { public static function get_info() { echo 'hello word 2'; } } ~~~ 然后在index.php分别rquire这2个文件 ~~~php <?php require './name.php'; require './gender.php'; info::get_info(); info::get_info(); ~~~ name.php 和 gender.php 里的类名字是一样的,都叫 info ,或许你会反问我,你是傻逼吗?你不会给这2个类取不一样的名字啊。因为这里只是小测试小项目,你当然会取不一样的名字。但是比如你用 composer 导入其他人的开源库的代码,肯定是会有 class name 是一样的,这一点是毋庸置疑的,所以你还是无法避免这个问题的。 这时候,你运行下 index.php 就直接报致命错误了的,说类重新声明了。 ~~~php Fatal error: Cannot redeclare class info in D:\wamp\www\testphp\namespace\gender.php on line 3 ~~~ 下面再简单说下如何用 namespace 避免重复,还是这个例子,下面会着重讲。 我们加入 namespace 看下: name.php ~~~php <?php namespace Foo; class info { public static function get_info() { echo 'hello word 1'; } } ~~~ gender.php ~~~php <?php namespace Fee; class info { public static function get_info() { echo 'hello word 2'; } } ~~~ 然后在 index.php 分别 rquire 这 2 个文件,并用 namespace 的方式调用。 ~~~php <?php require './name.php'; require './gender.php'; Foo\info::get_info(); Fee\info::get_info(); ~~~ 我们刷新下 index.php , 看看结果是啥,看,输出的就是我们想要的结果,没有报错: ~~~php hello word 1hello word 2 ~~~ function name 也是不能重复的,这里就不举例了,原理是一样的。 ## 2. 为什么目前国内使用率不高? 截止到目前为止,老实话其实我也没接触过任何关于php的命名空间的项目或者代码,我现在仔细想想为什么会这样呢。大概或许是这几点吧: 目前国内的php版本已经处于 5.3* , 而且还有很多处于 5.2 , php 的命名空间的更新是在 5.3 版本上加入的,所以使用率不是很高。 貌似目前的国内的开源的项目或者框架基本没用 namespace ,或许也有这个因素的影响吧,大家开发写代码想到的就是如何运用好 MVC 和面向对象,想起用 namespace 的少之又少。 namespace 对比 PHP 中的其他语法还是有点羞涩难懂的,而且一些很诡异的书写方式和命名方式,这或许也是一个比较大的影响因素,再加上平时项目中使用率不高,基本上也就不会用它了 ## 3. 在 PHP类文件中使用namespace 下面我们进入正题,真正意义上来学一下php中的命名空间。php的命名空间其实还是非常简单的。 如何声明一个 namespace 前面一个例子呢,简单的说了一下如何声明,现在着重说一下,先提前说明下,稍显变态。 像这样子申明: ~~~php namespce name ~~~ 先看个例子: ~~~php <?php namespace FOO class info { public function test() { echo 'HELLO WORD!'; } } ~~~ 必须用关键字 namespace 来做声明,后面加上命名空间的名字。这个关键字一行必须写在一个 php 文件的最开头,前面不能有任何的语句,额,这一点是有点变态哈,但是也还能忍受。所以,包括 ```ehco 222;, $info = array()``` 等这一系列的语句的都不能写在 namespace 前面。不然就会报致命错误: ~~~php Fatal error: Namespace declaration statement has to be the very first statement in the script in D:\wamp\www\testphp\namespace\gender.php on line 3 ~~~ 所以以下几个是错误的,会报错: ~~~php <?php $info = array(); namespace FOO class info { public function test() { echo 'HELLO WORD!'; } } <?php echo 345; namespace FOO class info { public function test() { echo 'HELLO WORD!'; } } <?php header("Content-type: text/html; charset=utf-8"); namespace FOO class info { public function test() { echo 'HELLO WORD!'; } } ~~~ 还有最重要的一个容易忽略的就是 `<?php`,这个声明是 php 的文件的标记也必须得定格写,前面不能有空格, 不然也会报错。这一点非常重要,极其容易忽略,就产生错误了。 `<?php` 前面有空格,也会报错。 `<?php` //前面有个空格,也会报错 ~~~php namespace FOO class info { public function test() { echo 'HELLO WORD!'; } } ~~~ 一个 namespace 的 name 的书写方式 上面的几个例子中,我们取的命名空间的 name 叫 Foo 和 Fee ,当然这只是一个例子,我们在取名字的时候必须得是有意义的。按照 PSR-0 的规范要求呢,这个名字必须得有一个上级的 Vendor Name ,可以理解为你的项目文件夹的名字,这样的目的呢,第一是为了防止 namespace 的 name 也重复,第二是为了更好的定位文件的位置。也许有点看不懂,举个例子: 假如 gender.php 和 name.php 文件中的 class name 都取名为 :info , 那么必须要设置 2 级的 namespace。 gender.php ~~~php <?php namespace App\Fee; class info { public static function get_info() { echo 'hello word 2'; } } ~~~ name.php ~~~php <?php namespace App\Foo; class info { public static function get_info() { echo 'hello word 1'; } } ~~~ namespace 的名字叫 App\Foo 和 App\Fee, App 就是 Vendor name 也就是项目的目录。这样就很好的区分了。 如果,name.php 和 gender.php 中的 class name 不一样,也就不会重复了,理论上可以不用命名空间,但是现在用命名空间不仅仅是为了防止重复,现在同样也是为了定位这个文件的目录,为了好快速找到。所以,就只需一层 Vendor name 就可以了: gender.php ~~~php <?php namespace App; class gender { public static function get_info() { echo 'hello word 2'; } } ~~~ name.php ~~~php <?php namespace App; class name { public static function get_info() { echo 'hello word 1'; } } ~~~ 上面的我们都将它们命名空间为 APP ,因为它们的 class name 不一样,所以组成的访问类的方式: APP\gender::get_info(); 和 App\name::get_info(); 也就不一样。也就不存在重复的关系。我们在下面将如何访问一个 namespace 时会继续讲到。 name 命名规范 和 php 中变量的命名规则一样,什么首字母不能是数字啊。只能有数字,字母,下划线_组成,也不能是系统保留关键字等。( \ 这个符号可以用的,因为是在 namespace 中用来分割目录的) namespace 的访问 上面我用了大幅篇章来声明如何定义一个 namespace ,当然还有一些很诡异的申明方式,我们放到后面起说。现在来说,如何访问一个 namespace。 访问一个 namespace 其实和访问一个 class 类一模一样,先是导入 class ,再是 new 适用等。 ### 第 1 种方式 像这样子访问调用: ~~~php Vendor\namespce\class gender.php <?php namespace App; class gender { //静态方法,可以直接用::访问 public static function get_info() { echo 'hello word 2'; } } name.php <?php namespace App; class name { public function get_info() { echo 'hello word 1'; } } <?php require './gender.php'; require './name.php'; //static function 直接使用 App\gender::get_info(); //一般方式,先new,再调用 $name = new App\name; $name->get_info(); ~~~ 和调用普通的类一样,先 require 进来,只不过现在的类名变成了:在 class name 前面多加了一个 namespace name 并用\ 隔开,如果是静态方法就直接 ::function name 调用就可以了。如果是常规方法就先 new 再调用 function name。 ### 第 2 中方式:使用 use 关键字 用过其他语言中的 namespace 的或许知道有一个关键字 use 来到导入命名空间的,php 中也是可以的。我们试一下: 像这样子访问调用: ~~~php use Vendor\namespce\class class::function index.php <?php require './gender.php'; require './name.php'; //第1种 use 用来导入gender类 use App\gender; gender::get_info(); use App\name; $name_object = new name; $name_object->get_info(); //第2种 use ** as alise_name 取别名 use App\gender as alise_gender; alise_gender::get_info(); use App\name as alise_name; $alise_name_object = new alise_name; $alise_name_object->get_info(); ~~~ 第 1 中是用 use 用来导入的,导入了 App\gender 类,然后就可以直接调用 gender:: 静态方法或者 new name 再来调用普通方法。 第 2 种是用 use as alise_name 方法取了一个别名而已,用法和第一种类似一致。 我是推荐用第 1 种的,直接使用 use 导入就好了。用 as 别名反而容易造成错误和复杂度,而且你使用 use 的方式,已经是将 namespace 给省略掉了,变成正常的 class 调用方式。一般 as 用在 namespace 申明 function 时候用,在下面会讲到。 OK. php 使用 命名空间基本的东西已经说完了。平时如果使用 namespace ,也就上面这些东西了。所以如果掌握了,基本也就没问题了。 但是,我们因为是在学习它,所以还是要继续深挖一些 namespace 其他的知识点的。在下面接着说。 ## 4. 在php function文件中使用namespace 大多数适用 namespace 其实是在类文件( class )中使用的,在 function 文件中也是可以使用的,也能够防止重复。但是用的很少,使用起来也很蛋疼。 还是看例子: 有一个 height.php 文件,用 namespace 申明一个命名空间 App ~~~php <?php namespace App; function test() { echo ' this is a namespace function test'; } ~~~ 然后在 index.php 中 require 并引用这个 namespace App ~~~php <?php require './height.php'; //第一种方式调用,和之前一样 App\test(); //第二种方式调用,使用use, 必须配合as 使用,不然报错 use App; test(); //报错 //正确的使用方式 use App as anthorApp; anthorApp\test(); ~~~ 上面一个报错的使用是我们自己想当然,想着没有 class name 了,是不是就可以直接使用 function name 了,结果就报错了。因为不管使用好是不使用 use,当得像这样子访问 class\function 。所以,既然 function 没有 class ,那么我们就可以使用 use namespace as class 生成一个别名 anthorApp,再用这个 anthorApp\test() 就可以访问了。 所以,你看到的这篇文件中这一处是错误的:PHP V5.3 中的新特性,第 3 部分: 名称空间 : ~~~php /* File3.php */ <?php include './Foo.php'; use Foo; bar(); // outputs "calling bar...."; //这种方式是错的。 ?> ~~~ 所以总结下: 如果我们用 namespace 声明 function 文件时,最好直接使用 App\test() 调用吧,如果想用 use 关键字,必须要用 as 一个别名。 ## 5. 在php中混合使用各种 什么叫混合使用呢。就是既使用 namespace 声明 class,又声明 function,又单独使用,虽然有点变态,但是为了学习它,为了找到 namespace 的精髓,我也是蛮拼的。 直接上代码吧: height.php 文件中,用 namespace 同时声明的 function 和 class ~~~php <?php namespace App; function test() { echo ' this is a namespace function test'; } class height { public static function test() { echo 'hello word 3'; } } ~~~ 在 function.php 写的是正常普通的 function 和 class ~~~php <?php function test() { echo ' this is a function test'; } class height { public static function test() { echo 'hello word 4'; } } ~~~ 好。那么这么变态的东西,如何访问呢。仔细想想上面说的那么多的,其实很快就可以写出来,而且不会报错: index.php ~~~php <?php require './height.php'; require './function.php'; // 调用namespace的function 和 class 直接调 App\test(); App\height::test(); //调用namespace的function 和 class 使用use use App as anthorApp; anthorApp\test(); use App\height; height::test(); use App\height as anthorClssApp; anthorClssApp::test(); //调用普通的 test(); height::test(); ~~~ 案例参考: https://www.zybuluo.com/phper/note/65479 http://www.ibm.com/developerworks/cn/opensource/os-php-5.3new3/ http://www.cnblogs.com/thinksasa/p/3423480.html http://www.w3cschool.cc/php/php-namespace.html