찾다
백엔드 개발PHP 튜토리얼PHP命名空间(Namespace)初探,命名空间namespace_PHP教程

PHP命名空间(Namespace)初探,命名空间namespace

探完闭包[查看],再探命名空间。

对于命名空间,官方文档已经说得很详细[查看],我在这里做了一下实践和总结。

命名空间一个最明确的目的就是解决重名问题,PHP中不允许两个函数或者类出现相同的名字,否则会产生一个致命的错误。这种情况下只要避免命名重复就可以解决,最常见的一种做法是约定一个前缀。

例:项目中有两个模块:articlemessage board,它们各自有一个处理用户留言的类Comment之后我可能想要增加对所有用户留言的一些信息统计功能,比如说我想得到所有留言的数量。这时候调用它们Comment提供的方法是很好的做法,但是同时引入各自的Comment类显然是不行的,代码会出错,在另一个地方重写任何一个Comment也会降低维护性。那这时只能重构类名,我约定了一个命名规则,在类名前面加上模块名,像这样:Article_CommentMessageBoard_Comment

可以看到,名字变得很长,那意味着以后使用Comment的时候会写上更多的代码(至少字符多了)。并且,以后如果要对各个模块增加更多的一些整合功能,或者是互相调用,发生重名的时候就需要重构名字。当然在项目开始的时候就注意到这个问题,并规定命名规则就能很好的避免这个问题。另一个解决方法可以考虑使用命名空间。

 

注明:

本文提到的常量:PHP5.3开始const关键字可以用在类的外部。constdefine都是用来声明常量的(它们的区别不详述),但是在命名空间里,define的作用是全局的,而const则作用于当前空间。我在文中提到的常量是指使用const声明的常量。

 

 

基础

命名空间将代码划分出不同的空间(区域),每个空间的常量、函数、类(为了偷懒,我下边都将它们称为元素)的名字互不影响, 这个有点类似我们常常提到的‘封装’的概念。

创建一个命名空间需要使用namespace关键字,这样:

复制代码
<?<span>php

</span><span>//</span><span>创建一个名为'Article'的命名空间</span>
<span>namespace Article;

</span>?>
复制代码

 

要注意的是,当前脚本文件的第一个命名空间前面不能有任何代码,下面的写法都是错误的:

复制代码
<span>//</span><span>例一
//在脚本前面写了一些逻辑代码</span>

<?<span>php

</span><span>$path</span> = "/"<span>;

</span><span>class</span><span> Comment { }

namespace Article;

</span>?>
<br />

<span>//</span><span>例二
//在脚本前面输出了一些字符</span>

<html></html>
<?<span>php

namespace Article;

</span>?>
复制代码

 

为什么要说第一个命名空间呢?因为同一脚本文件中可以创建多个命名空间。

下面我创建了两个命名空间,顺便为这两个空间各自添加了一个Comment类元素:

复制代码
<?<span>php

</span><span>//</span><span>创建一个名为'Article'的命名空间</span>
<span>namespace Article;

</span><span>//</span><span>此Comment属于Article空间的元素</span>
<span>class</span><span> Comment { }



</span><span>//</span><span>创建一个名为'MessageBoard'的命名空间</span>
<span>namespace MessageBoard;

</span><span>//</span><span>此Comment属于MessageBoard空间的元素</span>
<span>class</span><span> Comment { }
</span>?>
复制代码

 

在不同空间之间不可以直接调用其它元素,需要使用命名空间的语法:

复制代码
<?<span>php

namespace Article;

</span><span>class</span><span> Comment { }



namespace MessageBoard;

</span><span>class</span><span> Comment { }

</span><span>//</span><span>调用当前空间(MessageBoard)的Comment类</span>
<span>$comment</span> = <span>new</span><span> Comment();

</span><span>//</span><span>调用Article空间的Comment类</span>
<span>$article_comment</span> = <span>new</span><span> \Article\Comment();

</span>?>
复制代码

 

可以看到,在MessageBoard空间中调用article空间里的Comment类时,使用了一种像文件路径的语法: \空间名\元素名

除了类之外,对函数和常量的用法是一样的,下面我为两个空间创建了新的元素,并在MessageBoard空间中输出了它们的值。

复制代码
<?<span>php

namespace Article;

</span><span>const</span> PATH = '/article'<span>;

</span><span>function</span><span> getCommentTotal() {
    </span><span>return</span> 100<span>;
}

</span><span>class</span><span> Comment { }




namespace MessageBoard;

</span><span>const</span> PATH = '/message_board'<span>;

