PHP关键特性之命名空间实例详解

命名空间主要是为了解决代码中类和函数可能存在冲突的问题,而这个特性其他语言一早就有,PHP则是姗姗来迟,它的出现催生了 PSR-4 的诞生,从而也催生了 Composer 的兴起,所以是非常重要的特性。

命名空间的定义

命名空间是一个容器,这个容器主要是为了识别其下的类和函数。一旦定义了命名空间,它下面的代码就属于这个命名空间了,所以命名空间的定义要在代码的最开始行。

对于同一个包来说,同一个命名空间或者子命名空间的代码没有必要在一个 PHP 文件中定义,子命名空间下的代码是为了完成特定模块的工作,组合起来就是一个包完整的命名空间。

假如编写的代码没有定义命名空间,那说明它属于全局的命名空间(\ 符号),所以能够直接引用类或者函数(不用添加 \ 符号)。

引用命名空间标识符的三种方式

(1)Fully-qualified name

类似于操作系统上的绝对路径,而且是完整的路径,所以在理解的时候不会有误解。

比如在 new \A\B\C ,那么 C 就被会解析到 A\B 命名空间下的 C 类。

(2)Qualified name

类似于操作系统上的相对路径,它包含部分名字并被引用到当前的命名空间。

比如 B\C() 在命名空间 A 下调用,则最终引用的命名空间就是 A\B\C()。

(3)Unqualified name

类似于Qualified name,但是没包括子命名空间。

比如 C() 在命名空间 A\B 下调用,则最终引用的命名空间就是 A\B\C()。

通过一个例子来说明三种引用方式:

namespace \Example;
require_once "fnction.php";
class ClassA {}
function Function() {}
//完全限定名称
\Example\Function();
\Example\B\Function();
//限定名称
B\Function(); //指向 \Example\B\Function();
//非限定名称
$test = new ClassA(); //resolves to \Example\ClassA
Function(); //指向 \Example\Function

注意:

•Inside a namespace,假如在 current scope 没有发现函数和常量的定义,PHP 不会报错。而是去全局命名空间中寻找。

•Inside a namespace,假如在 current scope 没有发现类的定义,则 PHP 会直接报错,不会去全局域中找对应的类,所以假如你需要引用一个 internal 或用户自定义的类,必须使用完全限定名称。

先举个简单的例子,首先编写一段代码(定义在命名空间下),命名为 function.php :

namespace Foo\Bar\subnamespace;
const FOO = 1;
function foo()
{
  return "foo\r\n";
}
class foo
{
  static function staticmethod()
  {
    return __METHOD__ . "\r\n" ;
  }
  function foofunction()
  {
    return __METHOD__ . "\r\n" ;
  }
}

再编写一段代码 test.php,也是处于命名空间之下的代码:

namespace secondsp;
include 'function.php';
class foo
{
  function foofunction()
  {
    return __METHOD__ . "\r\n" ;
  }
}
function is_file($file)
{
  return true ;
}
//非限定名称:实例化secondsp\foo类对象
$obj = new foo;
echo $obj->foofunction();
//实例化Foo\Bar\subnamespace\foo 类对象
$obj = new Foo\Bar\subnamespace\foo ;
echo $obj->foofunction();
//代码会报错,在命名空间内部,假如无法找到当前命名空间下的类,则会报错
//$obj = new ArrayObject(array(1));
$obj = new \ArrayObject(array(1));
//在命名空间内部,假如无法找到当前命名空间下的函数或者常量,则会寻找 native function
echo strlen("nihao");
 //引用当前命名空间下的函数
var_dump(is_file('nihao')); //True
//引用全局函数
var_dump(\is_file('nihao')); //False

导入,别名

假如要使用的命名空间层级很长且数量很多,那么在使用的时候特别麻烦,所以可以使用 use 关键字导入命名空间、类、常量、函数等,然后可以使用它们直接引用完整的名称。而 alias 关键字可以给导入的类和函数等重命名。

举个例子如何使用 use 关键字,该代码处于全局命名空间之下:

include 'function.php';
use Foo\Bar\subnamespace\foo ;
$obj = new foo;
echo $obj->foofunction();
use Foo\Bar\subnamespace\foo as aliasfunname;
$obj = new aliasfunname;
echo $obj->foofunction();
use Foo\Bar\subnamespace ;
$obj = new subnamespace\foo ;
echo $obj->foofunction();
use Foo\Bar\subnamespace as aliasname;
$obj = new aliasname\foo ;
echo $obj->foofunction();
//由于调用代码并不在命名空间内,所以对于全局的类,无需引入使用
$obj = new ArrayObject(array(1));
//导入一个函数
use function Foo\Bar\subnamespace\foo  ;
echo foo();
use function Foo\Bar\subnamespace\foo as func;
echo func();
use const Foo\Bar\subnamespace\FOO;
//echo FOO;

总结:

•和 Python 不一样,PHP 中的命名空间是语义上的一种概念,和具体代码的位置、布局没有关系,换句话说,使用命名空间的代码需要自己引入库文件(所有文件),至于库文件如何组织无所谓;而在 Python 中,假如模块或包中有一个 __init__.py 文件,则 Python 解析器会自动引入包或所有模块的文件。

