【PHP】namespace的使用

前言

在我看来,namespace的出现主要是为了解决名称冲突(包括类名冲突、方法名冲突等)以及缩短一些很长的标识符名称(增强可读性)。namespace的思想就类似我们系统中的文件夹

废话不多说,直接进入正文。

声明方式

namespace有两种声明方式

第一种,其中 FirstClass 属于firstNameSpace的命名空间,SecondClass属于secondNameSpace的命名空间

namespace firstNameSpace;

class FirstClass{

}

namespace secondNameSpace;

class SecondClass{

}

第二种,个人比较推荐使用第二种,其中 ThirdClass属于thirdNameSpace的命名空间,FourthClass属于fourthNameSpace的命名空间

记住第二种方法中namespace末尾可以不用加分号,

namespace thirdNameSpace{

    class ThirdClass{

    }
}

namespace fourthNameSpace{

    class FourthClass{

    }
}

小提醒:如果你的代码使用了namespace,那么当前文件中所有的代码都必须包括在namespace中,如下代码会报错

namespace thirdNameSpace{

    class ThirdClass{

    }
}

namespace fourthNameSpace{

    class FourthClass{

    }
}

echo 'Hello NameSpace';

修改方法:把最后一句中的

echo 'Hello NameSpace';

单独放在一个全局的命名空间中(全局命名空间可以忽略空间名),如下

namespace thirdNameSpace{

    class ThirdClass{

    }
}

namespace fourthNameSpace{

    class FourthClass{

    }
}

namespace {

    echo 'Hello NameSpace';
}

第三个命名空间就是全局的命名空间,至于全局空间的导入,下面会讲。

使用方式

在这里,我分成三个情况来讲解

一、同个文件中使用namespace

①非限定名称方式:

字面上理解,就是不用指定名称的方式,看代码就懂了

namespace app{//假设有一个app的命名空间
    const NAME = '管理员';//定义一个NAME为管理员的常量
    function returnFunctionName(){//定义一个返回方法名称的方法
        return __FUNCTION__;
    }
    echo '这里是'.NAME.'<br>';//非限定名称:可以省略命名空间,直接访问常量NAME
    echo '这个方法是'.returnFunctionName().'<hr>';//方法也是如此,可以直接访问
}

其中要使用常量NAME,可以直接在命名空间app中,使用NAME,即可访问,同理app中的方法也是如此。

②限定名称方式:

在讲限定名称方式之前,先给大家讲一个概念:子命名空间

顾名思义,子命名空间与“父”命名空间的关系 就类似 子类与父类的关系

一开始提到,命名空间的思想就类似我们系统中的文件夹,想象一下,我们在系统存放一个视频的时候

一般都是存放与文件夹中,然后可能文件夹中放着文件夹,一层一层的展开,最后可能放了我们某个学习资料.avi

子命名空间就类似文件夹

如果我们把一个学习资料.avi存在D:/php/study/中,那我们要打开这个视频,就需要访问以D盘为根目录,D盘中的php为子文件夹,然后里面再有个study的子文件夹,最后再是我们的视频

同理,如果我们想在app为根命名空间,app中的index中的user为子命名空间,存放一个study的方法

那我们可以这么写

namespace app\index\user {//假设有一个app\index\user的命名空间
    const USERNAME = 'Student';//定义一个值为Student的常量USERNAME
    function study(){//定义一个study的方法
        echo 'I am studying';
    }
}

如果,在app\index里面有另外一个命名空间admin,存放了一个manage的方法

那我们可以这么写

1.php
namespace app\index\user {//假设有一个app\index\user的命名空间
    const USERNAME = 'Student';//定义一个值为Student的常量USERNAME
    function study(){//定义一个study的方法
        return 'I am studying';
    }
}

namespace app\index\admin {//假设有一个app\index\admin的命名空间
    const USERNAME = 'Admin';//定义一个值为Admin的常量USERNAME
    function manage(){//定义一个manage的方法
        return 'I am managing';
    }
}

注意两个命名空间都位于同一个文件中

app\index\user命名空间中有一个study()方法,app\index\admin命名空间有一个manage()方法

在app\index中就有两个子命名空间,一个是user,一个是admin,可以联想系统文件夹

接下来进入正题

字面上理解,限定名称方式就是要使用指定名称的方式,

如果想要在app\index的命名空间中访问user中的study方法,以及admin中的manage方法,如下

1.php
namespace app\index\student {//假设有一个app\index\student的命名空间
    const NAME = 'Student';//定义一个值为Student的常量NAME
    function study(){//定义一个study的方法
        return 'I am studying';
    }
}

namespace app\index\admin {//假设有一个app\index\admin的命名空间
    const NAME = 'Admin';//定义一个值为Admin的常量NAME
    function manage(){//定义一个manage的方法
        return 'I am managing';
    }
}

namespace app\index {//命名空间为app\index
    echo 'NAME is '.admin\NAME.'<br>';//访问当前命名空间app\index中的admin子命名空间中的常量NAME
    echo 'And '.admin\NAME.' say: '.admin\manage().'<br><br>';//访问当前命名空间app\index中的admin子命名空间中的方法manage
    echo 'NAME is '.student\NAME.'<br>';//访问当前命名空间app\index中的student子命名空间中的常量NAME
    echo 'And '.student\NAME.' say: '.student\study().'<hr>';//访问当前命名空间app\index中的student子命名空间中的方法study
}

