PHP 面向对象程序设计(oop)学习笔记 (五) - PHP 命名空间

 更新时间:2014年06月12日 16:37:40   投稿:hebedich  
PHP 在 5.3.0 以后的版本开始支持命名空间。什么是命名空间?从广义上来说,命名空间是一种封装事物的方法。在很多地方都可以见到这种抽象概念。

命名空间概述

在PHP中,命名空间用来解决在编写类库或应用程序时创建可重用的代码如类或函数时碰到的两类问题:

用户编写的代码与PHP内部的类/函数/常量或第三方类/函数/常量之间的名字冲突。
为很长的标识符名称(通常是为了缓解第一类问题而定义的)创建一个别名(或简短)的名称,提高源代码的可读性。
PHP 命名空间提供了一种将相关的类、函数和常量组合到一起的途径。下面是一个说明 PHP 命名空间语法的示例:

定义命名空间

虽然任意合法的PHP代码都可以包含在命名空间中,但只有三种类型的代码受命名空间的影响,它们是:类,函数和常量。命名空间通过关键字namespace 来声明。如果一个文件中包含命名空间,它必须在其它所有代码之前声明命名空间。另外,与PHP其它的语言特征不同,同一个命名空间可以定义在多个文件中,即允许将同一个命名空间的内容分割存放在不同的文件中。当然你也可以在同一个文件中定义多个命名空间。

复制代码 代码如下:

namespace MyProject;
class MyClass
{
    #code...
}

定义子命名空间:与目录和文件的关系很象,PHP 命名空间也允许指定层次化的命名空间的名称。因此,命名空间的名字可以使用分层次的方式定义:

复制代码 代码如下:

namespace MyProject\helper\http;
class MyClass
{
    #code...
}

在同一个文件中定义多个命名空间:在同一个文件中声明多个命名空间有两种方式,不过在实际编程实践中,非常不提倡在同一个文件中定义多戈命名空间。这种方式的主要用于将多个 PHP 脚本合并在同一个文件中。下面列出第一种方法。

复制代码 代码如下:

namespace MyProject\helper\http;
class MyClass
{
    #code...
}
namespace MyProject\helper\request;
class MyClass
{
    #code...
}

不过强烈不建议使用这种方法,可以参考下面的大括号定义法:

复制代码 代码如下:

namespace MyProject\helper\http;
{
    class MyClass
    {
        #code...
    }
}
namespace MyProject\helper\request;
{
    class MyClass
    {
        #code...
    }
}

PHP 命名空间中的元素使用

在讨论如何使用命名空间之前,必须了解 PHP 是如何知道要使用哪一个命名空间中的元素的。类名可以通过三种方式引用:

非限定名称,或不包含前缀的类名称,例如 $a=new foo(); 或 foo::staticmethod();。如果当前命名空间是 currentnamespace,foo 将被解析为 currentnamespace\foo。如果使用 foo 的代码是全局的,不包含在任何命名空间中的代码,则 foo 会被解析为foo。 警告:如果命名空间中的函数或常量未定义,则该非限定的函数名称或常量名称会被解析为全局函数名称或常量名称。详情参见 使用命名空间:后备全局函数名称/常量名称。

限定名称,或包含前缀的名称,例如 $a = new subnamespace\foo(); 或 subnamespace\foo::staticmethod();。如果当前的命名空间是 currentnamespace,则 foo 会被解析为 currentnamespace\subnamespace\foo。如果使用 foo 的代码是全局的,不包含在任何命名空间中的代码,foo 会被解析为subnamespace\foo。

完全限定名称,或包含了全局前缀操作符的名称,例如, $a = new \currentnamespace\foo(); 或 \currentnamespace\foo::staticmethod();。在这种情况下,foo 总是被解析为代码中的文字名(literal name)currentnamespace\foo。
使用命名空间:别名/导入

允许通过别名引用或导入外部的完全限定名称,是命名空间的一个重要特征。PHP 命名空间支持 有两种使用别名或导入方式:为类名称使用别名,或为命名空间名称使用别名。在PHP中,别名是通过操作符 use 来实现的。

