php 命名空间详解(带你看透吃透它)

未匹配的标注

php 命名空间详解(带你看透吃透它)

学习文章#

xueyuanjun.com/post/4221

记录问题#

1. 什么是命名空间?#

历史#

命名空间在 PHP5.3.0 中引入。

作用#

其作用是按照一种虚拟的层次结构组织 PHP 代码,这种层次结构类似操作系统中文件系统的目录结构。

为什么用?#

  1. 命名空间是现代 PHP 组件生态的基础
  2. 现代的 PHP 组件框架代码都是放在各自全局唯一的厂商命名空间中,以免和其他厂商使用的常见类名冲突。

2. 如何用命名空间?#

声明命名空间#

位置: 在 <?php 标签后的第一行声明
语法: 声明语句以 namespace 开头,随后是一个空格,然后是命名空间的名称,最后以 ; 结尾。


先简单来看看例子 1:
命名空间经常用于设置顶层厂商名,比如我们设置厂商名为 LaravelAcademy

<?php
namespace LaravelAcademy;

在这个命名空间声明语句后声明的所有 PHP 类、接口、函数和常量都在 LaravelAcademy 命名空间中。

听说过子命名空间吗?#

如果我们想用 LaravelAcademy 下的某个文件夹 ModernPHP 中的代码该怎么做呢?
答案是使用子命名空间。 子命名空间的声明方式和前面的示例完全一样,唯一的区别是我们要使用 \ (转义符号) 把命名空间和子命名空间分开,例如:

<?php
namespace LaravelAcademy\ModernPHP;

这个命名空间后的所有类、接口、函数和常量都位于 LaravelAcademy\ModernPHP 中。

结论:
在同一个命名空间中的类没必要在同一个 PHP 文件中声明,可以在 PHP 文件的顶部指定一个命名空间或子命名空间,此时,这个文件的代码就是该命名空间或子命名空间的一部分。因此我们可以在不同文件中编写属于同一个命名空间的多个类。


再来一个让你加深理解的例子 2:

例如, cart 和 order 这两个模块都处于同一个 shop 项目内,通过命名空间子空间表达关系。

`<?php`

`namespace` `shop\cart;` `//命名空间表示处于 shop 项目下的 cart`

`class` `Test {`

`}`

`namespace` `shop\order;` `//命名空间表示处于 shop 项目下的 order`

`class` `Test {`

`//申明与上面空间相同的类`

`}`

`$test` `=``new` `Test();` `//调用当前的类`

`$cart` `=` `new` `\shop\cart\Test();` `//调用shop\cart空间的类`

`?>`

命名空间的子空间还可以定义很多层次,例如 cn\my\www\shop 。多层子空间的声明通常使用公司域名的倒置,再加上项目名称组合而成。这样做的好处是域名在互联网上是不重复的,不会出现和网上同名的命名空间,还可以辨别出是哪家公司的具体项目。有很强的广告效应。

摘自 php 中文网


注:厂商命名空间是最顶层的命名空间,也是最重要的命名空间,用于识别品牌或组织,必须具有全局唯一性。子命名空间相对而言没那么重要,但是可以用于组织项目的代码。

导入和别名#

历史上的 php(在没有命名空间时)是如何导入别名的呢?#

使用 Zend 风格的类名解决命名冲突问题,蛇形命名,下划线拼接,以突出现实目录结构。

例如,Zend_Cloud_DocumentService_Adapter_WindowsAzure_Query 类对应的文件是 Zend/Cloud/DocumentService/Adapter/WindowsAzure/Query.php。可以看出,这种命名有个缺点:类名特别长。

现代的导入#

  1. 普通导入
    use 关键字告诉 PHP,我们想使用 Illuminate\Http\Response
<?php
use Illuminate\Http\Response;

$response = new Response(‘Oops’, 400);
$response->send();
  1. 别名导入

感觉命名还是很长?那就创建别名!
指的是告诉 PHP 我要使用简单的名称引用导入的类、接口、函数或常量:
关键字: as

<?php

use Illuminate\Http\Response as Res;

$res = new Res(‘Oops’, 400);
$res->send();
  1. 导入函数,use func (支持别名 as)
<?php
use func Namespace\functionName

functionName();
  1. 导入常量,use constant(支持别名 as)
<?php
use constant Namespace\CONST_NAME;

echo CONST_NAME;

实用技巧#

多重导入 多行 use 即可#

PHP 支持用简短的语法把多个 use 语句写成一行:

<?php
use Illuminate\Http\Request,
Illuminate\Http\Response;

但是为了可读性,建议不要这么写,还是一行写一个 use 语句比较好:

<?php
use Illuminate\Http\Request;
use Illuminate\Http\Response;

一个文件可以使用多个命名空间吗?(面试题)#

PHP 允许在一个文件中定义多个命名空间,但这么做不好,违背了 “一个文件一个类” 的良好实践,因此不建议这么做。

<?php
namespace Foo {
    //声明类、接口、函数、常量
}

namespace Bar {
    //声明类、接口、函数、常量
}

全局命名空间#

  1. 如何引入没有命名空间的类?

命名空间 + 类名

解释:
如果引用的类、接口、函数和常量没有指定命名空间,PHP 假定引用的类、接口、函数和常量在当前的命名空间中。如果要使用其他命名空间的类、接口、函数或常量,需要使用完全限定的 PHP 类名(命名空间 + 类名)。

  1. 全局命名空间例子: 原生的 Exception 类

有些代码在全局命名空间中,没有命名空间,比如原生的 Exception 类就是这样。在命名空间中引用全局的代码时,需要在类、接口、函数或常量前加 \ 符号:

<?php
namespace My\App;

class Foo {
    public function doSomething() {
        throw new \Exception();
    }
}

自动加载与命名空间的渊源#

  1. 命名空间是 PHP-FIG 制定的 PSR-4 自动加载标准的基础,
  2. 大多数现代的 PHP 组件都使用了这种自动加载模式,使用依赖管理器 Composer 可以自动加载项目的依赖。
  3. 没有命名空间,就没有现代的 PHP 生态系统和基于组件的新型架构。

本文章首发在 LearnKu.com 网站上。

上一篇 下一篇
wangchunbo
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
讨论数量: 0
发起讨论 只看当前版本


暂无话题~