</span><span>function</span><span> getCommentTotal() {
    </span><span>return</span> 300<span>;
}

</span><span>class</span><span> Comment { }

</span><span>//</span><span>调用当前空间的常量、函数和类</span>
<span>echo</span> PATH; <span>//</span><span>/message_board</span>
<span>echo</span> getCommentTotal(); <span>//</span><span>300</span>
<span>$comment</span> = <span>new</span><span> Comment();

</span><span>//</span><span>调用Article空间的常量、函数和类</span>
<span>echo</span> \Article\PATH; <span>//</span><span>/article</span>
<span>echo</span> \Article\getCommentTotal(); <span>//</span><span>100</span>
<span>$article_comment</span> = <span>new</span><span> \Article\Comment();

</span>?>
复制代码

 

然后我的确得到了Article空间的元素数据。

 

 

子空间

命名空间的调用语法像文件路径一样是有道理的,它允许我们自定义子空间来描述各个空间之间的关系。

抱歉我忘了说,articlemessage board这两个模块其实都是处于同一个blog项目内。如果用命名空间来表达它们的关系,是这样:

复制代码
<?<span>php

</span><span>//</span><span>我用这样的命名空间表示处于blog下的article模块</span>
<span>namespace Blog\Article;

</span><span>class</span><span> Comment { }



</span><span>//</span><span>我用这样的命名空间表示处于blog下的message board模块</span>
<span>namespace Blog\MessageBoard;

</span><span>class</span><span> Comment { }

</span><span>//</span><span>调用当前空间的类</span>
<span>$comment</span> = <span>new</span><span> Comment();

</span><span>//</span><span>调用Blog\Article空间的类</span>
<span>$article_comment</span> = <span>new</span><span> \Blog\Article\Comment();

</span>?>
复制代码

而且,子空间还可以定义很多层次,比如说 Blog\Article\Archives\Date

 

 

公共空间

我有一个common_inc.php脚本文件,里面有一些好用的函数和类:

复制代码
<?<span>php

</span><span>function</span><span> getIP() { }

</span><span>class</span><span> FilterXSS { }

</span>?>
复制代码

 

在一个命名空间里引入这个脚本,脚本里的元素不会归属到这个命名空间。如果这个脚本里没有定义其它命名空间,它的元素就始终处于公共空间中:

复制代码
<?<span>php

namespace Blog\Article;

</span><span>//</span><span>引入脚本文件</span>
<span>include</span> './common_inc.php'<span>;

</span><span>$filter_XSS</span> = <span>new</span> FilterXSS(); <span>//</span><span>出现致命错误:找不到Blog\Article\FilterXSS类</span>

<span>$filter_XSS</span> = <span>new</span> \FilterXSS(); <span>//</span><span>正确</span>


?>
复制代码

 

调用公共空间的方式是直接在元素名称前加 \ 就可以了,否则PHP解析器会认为我想调用当前空间下的元素。除了自定义的元素,还包括PHP自带的元素,都属于公共空间。

要提一下,其实公共空间的函数和常量不用加 \ 也可以正常调用(不明白PHP为什么要这样做),但是为了正确区分元素,还是建议调用函数的时候加上 \ 

 

 

名称术语

在说别名和导入之前,需要知道关于空间三种名称的术语,以及PHP是怎样解析它们的。官方文档说得非常好,我就直接拿来套了。

 

其实可以把这三种名称类比为文件名(例如 comment.php)、相对路径名(例如 ./article/comment.php)、绝对路径名(例如 /blog/article/comment.php),这样可能会更容易理解。

我用了几个示例来表示它们:

复制代码
<?<span>php

</span><span>//</span><span>创建空间Blog</span>
<span>namespace Blog;

</span><span>class</span><span> Comment { }

</span><span>//</span><span>非限定名称,表示当前Blog空间
//这个调用将被解析成 Blog\Comment();</span>
<span>$blog_comment</span> = <span>new</span><span> Comment();

</span><span>//</span><span>限定名称,表示相对于Blog空间
//这个调用将被解析成 Blog\Article\Comment();</span>
<span>$article_comment</span> = <span>new</span> Article\Comment(); <span>//类</span><span>前面没有反斜杆\

//完全限定名称,表示绝对于Blog空间
//这个调用将被解析成 Blog\Comment();</span>
<span>$article_comment</span> = <span>new</span> \Blog\Comment(); <span>//类</span><span>前面有反斜杆\

//完全限定名称,表示绝对于Blog空间
//这个调用将被解析成 Blog\Article\Comment();</span>
<span>$article_comment</span> = <span>new</span> \Blog\Article\Comment(); <span>//类</span><span>前面有反斜杆\