•PHP 中作用域的概念很弱化,全局域和局部域分的很清楚,比如在函数或类中无法引用全局空间中的变量。而在命名空间则不同,定义命名空间的代码,假如找不到对应命名空间下的常量和函数,则会使用全局的常量和函数;而假如找不到对应名命名空间下的类(包括自定义类),则代码直接报错。

•通过 use 关键字使用命名空间的,无须通过完全限定名称的方式(\ 符号)导入,因为 PHP 已经假设导入的是完全限定的命名空间。

•通过 use 关键字可以导入常量、函数、类、接口、其他命名空间。

•命名空间是一种语言特性,为了追求更有效的使用,应该有一种使用规范和自动加载机制,这就是 PSR-4 规范。

以上所述是小编给大家介绍的PHP关键特性之命名空间实例详解,希望对大家有所帮助,如果大家有任何疑问欢迎给我留言,小编会及时回复大家的!

(0)

相关推荐

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

    命名空间概述 在PHP中,命名空间用来解决在编写类库或应用程序时创建可重用的代码如类或函数时碰到的两类问题: 用户编写的代码与PHP内部的类/函数/常量或第三方类/函数/常量之间的名字冲突.为很长的标识符名称(通常是为了缓解第一类问题而定义的)创建一个别名(或简短)的名称,提高源代码的可读性.PHP 命名空间提供了一种将相关的类.函数和常量组合到一起的途径.下面是一个说明 PHP 命名空间语法的示例: 定义命名空间 虽然任意合法的PHP代码都可以包含在命名空间中,但只有三种类型的代码受命名空间的

  • thinkphp autoload 命名空间自定义 namespace

    使用thinkPHP过程中,一些自定义的类库和第三方类库需要找一个合适的位置放置,放到系统默认的org文件夹感觉不太好,破坏了thinkPHP的原生目录. 就看了一下官方手册,可以在模块或者应用的配置文件里自定义类库的命名空间. 不过使用中需要注意的是,你的自定义的命名空间名称需要和你的文件夹名称相对应,不能更改. 然后测试一下 以上所述就是本文的全部内容了,希望大家能够喜欢.

  • PHP命名空间(namespace)的动态访问及使用技巧

    PHP的命名空间(namespace)是PHP 5.3中加入最重要的一个新特性,这个概念在C#中已经很早就有了,php中的namespace其实和c#的概念是一样的. 一.动态访问命名空间的元素 namespace me\poet; function test() { echo '1111'; } $fun = 'test';//不能这么用,最后$fun()无法动态调用到test():Fatal error: Call to undefined function test() $fun = '\

  • PHP命名空间(Namespace)简明教程

    这一特性在 PHP5.0x 时候就提出过,后来被取消并安排在 PHP6 中实现.而此次又再次"提前"到了 PHP5.3 发布,可见开发人员对其的重视以及谨慎的态度. 官方发布时说明文档的内容可能已过期(documentation maybe out dated),所以在这里简单的说明命名空间的用法:首先是声明一个命名空间,加入了新的关键字 namespace ,其应在类文件的开头 复制代码 代码如下: <?php   namespace Project::Module;    c

  • PHP中的命名空间详细介绍

    概述 PHP对于命名空间的支持,经历了一段艰难的旅程.幸运的是,PHP从5.3开始引入了命名空间.自从PHP引入了命名空间,PHP代码的适用结构也得到了大大的改善.许多编程语言早就有了命名空间的概念,相对于其他语言来说,PHP对于命名空间的支持,稍微有点晚了.不管如何,每一种新特性的引入都有其目的,和其他语言一样,PHP引入命名空间也主要是为了解决名字冲突的问题. 命名空间(namespace)的概念 复制代码 代码如下: 当在字符串中使用命名空间名字的时候,一定不要忘了转义\ 可以将命名空间想

  • PHP命名空间(namespace)的使用基础及示例

    PHP的命名空间(namespace)是PHP 5.3中加入最重要的一个新特性,这个概念在C#中已经很早就有了,php中的namespace其实和c#的概念是一样的. 一. PHP的命名空间主要解决三种冲突的问题:常量,函数,类 通俗理解:namespace就相当于是用来建一个目录,将namespace下面的代码放在该目录里面,与外面的区分开来. /* |--------------------------------- |namespace示例 |@黑眼诗人 <www.chenwei.ws>

  • PHP关键特性之命名空间实例详解

    命名空间主要是为了解决代码中类和函数可能存在冲突的问题,而这个特性其他语言一早就有,PHP则是姗姗来迟,它的出现催生了 PSR-4 的诞生,从而也催生了 Composer 的兴起,所以是非常重要的特性. 命名空间的定义 命名空间是一个容器,这个容器主要是为了识别其下的类和函数.一旦定义了命名空间,它下面的代码就属于这个命名空间了,所以命名空间的定义要在代码的最开始行. 对于同一个包来说,同一个命名空间或者子命名空间的代码没有必要在一个 PHP 文件中定义,子命名空间下的代码是为了完成特定模块的工

  • Java8新特性Stream流实例详解

    什么是Stream流? Stream流是数据渠道,用于操作数据源(集合.数组等)所生成的元素序列. Stream的优点:声明性,可复合,可并行.这三个特性使得stream操作更简洁,更灵活,更高效. Stream的操作有两个特点:可以多个操作链接起来运行,内部迭代. Stream可分为并行流与串行流,Stream API 可以声明性地通过 parallel() 与sequential() 在并行流与顺序流之间进行切换.串行流就不必再细说了,并行流主要是为了为了适应目前多核机器的时代,提高系统CP

  • Java8 新特性Lambda表达式实例详解

    Java8 新特性Lambda表达式实例详解 在介绍Lambda表达式之前,我们先来看只有单个方法的Interface(通常我们称之为回调接口): public interface OnClickListener { void onClick(View v); } 我们是这样使用它的: button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { v.setText("

  • C#语法新特性之元组实例详解

    1.元组(Tuple) 元组(Tuple)在4.0 的时候就有了,但元组也有些缺点,如: 1)Tuple 会影响代码的可读性,因为它的属性名都是:Item1,Item2.. . 2)Tuple 还不够轻量级,因为它是引用类型(Class),对于一个变量要使用一个类型,有点太没必要了. 源代码如下: // 摘要: // 提供用于创造元组对象的静态方法.若要浏览此类型的.NET Framework 源代码,请参阅 Reference Source. public static class Tuple

  • C++命名空间实例详解

    一个中大型软件往往由多名程序员共同开发,会使用大量的变量和函数,不可避免地会出现变量或函数的命名冲突.当所有人的代码都测试通过,没有问题时,将它们结合到一起就有可能会出现命名冲突. 例如小李和小韩都参与了一个文件管理系统的开发,它们都定义了一个全局变量 fp,用来指明当前打开的文件,将他们的代码整合在一起编译时,很明显编译器会提示 fp 重复定义(Redefinition)错误. 为了解决合作开发时的命名冲突问题,C++ 引入了命名空间(Namespace)的概念.请看下面的例子: namesp

  • JDK19新特性使用实例详解

    目录 前提 新特性列表 新特性使用详解 Record模式 Linux/RISC-V移植 外部函数和内存API 虚拟线程 向量API switch匹配模式 结构化并发 前提 JDK19于2022-09-20发布GA版本,本文将会详细介绍JDK19新特性的使用. 新特性列表 新特性列表如下: JPE-405:Record模式(预览功能) JPE-422:JDK移植到Linux/RISC-V JPE-424:外部函数和内存API(预览功能) JPE-425:虚拟线程,也就是协程(预览功能) JPE-4

  • Java8新特性 StreamAPI实例详解

    目录 Stream结果收集 结果收集到集合中 结果收集到数组中 对流中的数据做聚合计算 对流中数据做分组操作 对流中的数据做分区操作 对流中的数据做拼接 并行的Stream流 串行的Stream流 并行流 获取并行流 并行流操作 并行流和串行流对比 线程安全问题 Stream结果收集 面试官:说说你常用的StreamAPI. 结果收集到集合中 public static void main(String[] args){ // Stream<String> stream = Stream.of

  • springboot与mybatis整合实例详解(完美融合)

    简介 从 Spring Boot 项目名称中的 Boot 可以看出来,Spring Boot 的作用在于创建和启动新的基于 Spring 框架的项目.它的目的是帮助开发人员很容易的创建出独立运行和产品级别的基于 Spring 框架的应用.Spring Boot 会选择最适合的 Spring 子项目和第三方开源库进行整合.大部分 Spring Boot 应用只需要非常少的配置就可以快速运行起来. Spring Boot 包含的特性如下: 创建可以独立运行的 Spring 应用. 直接嵌入 Tomc

  • Python探索之URL Dispatcher实例详解

    URL dispatcher简单点理解就是根据URL,将请求分发到相应的方法中去处理,它是对URL和View的一个映射,它的实现其实也很简单,就是一个正则匹配的过程,事先定义好正则表达式和该正则表达式对应的view方法,如果请求的URL符合这个正则表达式,那么就分发这个请求到这个view方法中. 有了这个base,我们先抛出几个问题,提前思考一下: 这个映射定义在哪里?当映射很多时,如果有效的组织? URL中的参数怎么获取,怎么传给view方法? 如何在view或者是template中反解出UR

  • Java编程思想对象的容纳实例详解

    Java提供了容纳对象(或者对象的句柄)的多种方式,接下来我们具体看看都有哪些方式. 有两方面的问题将数组与其他集合类型区分开来:效率和类型.对于Java来说,为保存和访问一系列对象(实际是对象的句柄)数组,最有效的方法莫过于数组.数组实际代表一个简单的线性序列,它使得元素的访问速度非常快,但我们却要为这种速度付出代价:创建一个数组对象时,它的大小是固定的,而且不可在那个数组对象的"存在时间"内发生改变.可创建特定大小的一个数组,然后假如用光了存储空间,就再创建一个新数组,将所有句柄从

随机推荐