zoukankan      html  css  js  c++  java
  • How to Use PHP Namespaces, Part 1: The Basics

    命名空间是一个重要的概念。该系列文章详细介绍了PHP对命名空间的支持及用法。原文地址:http://www.sitepoint.com/php-53-namespaces-basics/

    命名空间是PHP 5.3诸多重要更新中的一个。它会使C#和Java开发者感到友好,同时很有希望使PHP应用的程序结构变得更好。

    为什么需要命名空间?
         随着你的PHP代码库的增长,意外重定义之前已声明过的函数的风险也在增加。这个问题会在引入第三方组件或插件时恶化——如果多段代码都实现了”Database”或者”User”类, 会发生什么呢?
         直到现在,唯一的解决方案就是命名一个较长的类或函数名。例如,WordPress在每一个命名前使用”WP_”前缀。Zend Framework使用高度可描述的命名约定,而这会导致产生诸如Zend_Search_Lucene_Analysis_Analyzer_Common_Text_CaseInsensitive这样冗长的类名。
         命名空间可解决命名冲突的问题。可以把PHP常量、类和函数组织到使用了命名空间的代码库中。
    如何定义命名空间?
         默认情况下,所有的常量、类及函数命名都位于全局空间内——就像PHP未支持命名空间之前的样子。
         命名空间化的代码在PHP文件的顶部使用namespace关键字。该关键字之前不能有PHP或HTML代码,只可有空白字符或declare关键字。
    1
    2
    3
    4
    <?php
    // define this code in the 'MyProject' namespace
    namespace MyProject;
    // ... code ...
      在namespace关键字之后的代码都会纳入”MyProject”命名空间。命名空间不能嵌套或在同一代码处声明多次(只有最后一次会被识别)。但是,你能在同一个文件中定义多个命名空间化的代码。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <?php
    namespace MyProject1;
    // PHP code for the MyProject1 namespace
    namespace MyProject2;
    // PHP code for the MyProject2 namespace
    // Alternative syntax
    namespace MyProject3 {
        // PHP code for the MyProject3 namespace
    }
    ?>

    虽然这种用法从语法方面讲是可行的,但明智的做法是每个文件定义一个命名空间。

      子命名空间
         PHP允许定义命名空间层级。子命名空间使用反斜线来分隔。例如:
    • MyProjectSubName
    • MyProjectDatabaseMySQL
    • CompanyNameMyProjectLibraryCommonWidget1
    调用已命名空间化的代码
         在lib1.php文件中的AppLib1命名空间内定义一个常量、一个函数以及一个类
      lib1.php
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    <?php
    // application library 1
    namespace AppLib1;
    const MYCONST = 'AppLib1MYCONST';
    function MyFunction() {
         return __FUNCTION__;
    }
    class MyClass {
         static function WhoAmI() {
              return __METHOD__;
         }
    }
    ?>

    在另一个PHP文件中包含此文件。

      myapp.php

    1
    2
    3
    4
    5
    6
    7
    <?php
    header('Content-type: text/plain');
    require_once('lib1.php');
    echo AppLib1MYCONST . " ";
    echo AppLib1MyFunction() . " ";
    echo AppLib1MyClass::WhoAmI() . " ";
    ?>

    因在myapp.php中未定义任何命名空间,所以全部代码都位于全局空间内。任何对MYCONST、MyFunction 或者MyClass 的直接引用都会失败,因为他们位于AppLib1命名空间内。当想调用lib1.php中的代码,必须加上”AppLib1″前缀形成完全限定名(fully-qualified names)。myapp.php的运行结果为:

    AppLib1MYCONST
    AppLib1MyFunction
    AppLib1MyClass::WhoAmI

    完全限定名也会很长,而且相对于诸如 App-Lib1-MyClass这样的长类名并无明显好处。因此,在下篇文章中将会讨论命名空间别名,同时对PHP如何处理命名空间做近距离观察。

     

    How to Use PHP Namespaces, Part 2: Importing, Aliases, and Name Resolution

     

    在下面的示例中,定义了两段几乎完全相同的代码,唯一的不同之处就在于它们的命名空间。
    lib1.php
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    <?php
    // application library 1
    namespace AppLib1;
    const MYCONST = 'AppLib1MYCONST';
    function MyFunction() {
        return __FUNCTION__;
    }
    class MyClass {
        static function WhoAmI() {
            return __METHOD__;
        }
    }
    ?>

    lib2.php

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    <?php
    // application library 2
    namespace AppLib2;
    const MYCONST = 'AppLib2MYCONST';
    function MyFunction() {
        return __FUNCTION__;
    }
    class MyClass {
        static function WhoAmI() {
            return __METHOD__;
        }
    }
    ?>
    先来了解一些PHP术语:
    完全限定名
    任何PHP代码都具有完全限定名——一个以反斜线起始的标识符。例如:AppLib1MYCONST, AppLib2MyFunction()。
    完全限定名不会产生任何歧义。首个反斜线与文件系统路径类似,都指明了“根”全局空间。如果在全局空间内实现了一个MyFunction()函数,可在lib1.php和lib2.php中使用“MyFunction()”对其进行调用。
    完全限定名对一次性函数调用或对象初始化有帮助。然而,它们不适用于大量调用的情况。就像接下来要看到的,PHP为命名空间输入提供了其他一些选择。
    部分限定名
    至少有一个命名空间分隔符的标识符。例如:Lib1MyFunction().
    未限定名
    没有命名空间分隔符的标识符。例如:MyFunction().
    在同一命名空间内工作
    考虑以下代码:
    myapp1.php
    1
    2
    3
    4
    5
    6
    7
    8
    9
    <?php
    namespace AppLib1;
    require_once('lib1.php');
    require_once('lib2.php');
    header('Content-type: text/plain');
    echo MYCONST . " ";
    echo MyFunction() . " ";
    echo MyClass::WhoAmI() . " ";
    ?>
    虽然同时包含了lib1.php和lib2.php,但MYCONST, MyFunction, and MyClass只会引用lib1.php中的代码。因为myapp1.php的代码同样位于Applib1命名空间内。
    result: 
    AppLib1MYCONST
    AppLib1MyFunction
    AppLib1MyClass::WhoAmI
    
    命名空间导入
    命名空间可通过use操作符导入。例如
    myapp2.php
    1
    2
    3
    4
    5
    6
    7
    8
    9
    <?php
    use AppLib2;
    require_once('lib1.php');
    require_once('lib2.php');
    header('Content-type: text/plain');
    echo Lib2MYCONST . " ";
    echo Lib2MyFunction() . " ";
    echo Lib2MyClass::WhoAmI() . " ";
    ?>

     

    可使用任意数量的use语句或使用逗号分隔每个独立的命名空间。在此例中,导入了“AppLib2”命名空间。但此刻仍然无法直接引用MYCONST, MyFunction 或 MyClass,因为调用他们的代码位于全局空间内,PHP将会在全局空间内查找它们。然而,如果我们加入“Lib2”前缀,它们便形成部分限定名,PHP将会在已导入的命名空间内搜索直到找到匹配项。
    result
    AppLib2MYCONST
    AppLib2MyFunction
    AppLib2MyClass::WhoAmI
    命名空间别名
    命名空间别名或许是最有帮助的功能。别名可使较短的名称来代替较长名称。
    myapp3.php
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <?php
    use AppLib1 as L;
    use AppLib2MyClass as Obj;
    header('Content-type: text/plain');
    require_once('lib1.php');
    require_once('lib2.php');
    echo LMYCONST . " ";
    echo LMyFunction() . " ";
    echo LMyClass::WhoAmI() . " ";
    echo Obj::WhoAmI() . " ";
    ?>
    第一个use语句设定"App/Lib1"的别名为“L”,任何使用"L"的部分限定名都会在编译阶段被解释为“App/Lib1”。因此可使用 LMYCONST 和 LMyFunction来代替完全限定名。
    第二个use语句非常有趣。它将'Obj'设定为AppLib2命名空间内的类MyClass的别名。这种别名设定方式只对类有效,常量与函数不适用。
    设定类别名后,就可以用new Obj()来创建实例或直接调用静态方法了。
    AppLib1MYCONST
    AppLib1MyFunction
    AppLib1MyClass::WhoAmI
    AppLib2MyClass::WhoAmI
    PHP命名解析规则
    PHP标识符命名解析遵循以下规则:
    1. 在编译阶段解析拥有完全限定名的常量、类或函数的调用。
    2. 未限定和部分限定名根据命名空间导入规则进行解释。例如,如果命名空间ABC被导入且设定别名为C,那么CDe()调用将被解释为ABCDe()
    3. 在命名空间内,所有未根据命名空间导入规则进行解释的部分限定名都会拥有当前命名空间的前缀。例如:如果在命名空间AB内执行CDe()调用,它将会被解释为 ABCDe()。
    4. 未限定的类名会根据当前导入的命名空间进行解释,同时会使用全名来代替缩写后的名称。例如:如果在命名空间AB内的类C被导入为X,new X()将被解释为 new ABC()。
    5. 命名空间内的未限定函数调用会在运行时解析。例如:如果MyFunction()在命名空间AB内被调用,PHP首先会搜索函数ABMyFunction(),如果未找到匹配项,PHP会在全局空间内搜索MyFunction()函数。
    6. 调用未限定或部分限定名的类会在运行时解析。例如:如果在命名空间AB内调用new C(),PHP会搜索类ABC,如果未能找到匹配项,PHP将会试图自动载入类ABC。
  • 相关阅读:
    find the first t.py file through traversal C: and D:
    gevent simple server
    【python实例】判断是否是回文数
    【python实例】要求输出字符串中最少一个最多八个的所有字符串组合(连续)
    【python实例】统计字符串里大写字母,小写字母和非字母的个数
    【python基础】字符串方法汇总
    【python实例】判断质数:for-break-else
    【python实例】while&for 九九乘法表
    【python实例】水仙花数:每个位上的数值的三次方求和,刚好是这个三位数本身
    【python实例】判断输入年份是否是闰年
  • 原文地址:https://www.cnblogs.com/dsphper/p/4231697.html
Copyright © 2011-2022 走看看