//创建Blog的子空间Article</span>
<span>namespace Blog\Article;

</span><span>class</span><span> Comment { }


</span>?>
复制代码

 

其实之前我就一直在使用非限定名称和完全限定名称,现在它们终于可以叫出它们的名称了。

 

别名和导入

别名和导入可以看作是调用命名空间元素的一种快捷方式。PHP并不支持导入函数或常量。

它们都是通过使用use操作符来实现:

复制代码
<?<span>php

namespace Blog\Article;

</span><span>class</span><span> Comment { }



</span><span>//创建一个BBS空间(我有打算开个论坛)</span>
<span>namespace BBS;

</span><span>//</span><span>导入一个命名空间</span>
<span>use</span><span> Blog\Article;
</span><span>//</span><span>导入命名空间后可使用限定名称调用元素</span>
<span>$article_comment</span> = <span>new</span><span> Article\Comment();

</span><span>//</span><span>为命名空间使用别名</span>
<span>use</span> Blog\Article <span>as</span><span> Arte;
</span><span>//</span><span>使用别名代替空间名</span>
<span>$article_comment</span> = <span>new</span><span> Arte\Comment();

</span><span>//</span><span>导入一个类</span>
<span>use</span><span> Blog\Article\Comment;
</span><span>//</span><span>导入类后可使用非限定名称调用元素</span>
<span>$article_comment</span> = <span>new</span><span> Comment();

</span><span>//</span><span>为类使用别名</span>
<span>use</span> Blog\Article\Comment <span>as</span><span> Comt;
</span><span>//</span><span>使用别名代替空间名</span>
<span>$article_comment</span> = <span>new</span><span> Comt();

</span>?>
复制代码

 

我注意到,如果导入元素的时候,当前空间有相同的名字元素将会怎样?显然结果会发生致命错误。

例:

复制代码
<?<span>php

namespace Blog\Article;

</span><span>class</span><span> Comment { }



namespace BBS;

</span><span>class</span><span> Comment { }

</span><span>Class</span><span> Comt { }


</span><span>//</span><span>导入一个类</span>
<span>use</span><span> Blog\Article\Comment;
</span><span>$article_comment</span> = <span>new</span> Comment(); <span>//</span><span>与当前空间的Comment发生冲突,程序产生致命错误

//为类使用别名</span>
<span>use</span> Blog\Article\Comment <span>as</span><span> Comt;
</span><span>$article_comment</span> = <span>new</span> Comt(); <span>//</span><span>与当前空间的Comt发生冲突,程序产生致命错误</span>

?>
复制代码

 

 

动态调用

PHP提供了namespace关键字和__NAMESPACE__魔法常量动态的访问元素,__NAMESPACE__可以通过组合字符串的形式来动态访问:

复制代码
<?<span>php

namespace Blog\Article;

</span><span>const</span> PATH = '/Blog/article'<span>;

</span><span>class</span><span> Comment { }


</span><span>//</span><span>namespace关键字表示当前空间</span>
<span>echo</span> namespace\PATH; <span>//</span><span>/Blog/article</span>
<span>$comment</span> = <span>new</span><span> namespace\Comment();

</span><span>//</span><span>魔法常量__NAMESPACE__的值是当前空间名称</span>
<span>echo</span> __NAMESPACE__; <span>//</span><span>Blog\Article
//可以组合成字符串并调用</span>
<span>$comment_class_name</span> = __NAMESPACE__ . '\Comment'<span>;
</span><span>$comment</span> = <span>new</span> <span>$comment_class_name</span><span>();

</span>?>
复制代码

 

字符串形式调用问题

上面的动态调用的例子中,我们看到了字符串形式的动态调用方式,如果要使用这种方式要注意两个问题。

1. 使用双引号的时候特殊字符可能被转义

复制代码
<?<span>php

namespace Blog\Article;

</span><span>class</span><span> name { }

</span><span>//</span><span>我是想调用Blog\Article\name</span>
<span>$class_name</span> = __NAMESPACE__ . "\name"; <span>//</span><span>但是\n将被转义为换行符</span>

<span>$name</span> = <span>new</span> <span>$class_name</span>(); <span>//</span><span>发生致命错误</span>

?>
复制代码

 

2. 不会认为是限定名称

PHP在编译脚本的时候就确定了元素所在的空间,以及导入的情况。而在解析脚本时字符串形式调用只能认为是非限定名称和完全限定名称,而永远不可能是限定名称。

复制代码
<?<span>php

namespace Blog;