注意PHP不支持导入函数或常量。

复制代码 代码如下:

namespace foo;
use My\Full\Classname as Another;

// 下面的例子与 use My\Full\NSname as NSname 相同
use My\Full\NSname;

// 导入一个全局类
use \ArrayObject;

名称解析规则

在说明名称解析规则之前,我们先看一些重要的定义:

非限定名称Unqualified name:名称中不包含命名空间分隔符的标识符,例如 Foo
限定名称Qualified name:名称中含有命名空间分隔符的标识符,例如 Foo\Bar
完全限定名称Fully qualified name:名称中包含命名空间分隔符,并以命名空间分隔符开始的标识符,例如 \Foo\Bar。 namespace\Foo 也是一个完全限定名称。
名称解析遵循下列规则:

对完全限定名称的函数,类和常量的调用在编译时解析。例如 new \A\B 解析为类 A\B。
所有的非限定名称和限定名称(非完全限定名称)根据当前的导入规则在编译时进行转换。例如,如果命名空间 A\B\C 被导入为 C,那么对 C\D\e() 的调用就会被转换为 A\B\C\D\e()。
在命名空间内部,所有的没有根据导入规则转换的限定名称均会在其前面加上当前的命名空间名称。例如,在命名空间 A\B 内部调用 C\D\e(),则 C\D\e() 会被转换为 A\B\C\D\e() 。
非限定类名根据当前的导入规则在编译时转换(用全名代替短的导入名称)。例如,如果命名空间 A\B\C 导入为C,则 new C() 被转换为 new A\B\C() 。
在命名空间内部(例如A\B),对非限定名称的函数调用是在运行时解析的。例如对函数 foo() 的调用是这样解析的:
1) 在当前命名空间中查找名为 A\B\foo() 的函数
2) 尝试查找并调用 全局(global) 空间中的函数 foo()。
在命名空间(例如A\B)内部对非限定名称或限定名称类(非完全限定名称)的调用是在运行时解析的。下面是调用 new C() 及 new D\E() 的解析过程: new C()的解析:
在当前命名空间中查找A\B\C类。
尝试自动装载类A\B\C。

new D\E()的解析:
在类名称前面加上当前命名空间名称变成:A\B\D\E,然后查找该类。
尝试自动装载类 A\B\D\E。

为了引用全局命名空间中的全局类,必须使用完全限定名称 new \C()。

Example 名称解析示例

复制代码 代码如下:

<?php
namespace A;
use B\D, C\E as F;
// 函数调用
foo();      // 首先尝试调用定义在命名空间"A"中的函数foo()
            // 再尝试调用全局函数 "foo"
\foo();     // 调用全局空间函数 "foo"
my\foo();   // 调用定义在命名空间"A\my"中函数 "foo"
F();        // 首先尝试调用定义在命名空间"A"中的函数 "F"
            // 再尝试调用全局函数 "F"
// 类引用
new B();    // 创建命名空间 "A" 中定义的类 "B" 的一个对象
            // 如果未找到,则尝试自动装载类 "A\B"
new D();    // 使用导入规则,创建命名空间 "B" 中定义的类 "D" 的一个对象
            // 如果未找到,则尝试自动装载类 "B\D"
new F();    // 使用导入规则,创建命名空间 "C" 中定义的类 "E" 的一个对象
            // 如果未找到,则尝试自动装载类 "C\E"
new \B();   // 创建定义在全局空间中的类 "B" 的一个对象
            // 如果未发现,则尝试自动装载类 "B"
new \D();   // 创建定义在全局空间中的类 "D" 的一个对象
            // 如果未发现,则尝试自动装载类 "D"
new \F();   // 创建定义在全局空间中的类 "F" 的一个对象
            // 如果未发现,则尝试自动装载类 "F"
