• 微信号
目录

php基础

您当前的位置:首页 > 我的笔记 > php基础>php命名空间

php命名空间

为什么要使用命名空间

在程序开发中会涉及到大量的代码,而代码在编写的时候不可避免的乐能会出现重名的问题,但重名的类被调用时就会导致程序错误。因此php命名空间的概念就是为了解决这一问题。

php命名空间可以解决以下两类问题:

1.用户编写的代码与php内部的类、函数、常量或第三方类、函数、常量之间的名字冲突

2.为很长的标识符名称(通常是为了缓解第一类问题问而定义的)创建一个别名(或简短)的名称,提高源代码的可读性。

命名空间的定义

在默认情况下,所有常量、类和函数名都放在全局空间下。

命名空间通过关键字namespace来声明,如果一个文件中包含命名空间,它必须在其他所有代码之前声明命名空间。其语法格式如下:

<?php
    //定义命名空间
    namespance 命名空间;
    ……代码……
?>

可以在同一个文件中定义不同的命名空间:如

?php  
    namespace MyProject;

    const CONNECT_OK = 1;
    class Connection { /* ... */ }
    function connect() { /* ... */  }

    namespace AnotherProject;

    const CONNECT_OK = 1;
    class Connection { /* ... */ }
    function connect() { /* ... */  }
?>

不建议使用这种语法在单个文件中定义多个命名空间,建议使用大括号形式的语法

<?php
    namespace MyProject {
        const CONNECT_OK = 1;
        class Connection { /* ... */ }
        function connect() { /* ... */  }
    }

    namespace AnotherProject {
        const CONNECT_OK = 1;
        class Connection { /* ... */ }
        function connect() { /* ... */  }
    }
?>

将全局的非命名空间中的代码与命名空间中的代码组合在一起,只能使用大括号形式的语法。全局代码必须用一个不带名称的 namespace 语句加上大括号括起来,例如

<?php
    namespace MyProject {

    const CONNECT_OK = 1;
    class Connection { /* ... */ }
    function connect() { /* ... */  }
    }

    namespace { // 全局代码
    session_start();
    $a = MyProject\connect();
    echo MyProject\Connection::start();
    }
?>

在声明命名空间之前唯一合法的代码是用于定义源文件编码方式的 declare 语句。所有非 PHP 代码包括空白符都不能出现在命名空间的声明之前

<?php
    declare(encoding='UTF-8'); //定义多个命名空间和不包含在命名空间中的代码
    namespace MyProject {

    const CONNECT_OK = 1;
    class Connection { /* ... */ }
    function connect() { /* ... */  }
    }

    namespace { // 全局代码
    session_start();
    $a = MyProject\connect();
    echo MyProject\Connection::start();
    }
?>

定义子命名空间

与目录和文件关系很想,php命名空间也允许指定层次化的命名空间名称,通常把这种用法定位为自命名空间,具体如下所示:

<?php
    namespace MyProject\Sub\Level;  //声明分层次的单个命名空间

    const CONNECT_OK = 1;
    class Connection { /* ... */ }
    function Connect() { /* ... */  }
?>

命名空间的使用

php命名空间中类名可以通过以下三种方式引用

  • 1.非限定名称,或不包含前缀的类名称,例如 $a=new foo(); 或 foo::staticmethod();。如果当前命名空间是 currentnamespace,foo 将被解析为 currentnamespace\foo。如果使用 foo 的代码是全局的,不包含在任何命名空间中的代码,则 foo 会被解析为foo。
    警告:如果命名空间中的函数或常量未定义,则该非限定的函数名称或常量名称会被解析为全局函数名称或常量名称
  • 2.限定名称,或包含前缀的名称,例如 $a = new subnamespace\foo(); 或 subnamespace\foo::staticmethod();。如果当前的命名空间是 currentnamespace,则 foo 会被解析为 currentnamespace\subnamespace\foo。如果使用 foo 的代码是全局的,不包含在任何命名空间中的代码,foo 会被解析为subnamespace\foo。
  • 3.完全限定名称,或包含了全局前缀操作符的名称,例如, $a = new \currentnamespace\foo(); 或 \currentnamespace\foo::staticmethod();。在这种情况下,foo 总是被解析为代码中的文字名(literal name)currentnamespace\foo。

代码中如何使用命名空间?示例如下

<?php
    include "file1.php";
    include "file2.php";
    //使用各自命名空间实例化对象
    $filter=new \file1\Clean(); //使用完成限定名称
    $profanity=new file2\Clean(); //使用完成限定名称
?>

上述代码中,使用完全限定名称和限定名称的方式分别对类Clean进行引用。需要注意的是,如果当前文件中声明了命名空间,此时实现限定名称的方式引用成员可能会出错

命名空间除了可以解决命名冲突之外,还可以用来定义别名,当程序中多次使用某个类或者命名空间时,每次不得不写一长串的单词,使程序阅读性变差。为此,php提供了别名机制,允许通过别名引用或导入外部完成限定名称

在php中,命名空间的别名通过ues关键字来实现的

php命名空间支持两种使用别名或导入的方式:一是为类名称使用别名;二是为命名空间使用别名。示例代码如下

<?php
    namespace foo;
    include "file1.php";
    include "file2.php";
    use file1\Clean as X; //为file1中的Clean类名定义为x
    use file2\Clean; //为file2中的Clean类定义别名为Clean
    use file2 as Y; //为命名空间file2定义别名为Y
    $filter=new X(); //实例化file1\Clean对象
    $profanity=new Clean(); // 实例化file2\Clean对象
    $profanity1=new Y\Clean();
?>

在使用时需要注意以下几点

(1)使用别名机制只能导入类,不支持导入变量或函数

(2)对命名空间来说,前面的反斜杆不是必须的,因为导入的名称必须是完全限定的,它不会根据当前的命名空间作出相对的解析,如果使用了反斜杆开始,则便是访问的是全局命名空间中的类

(3)如果省略了 as ,实际上它隐式使用了别名Clean

(4)导入操作只影响费限定名称和限定名称,用于完全限定名称是确定的,所以不受导入影响

注意

  • 1.php在5.3.0后的版本才开始支持命名空间
  • 2.虽然任意合法的php代码都可以包含在命名空间中,但只有三种类型的代码受命名空间影响,它们是:类,函数和常量
  • 3.所有非php代码包括空白符都不能出现在命名空间声明之前,下面的用法是错误的
    <html>
    <?php
       namespace myprject; //致命错误-命名空间必须是程序脚本的第一条语句
    ?>