</span><span>//</span><span>导入Common类</span>
<span>use</span><span> Blog\Article\Common;
</span><span>//</span><span>我想使用非限定名称调用Blog\Article\Common</span>
<span>$common_class_name</span> = 'Common'<span>;
</span><span>//</span><span>实际会被当作非限定名称,也就表示当前空间的Common类,但我当前类没有创建Common类</span>
<span>$common</span> = <span>new</span> <span>$common_class_name</span>(); <span>//</span><span>发生致命错误:Common类不存在

//我想使用限定名称调用Blog\Article\Common</span>
<span>$common_class_name</span> = 'Article\Common'<span>;
</span><span>//</span><span>实际会被当作完全限定名称,也就表示Article空间下的Common类,但我下面只定义了Blog\Article空间而不是Article空间</span>
<span>$common</span> = <span>new</span> <span>$common_class_name</span>(); <span>//</span><span>发生致命错误:Article\Common类不存在</span>
<span>

namespace Blog\Article;

</span><span>class</span><span> Common { }

</span>?>
复制代码

 

 

总结

我对PHP的命名空间刚刚接触,也不能随便给一些没有实践的建议。我个人认为命名空间的作用和功能都很强大,如果要写插件或者通用库的时候再也不用担心重名问题。不过如果项目进行到一定程度,要通过增加命名空间去解决重名问题,我觉得工作量不会比重构名字少。也不得不承认它的语法会对项目增加一定的复杂度,因此从项目一开始的时候就应该很好的规划它,并制定一个命名规范。

 

 

www.bkjia.comtruehttp://www.bkjia.com/PHPjc/1129454.htmlTechArticlePHP命名空间(Namespace)初探,命名空间namespace 探完闭包[查看],再探命名空间。 对于命名空间,官方文档已经说得很详细[查看],我在这里...
성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
PHP 세션이 실패 할 수있는 몇 가지 일반적인 문제는 무엇입니까?PHP 세션이 실패 할 수있는 몇 가지 일반적인 문제는 무엇입니까?Apr 25, 2025 am 12:16 AM

phpsession 실패 이유에는 구성 오류, 쿠키 문제 및 세션 만료가 포함됩니다. 1. 구성 오류 : 올바른 세션을 확인하고 설정합니다. 2. 쿠키 문제 : 쿠키가 올바르게 설정되어 있는지 확인하십시오. 3. 세션 만료 : 세션 시간을 연장하기 위해 세션을 조정합니다 .GC_MAXLIFETIME 값을 조정하십시오.

PHP의 세션 관련 문제를 어떻게 디버그합니까?PHP의 세션 관련 문제를 어떻게 디버그합니까?Apr 25, 2025 am 12:12 AM

PHP에서 세션 문제를 디버그하는 방법 : 1. 세션이 올바르게 시작되었는지 확인하십시오. 2. 세션 ID의 전달을 확인하십시오. 3. 세션 데이터의 저장 및 읽기를 확인하십시오. 4. 서버 구성을 확인하십시오. 세션 ID 및 데이터를 출력, 세션 파일 컨텐츠보기 등을 통해 세션 관련 문제를 효과적으로 진단하고 해결할 수 있습니다.

session_start ()가 여러 번 호출되면 어떻게됩니까?session_start ()가 여러 번 호출되면 어떻게됩니까?Apr 25, 2025 am 12:06 AM

Session_Start ()로 여러 통화를하면 경고 메시지와 가능한 데이터 덮어 쓰기가 발생합니다. 1) PHP는 세션이 시작되었다는 경고를 발행합니다. 2) 세션 데이터의 예상치 못한 덮어 쓰기를 유발할 수 있습니다. 3) Session_status ()를 사용하여 반복 통화를 피하기 위해 세션 상태를 확인하십시오.

PHP에서 세션 수명을 어떻게 구성합니까?PHP에서 세션 수명을 어떻게 구성합니까?Apr 25, 2025 am 12:05 AM

SESSION.GC_MAXLIFETIME 및 SESSION.COOKIE_LIFETIME을 설정하여 PHP에서 세션 수명을 구성 할 수 있습니다. 1) SESSION.GC_MAXLIFETIME 서버 측 세션 데이터의 생존 시간을 제어합니다. 2) 세션 .Cookie_Lifetime 클라이언트 쿠키의 수명주기를 제어합니다. 0으로 설정하면 브라우저가 닫히면 쿠키가 만료됩니다.

세션을 저장하기 위해 데이터베이스를 사용하면 어떤 장점이 있습니까?세션을 저장하기 위해 데이터베이스를 사용하면 어떤 장점이 있습니까?Apr 24, 2025 am 12:16 AM

