php命名空间的引入问题 include namespace
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了php命名空间的引入问题 include namespace相关的知识,希望对你有一定的参考价值。
file1
<?php
namespace Foo\Bar\subnamespace;
const FOO = 1;
function foo()
class foo
static function staticmethod()
?>
file2
<?php
namespace Foo\Bar;
include 'file1.php';
const FOO = 2;
function foo()
class foo
static function staticmethod()
?>
*******************************************
问题:
namespace Foo\Bar;
include 'file1.php';
这2句到底怎么执行的??
*******************************************
include 'file1.php'; 是把file1的语句替换本语句吗?
比如这样
namespace Foo\Bar;
namespace Foo\Bar\subnamespace; //直接替换本include语句
const FOO = 1;
function foo()
class foo
static function staticmethod()
const FOO = 2;
function foo()
class foo
static function staticmethod()
为什么一运行救你报错呢??
但是写include不报错
这是为什么啊
include函数是引入文件
命名空间解决的是同一脚本下相同函数重名,不同的命名空间命名,相当于处于不同的模块,解决同一脚本下php函数重名的致命错误
你之前include引入的时候你的2个文件的相同函数处于不同命名空间下,就算在同一脚本也不会报错
看你最后段代码,你连续定义了2个命名空间,第1个就没用了,相当于你在namespace Foo\\Bar\\subnamespace;命名空间下写了之后的代码,但是之后的代码处于namespace Foo\\Bar\\subnamespace;下但是出现了2个相同名的函数,自然报错
你要区分命名空间和include就要先懂得他们代表的意思,从你的问题可以看出你不太懂命名空间,建议你百度或者看下php手册上的命名空间,自己捉摸比别人教理解得更加深刻
建议你把namespace Foo\\Bar\\subnamespace;写到const FOO = 2;上面
就加个横杠的事情找了我一天,就看到这么一个正经写的,贴在这里给人看下,不用像我一样找的要死要活,在要用的include的文件里的类的时候,new 的面,类的前面加 \\
现代PHP-命名空间
1、什么是命名空间
如果你只需要知道现代PHP特性中的一个,那就应该是命名空间。命名空间在PHP5.3.0中引入,其作用是按照一种虚拟的层次结构组织PHP代码,这种层次结构类似操作系统中文件系统的目录结构。命名空间是现代PHP组件生态的基础,现代的PHP组件框架代码都是放在各自全局唯一的厂商命名空间中,以免和其他厂商使用的常见类名冲突。 下面我来看看真实的PHP组件是如何使用命名空间的。Laravel框架中的Http组件用于管理HTTP请求和响应,这个组件用到了常见的类名,例如Request、Response,很多其他PHP组件也用到了这样的类名,既然其他PHP代码也用到了相同的类名,那怎么使用这个组件呢?其实我们可以放心使用,因为这个组件的代码放在了唯一的厂商命名空间Illuminate中。打开这个组件在GitHub中的仓库https://github.com/laravel/framework/blob/master/src/Illuminate/Http/Response.php ,找到Response.php
文件:
第3行代码如下:
namespace IlluminateHttp;
这一行是PHP命名空间声明语句,声明命名空间的代码始终应该放在<?php
标签后的第一行。通过这个命名空间的声明语句我们可以看到Response
位于厂商命名空间Illuminate
中(最顶层命名空间),我们还看到Response
类在子命名空间Http
中,你可以看下和Response.php
文件在同一层级的其他文件,会发现它们都使用相同的命名空间声明语句。 命名空间的作用是封装和组织相关的PHP类,就像在文件系统中把相关的文件放在同一个目录中一样。PHP命名空间和操作系统的物理文件系统不同,这是一个虚拟概念,没必要和文件系统中的目录结构完全相同,虽然如此,但是大多数PHP组件为了兼容广泛使用的PSR-4自动加载标准,会把命名空间放到对应文件系统的子目录中。
2、为什么使用命名空间
前面已经提到过,我们的代码可能和其他开发者的代码使用相同的类名、接口名、函数或常量名,如果不使用命名空间,名称会起冲突,导致PHP执行出错。而使用命名空间将代码放到唯一的厂商命名空间,我们的代码就可以和其他开发者使用相同的类名、接口名、函数或常量名。 当然如果你开发的是小型个人项目,只有少量的依赖,类名冲突可能不是问题,但是如果在团队中工作,开发用到许多第三方依赖的大型项目,就要认真对待命名冲突问题,因为你无法控制项目依赖在全局命名空间中引入的类、接口、函数和常量,这也是为什么要使用命名空间的原因。
3、声明命名空间
每个PHP类、接口、函数和常量都在命名空间中,声明命名空间很简单,在<?php
标签后的第一行声明,声明语句以namespace
开头,随后是一个空格,然后是命名空间的名称,最后以;
结尾。 命名空间经常用于设置顶层厂商名,比如我们设置厂商名为LaravelAcademy
:
<?php
namespace LaravelAcademy;
在这个命名空间声明语句后声明的所有PHP类、接口、函数和常量都在LaravelAcademy
命名空间中,而且和Laravel学院有某种关系。如果我们想组织学院用到的代码该怎么做呢?答案是使用子命名空间。 子命名空间的声明方式和前面的示例完全一样,唯一的区别是我们要使用符号把命名空间和子命名空间分开,例如:
<?php
namespace LaravelAcademyModernPHP;
这个命名空间后的所有类、接口、函数和常量都位于LaravelAcademyModernPHP
中。 在同一个命名空间中的类没必要在同一个PHP文件中声明,可以在PHP文件的顶部指定一个命名空间或子命名空间,此时,这个文件的代码就是该命名空间或子命名空间的一部分。因此我们可以在不同文件中编写属于同一个命名空间的多个类。
注:厂商命名空间是最顶层的命名空间,也是最重要的命名空间,用于识别品牌或组织,必须具有全局唯一性。子命名空间相对而言没那么重要,但是可以用于组织项目的代码。
4、导入和别名
在命名空间出现之前,PHP开发者使用Zend风格的类名解决命名冲突问题,这是一种类的命名方案,因Zend框架而流行,这种命名方案在PHP类名中使用下划线的方式表示文件系统的目录分隔符。这种约定有两个作用:其一,确保类名是唯一的;其二,原生的自动加载器会把类名中的下划线替换成文件系统的目录分隔符,从而确定文件的路径。例如,Zend_Cloud_DocumentService_Adapter_WindowsAzure_Query
类对应的文件是Zend/Cloud/DocumentService/Adapter/WindowsAzure/Query.php
。可以看出,这种命名有个缺点:类名特别长。 现代的PHP命名空间也有这个问题,例如上述Response
类完整的全名是IlluminateHttpResponse
,幸好,我们可以通过导入以及创建别名的方式来改变这一状况。 导入的意思是指,在每个PHP文件中告诉PHP想使用哪个命名空间、类、接口、函数和常量,导入后就不用使用全名了:
<?php
use IlluminateHttpResponse;
$response = new Response(‘Oops’, 400);
$response->send();
我们通过use
关键字告诉PHP,我们想使用IlluminateHttpResponse
类,我们只需要输入一次完全限定的类名,随后实例化Response
的时候,无需使用完整的类名。 如果觉得这样的类名还是长,可以创建别名。创建别名指的是告诉PHP我要使用简单的名称引用导入的类、接口、函数或常量:
<?php
use IlluminateHttpResponse as Res;
$res = new Res(‘Oops’, 400);
$res->send();
从PHP 5.6开始还可以导入函数和常量,不过要调整use关键字的句法,如果要导入函数,需要使用use func
:
<?php
use func NamespacefunctionName
functionName();
如果想导入常量,可以使用use constant
:
<?php
use constant NamespaceCONST_NAME;
echo CONST_NAME;
当然也支持别名,创建方式和类一样。
5、实用技巧
多重导入
如果想要在PHP文件中导入多个类、接口、函数或常量,需要在PHP文件的顶部使用多个use语句,PHP支持用简短的语法把多个use语句写成一行:
<?php
use IlluminateHttpRequest,
IlluminateHttpResponse;
但是为了可读性,建议不要这么写,还是一行写一个use语句比较好:
<?php
use IlluminateHttpRequest;
use IlluminateHttpResponse;
一个文件使用多个命名空间
PHP允许在一个文件中定义多个命名空间:
<?php
namespace Foo {
//声明类、接口、函数、常量
}
namespace Bar {
//声明类、接口、函数、常量
}
但这么做不好,违背了“一个文件一个类”的良好实践,因此不建议这么做。
全局命名空间
如果引用的类、接口、函数和常量没有指定命名空间,PHP假定引用的类、接口、函数和常量在当前的命名空间中。如果要使用其他命名空间的类、接口、函数或常量,需要使用完全限定的PHP类名(命名空间+类名)。 有些代码在全局命名空间中,没有命名空间,比如原生的Exception类就是这样。在命名空间中引用全局的代码时,需要在类、接口、函数或常量前加符号:
<?php
namespace MyApp;
class Foo {
public function doSomething() {
throw new Exception();
}
}
自动加载
命名空间还为PHP-FIG制定的PSR-4自动加载标准奠定了坚实的基础,大多数现代的PHP组件都使用了这种自动加载模式,使用依赖管理器Composer可以自动加载项目的依赖,后续我们还会详细介绍Composer和PHP-FIG
以上是关于php命名空间的引入问题 include namespace的主要内容,如果未能解决你的问题,请参考以下文章