乐趣区

关于php:PHP中命名空间是怎样的存在三

这是与命名空间无关的最初一篇。最初还是两个比较简单的内容,是对于命名空间和全局相干的一些类、函数、常量的应用比照。当然,最初咱们还会总结一下命名空间的名称解析规定做为这三篇系列文章的完结。

全局空间

当文件中定义了命名空间,也就是 namesapce 指定了以后的命名空间后,在调用全局类、函数、常量时,须要增加一个“\”,也就是齐全限定拜访符号来表明这个类、函数、常量是全局的那个,而不是以后命名空间中的。特地是以后命名空间中蕴含与全局类、函数、常量同名的内容时。

namespace FILE6;

function show()
{echo strtoupper('aaa'), PHP_EOL; // 调用本人的
    echo \strtoupper('aaa'), PHP_EOL; // 调用全局的
}

function strtoupper($str)
{return __NAMESPACE__ . ':' . \strtoupper($str);
}

在这个 FILE6 命名空间中,咱们定义了一个 strtoupper() 办法。之间说过,命名空间就是为了解决同名问题而呈现的,这个办法和全局 php 自带的那个办法是完全相同的名称的。所以,在调用的时候咱们须要调用的是哪个办法。那么如果以后命名空间中没有定义这个办法呢?别急,接下来的内容就是讲这个问题。

后备全局函数 / 常量

从上个例子中,咱们就能够看出全局齐全限定拜访符的作用,当没有应用全局符时,strtoupper() 办法会先调用以后命名空间下的办法。那么后备的作用就是如果以后命名空间中没有找到时,会去全局找相干的函数。在文档中的定义是这样的:

当 PHP 遇到一个非限定的类、函数或常量名称时,它应用不同的优先策略来解析该名称。类名称总是解析到以后命名空间中的名称。因而在拜访零碎外部或不蕴含在命名空间中的类名称时,必须应用齐全限定名称。对于函数和常量来说,如果以后命名空间中不存在该函数或常量,PHP 会退而应用全局空间中的函数或常量。

意思也就是说,函数和常量,会有后备去全局查找的能力。然而类不行!!如果要应用全局类,肯定要加全局齐全限定符。咱们通过一个例子来看:

namespace FILE7;

// 类必须应用齐全限定的全局空间
$o1 = new \stdClass();
// $o2 = new stdClass(); // Fatal error: Uncaught Error: Class 'FILE7\stdClass' not found

// 办法会先在本命名空间查找,如果没找到会去全局找
function strlen($str)
{return __NAMESPACE__ . ':' . (\strlen($str) - 1);
}
echo strlen('abc'), PHP_EOL; // FILE7:2,以后命名空间
echo \strlen('abc'), PHP_EOL; // 3,全局

echo strtoupper('abc'), PHP_EOL; // ABC,全局

// 常量也是有后备能力的

const E_ERROR = 22; 
echo E_ERROR, PHP_EOL; // 22,以后命名空间
echo \E_ERROR, PHP_EOL; // 1,全局

echo INI_ALL, PHP_EOL; // 7,全局 

名称解析规定

  1. 对齐全限定名称的函数,类和常量的调用在编译时解析。例如 new \A\B 解析为类 A\B。
  2. 所有的非限定名称和限定名称(非齐全限定名称)依据以后的导入规定在编译时进行转换。例如,如果命名空间 A\B\C 被导入为 C,那么对 C\D\e() 的调用就会被转换为 A\B\C\D\e()。
  3. 在命名空间外部,所有的没有依据导入规定转换的限定名称均会在其后面加上以后的命名空间名称。例如,在命名空间 A\B 外部调用 C\D\e(),则 C\D\e() 会被转换为 A\B\C\D\e()。
  4. 非限定类名依据以后的导入规定在编译时转换(用全名代替短的导入名称)。例如,如果命名空间 A\B\C 导入为 C,则 new C() 被转换为 new A\B\C()。
  5. 在命名空间外部(例如 A\B),对非限定名称的函数调用是在运行时解析的。例如对函数 foo() 的调用是这样解析的:

    • 在以后命名空间中查找名为 A\B\foo() 的函数
    • 尝试查找并调用 全局 (global) 空间中的函数 foo()。
  6. 在命名空间(例如 A\B)外部对非限定名称或限定名称类(非齐全限定名称)的调用是在运行时解析的。上面是调用 new C() 及 new D\E() 的解析过程:new C() 的解析:

    • 在以后命名空间中查找 A\B\C 类。
    • 尝试主动装载类 A\B\C。

new D\E() 的解析:

  1. 在类名称后面加上以后命名空间名称变成:A\B\D\E,而后查找该类。
  2. 尝试主动装载类 A\B\D\E。

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

测试代码:
https://github.com/zhangyue0503/dev-blog/blob/master/php/202001/source/namespace/file6.php
[https://github.com/zhangyue05…]https://github.com/zhangyue0503/dev-blog/blob/master/php/202001/source/namespace/file7.php()

参考文档:
https://www.php.net/manual/zh/language.namespaces.global.php
https://www.php.net/manual/zh/language.namespaces.fallback.php
https://www.php.net/manual/zh/language.namespaces.rules.php

===========

各自媒体平台均可搜寻【硬核项目经理】

退出移动版