데이터베이스 스토리지 세션 사용의 주요 장점에는 지속성, 확장 성 및 보안이 포함됩니다. 1. 지속성 : 서버가 다시 시작 되더라도 세션 데이터는 변경되지 않아도됩니다. 2. 확장 성 : 분산 시스템에 적용하여 세션 데이터가 여러 서버간에 동기화되도록합니다. 3. 보안 : 데이터베이스는 민감한 정보를 보호하기 위해 암호화 된 스토리지를 제공합니다.

PHP에서 사용자 정의 세션 처리를 어떻게 구현합니까?PHP에서 사용자 정의 세션 처리를 어떻게 구현합니까?Apr 24, 2025 am 12:16 AM

SessionHandlerInterface 인터페이스를 구현하여 PHP에서 사용자 정의 세션 처리 구현을 수행 할 수 있습니다. 특정 단계에는 다음이 포함됩니다. 1) CustomsessionHandler와 같은 SessionHandlerInterface를 구현하는 클래스 만들기; 2) 인터페이스의 방법 (예 : Open, Close, Read, Write, Despare, GC)의 수명주기 및 세션 데이터의 저장 방법을 정의하기 위해 방법을 다시 작성합니다. 3) PHP 스크립트에 사용자 정의 세션 프로세서를 등록하고 세션을 시작하십시오. 이를 통해 MySQL 및 Redis와 같은 미디어에 데이터를 저장하여 성능, 보안 및 확장 성을 향상시킬 수 있습니다.

세션 ID 란 무엇입니까?세션 ID 란 무엇입니까?Apr 24, 2025 am 12:13 AM

SessionId는 웹 애플리케이션에 사용되는 메커니즘으로 사용자 세션 상태를 추적합니다. 1. 사용자와 서버 간의 여러 상호 작용 중에 사용자의 신원 정보를 유지하는 데 사용되는 무작위로 생성 된 문자열입니다. 2. 서버는 쿠키 또는 URL 매개 변수를 통해 클라이언트로 생성하여 보낸다. 3. 생성은 일반적으로 임의의 알고리즘을 사용하여 독창성과 예측 불가능 성을 보장합니다. 4. 실제 개발에서 Redis와 같은 메모리 내 데이터베이스를 사용하여 세션 데이터를 저장하여 성능 및 보안을 향상시킬 수 있습니다.

무국적 환경 (예 : API)에서 세션을 어떻게 처리합니까?무국적 환경 (예 : API)에서 세션을 어떻게 처리합니까?Apr 24, 2025 am 12:12 AM

JWT 또는 쿠키를 사용하여 API와 같은 무국적 환경에서 세션을 관리 할 수 ​​있습니다. 1. JWT는 무국적자 및 확장 성에 적합하지만 빅 데이터와 관련하여 크기가 크다. 2. 쿠키는보다 전통적이고 구현하기 쉽지만 보안을 보장하기 위해주의해서 구성해야합니다.

See all articles

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

Video Face Swap

Video Face Swap

완전히 무료인 AI 얼굴 교환 도구를 사용하여 모든 비디오의 얼굴을 쉽게 바꾸세요!

뜨거운 도구

SublimeText3 영어 버전

SublimeText3 영어 버전

권장 사항: Win 버전, 코드 프롬프트 지원!

ZendStudio 13.5.1 맥

ZendStudio 13.5.1 맥

강력한 PHP 통합 개발 환경

MinGW - Windows용 미니멀리스트 GNU

MinGW - Windows용 미니멀리스트 GNU

이 프로젝트는 osdn.net/projects/mingw로 마이그레이션되는 중입니다. 계속해서 그곳에서 우리를 팔로우할 수 있습니다. MinGW: GCC(GNU Compiler Collection)의 기본 Windows 포트로, 기본 Windows 애플리케이션을 구축하기 위한 무료 배포 가능 가져오기 라이브러리 및 헤더 파일로 C99 기능을 지원하는 MSVC 런타임에 대한 확장이 포함되어 있습니다. 모든 MinGW 소프트웨어는 64비트 Windows 플랫폼에서 실행될 수 있습니다.

Eclipse용 SAP NetWeaver 서버 어댑터

Eclipse용 SAP NetWeaver 서버 어댑터

Eclipse를 SAP NetWeaver 애플리케이션 서버와 통합합니다.

Atom Editor Mac 버전 다운로드

Atom Editor Mac 버전 다운로드

가장 인기 있는 오픈 소스 편집기