在第三个命名空间中,指定了第三个命名空间为app\index

要使用admin中的NAME,则可以直接admin\NAME,同理,student\NAME可以访问student中的NAME常量

这种思想可以理解为在指定一个命名空间中,使用相对的子命名空间

以上这种方式,成为限定名称方式,通常用于子空间中

③完全限定名称方式:

跟第二种类似,第三种方式为“绝对路径”,即从根命名空间开始,看代码

1.php
namespace app\index\student {//假设有一个app\index\student的命名空间
    const NAME = 'Student';//定义一个值为Student的常量NAME
    function study(){//定义一个study的方法
        return 'I am studying';
    }
}

namespace app\index\admin {//假设有一个app\index\admin的命名空间
    const NAME = 'Admin';//定义一个值为Admin的常量NAME
    function manage(){//定义一个manage的方法
        return 'I am managing';
    }
}

namespace app\index {//命名空间为app\index
    echo 'NAME is '.admin\NAME.'<br>';//访问当前命名空间app\index中的admin子命名空间中的常量NAME
    echo 'And '.admin\NAME.' say: '.admin\manage().'<br><br>';//访问当前命名空间app\index中的admin子命名空间中的方法manage
    echo 'NAME is '.student\NAME.'<br>';//访问当前命名空间app\index中的student子命名空间中的常量NAME
    echo 'And '.student\NAME.' say: '.student\study().'<hr>';//访问当前命名空间app\index中的student子命名空间中的方法study
}

namespace {
    echo 'NAME is '.app\index\admin\NAME.'<br>';//使用完全限定名称访问app\index\admin中的NAME常量
    echo 'And '.app\index\admin\NAME.' say: '.app\index\admin\manage().'<br><br>';//使用完全限定名称访问app\index\admin中的manage方法
    echo 'NAME is '.app\index\student\NAME.'<br>';//使用完全限定名称访问app\index\student中的NAME常量
    echo 'And '.app\index\student\NAME.' say: '.app\index\student\study().'<hr>';//使用完全限定名称访问app\index\student中的study方法
}

第四个命名空间为全局的命名空间,在这个空间中

使用app\index\admin\NAME来访问app\index\admin中的NAME常量

使用app\index\admin\manage()来访问app\index\admin中的mange()方法

同理,student命名空间的调用也是如此。

二、不同个文件中使用namespace

假设要在2.php中,使用1.php中的app\index\admin命名空间

则必须在2.php中先include或者require1.php

include '1.php';
echo 'NAME is '.app\index\admin\NAME.'<br>';//使用完全限定名称访问app\index\admin中的NAME常量
echo 'And '.app\index\admin\NAME.' say: '.app\index\admin\manage().'<br><br>';//使用完全限定名称访问app\index\admin中的manage方法

或者

namespace app\index\admin;
include '5_blog.php';
echo 'NAME is '.NAME.'<br>';//使用完全限定名称访问app\index\admin中的NAME常量
echo 'And '.NAME.' say: '.manage().'<br><br>';//使用完全限定名称访问app\index\admin中的manage方法

三、使用use关键字或者use 跟 as搭配

 use指定的空间名称,然后用法跟上面的有点小出入,use里面用  子命名空间\常量名  的方式来访问常量

use app\index\admin;
echo 'NAME is '.admin\NAME;

 如果觉得admin\NAME这样写比较长,可以使用as作为别名来使用

use app\index\admin as a;
echo 'NAME is '.a\NAME;

一些问题 

问题1:全局性函数(php内置函数)的使用

在命名空间中,可以使用与php内置函数相同的名字,比如你可以在app的命名空间中使用strlen来定义一个函数

而且不会报错,代码如下

namespace app{
    function strlen($str){//可以定义与内置函数重名的方法
    
    }
}

 如果要使用php内置的函数,比如strlen,则需要加一个反斜杠(代表全局的意思),\strlen来表示php内置函数strlen

同理,其它具有全局性的函数(strlen)或者类,都是需要加上反斜杠,类似\strlen,才可以访问指定的函数

namespace app{
    function strlen($str){//可以定义与内置函数重名的方法
        return \strlen($str);//从php内置函数strlen返回str的长度
    }
}

 问题2:常量的定义

在上面的例子中,我是使用const来在两个命名空间中定义一个常量,那如果我们使用define来定义呢

namespace app1{
    define('A',4);
    echo A;
}

namespace app2{
    define('A',4);
    echo A;
}

出了个小错误,因为define来定义常量具有全局性,在同个文件的两个命名空间中定义两个相同的常量会出错,所以建议使用const来定义命名空间中的常量 

Notice: Constant A already defined in

总结

学习没有捷径,如果有不懂的地方,就多打几遍代码,多翻翻官方文档,多琢磨琢磨

我们生活在一个资源丰富的互联网时代,好好利用身边的资源

总有一天,我们也能成为拔尖的人,加油,一起成长

猜你喜欢

转载自blog.csdn.net/weixin_41463193/article/details/83691509