// 调用另一个命名空间中的静态方法或命名空间函数
B\foo();    // 调用命名空间 "A\B" 中函数 "foo"
B::foo();   // 调用命名空间 "A" 中定义的类 "B" 的 "foo" 方法
            // 如果未找到类 "A\B" ,则尝试自动装载类 "A\B"
D::foo();   // 使用导入规则,调用命名空间 "B" 中定义的类 "D" 的 "foo" 方法
            // 如果类 "B\D" 未找到,则尝试自动装载类 "B\D"
\B\foo();   // 调用命名空间 "B" 中的函数 "foo"
\B::foo();  // 调用全局空间中的类 "B" 的 "foo" 方法
            // 如果类 "B" 未找到,则尝试自动装载类 "B"
// 当前命名空间中的静态方法或函数
A\B::foo();   // 调用命名空间 "A\A" 中定义的类 "B" 的 "foo" 方法
              // 如果类 "A\A\B" 未找到,则尝试自动装载类 "A\A\B"
\A\B::foo();  // 调用命名空间 "A\B" 中定义的类 "B" 的 "foo" 方法
              // 如果类 "A\B" 未找到,则尝试自动装载类 "A\B"
?>

相关文章

  • PHP之CI框架学习讲解

    PHP之CI框架学习讲解

    这篇文章主要介绍了PHP之CI框架学习讲解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-08-08
  • Laravel框架集合用法实例浅析

    Laravel框架集合用法实例浅析

    这篇文章主要介绍了Laravel框架集合用法,结合实例形式简单分析了Laravel框架集合的基本原理、创建与使用方法,需要的朋友可以参考下
    2020-05-05
  • thinkphp5上传图片及生成缩略图公共方法(分享)

    thinkphp5上传图片及生成缩略图公共方法(分享)

    下面小编就为大家分享一篇thinkphp5上传图片及生成缩略图公共方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-01-01
  • Symfony2获取web目录绝对路径、相对路径、网址的方法

    Symfony2获取web目录绝对路径、相对路径、网址的方法

    这篇文章主要介绍了Symfony2获取web目录绝对路径、相对路径、网址的方法,结合实例形式分析了Symfony获取路径与网址的常用操作技巧,并给出了Request完整文件的源码供大家下载参考,需要的朋友可以参考下
    2016-11-11
  • laravel Task Scheduling(任务调度)在windows下的使用详解

    laravel Task Scheduling(任务调度)在windows下的使用详解

    今天小编就为大家分享一篇laravel Task Scheduling(任务调度)在windows下的使用详解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-10-10
  • php 购物车完整实现代码

    php 购物车完整实现代码

    本文介绍一个php实现的购物车代码,功能实现比较完整,实现了购物车、订货人信息、会员价等功能,还是不错的,有需要的朋友,可以参考下
    2014-06-06
  • Yii框架多语言站点配置方法分析【中文/英文切换站点】

    Yii框架多语言站点配置方法分析【中文/英文切换站点】

    这篇文章主要介绍了Yii框架多语言站点配置方法,结合实例形式分析了基于Yii框架实现中文/英文切换的多语言站点相关配置方法与操作注意事项,需要的朋友可以参考下
    2020-04-04
  • Yii框架form表单用法实例

    Yii框架form表单用法实例

    这篇文章主要介绍了Yii框架form表单用法,实例分析了Yii中form表单的实现方法与相关技巧,非常具有实用价值,需要的朋友可以参考下
    2014-12-12
  • ThinkPHP控制器里javascript代码不能执行的解决方法

    ThinkPHP控制器里javascript代码不能执行的解决方法

    这篇文章主要介绍了ThinkPHP控制器里javascript代码不能执行的解决方法,采用ThinkPHP的<literal>标签来解决javascript标签被解析的问题,是非常实用的技巧,需要的朋友可以参考下
    2014-11-11
  • PHP中cookie和session的区别实例分析

    PHP中cookie和session的区别实例分析

    这篇文章主要介绍了PHP中cookie和session的区别,比较详尽的分析了二者从创建、运用到清除的各个流程的注意事项,需要的朋友可以参考下
    2014-08-08

最新评论