技术开发 频道

PHP V5.3 中的新特性: 名称空间

        PHP 名称空间用例

  名称空间的总体目标就是帮助我们更好地组织代码,减少全局空间内的定义数量。在本节中,我们将查看一些例子,看看名称空间如何帮助我们轻松地实现这些目标。

  使用名称空间的第三方代码

  许多 PHP 应用程序使用来自不同来源的代码,包括像 PEAR 库那样经过精心设计的代码,或者来自 CakePHP 或 Zend Framework 等各种框架的代码,或是来自 Internet 上不同位置的代码。在集成这些代码时,最主要的问题之一就是这些代码可能无法恰当地融合到已有代码中;函数或类名可能与应用程序中已经在使用的内容冲?。

  其中一个例子就是 PEAR Date 包。它使用类名 Date,这是一个非常通用的类名,并且可以很好地切入到代码中的其他位置。因此,一个良好的解决方法就是在包内部的 Date.php 文件的顶部添加一个简单的名称空间命令。现在,当希望使用 PEAR Date 类而不是我们自己的 PEAR Date 类时,就不会感到迷惑。

  清单 8. 按照名称空间的定义使用 PEAR Date 类

1 <?php
2
3 require_once('PEAR/Date.php');
4
5 use PEAR\Date;    // the name of the namespace we've specified in PEAR/Date.php
6
7 // since the current namespace is PEAR\Date, we don't need to prefix the namespace name
8 $now = new Date();
9 echo $now->getDate();  // outputs the ISO formatted date
10
11 // this example shows the full namespace specified as part of the class name
12 $now = new PEAR\Date\Date();
13 echo $now->getDate();  // outputs the ISO formatted date  
14 ?>
15

  我们已经在 PEAR/Date.php 文件的 PEAR/Date 名称空间内定义了 PEAR Date 类,因此现在只需在我们的文件中包含代码并使用名称空间,或使用名称空间的名称作为类或函数名的前缀。通过这种方法,我们就可以安全地在应用程序中包含第三方代码。

  名称冲突不仅仅是第三方代码才有的问题。如果大型代码库的各个部分永远不会互相靠近,那么也会出现此问题。在下一小节中,我们将了解名称空间如何应对这个情况。

  避免实用函数名冲突

  几乎所有 PHP 应用程序都具有大量实用方法。虽然并非应用程序的任意对象都包含实用方法,并且也不一定存在于应用程序的所有部分,但是总的来说它在应用程序中确实发挥着作用。但是,随着应用程序不断壮大,实用方法会引起维护问题。

  其中一个产生问题的位置就是单元测试,我们编写代码来测试运行应用程序的代码。大多数单元测试套件被设计为运行整个测试套件中的所有测试。比如,我们有两个永远不会包含在一起的实用方法文件,但是在测试套件中,它们就会包含在一起,因为我们会一次性测试整个应用程序。尽管使用这种方式设计应用程序不利于长期维护,但是它确实存在于大型遗留代码库中。

  清单 9 展示了如何避免这一问题。我们有两个文件 utils_left.php 和 utils_right.php,这是面向主要使用右手的用户和主要使用左手的用户的实用函数集合。对于每个文件,我们在其各自的名称空间内分别定义。

  清单 9. utils_left.php 和 utils_right.php

1 /* utils_left.php */
2 <?php
3 namespace Utils\Left;
4
5 function whichHand()
6 {
7     echo "I'm using my left hand!";
8 }
9 ?>
10
11 /* utils_right.php */
12 <?php
13 namespace Utils\Right;
14
15 function whichHand()
16 {
17     echo "I'm using my right hand!";
18 }
19 ?>
20

  我们定义了一个 whichHand() 函数,函数的输出表示我们使用哪一只手。在清单 10 中,我们看到可以方便地包含两个文件并在希望调用的名称空间之间进行切换。

  清单 10. 同时使用 utils_left.php 和 utils_right.php 的示例

1 <?php
2 include('./utils_left.php');
3 include('./utils_right.php');
4
5 Utils\Left\whichHand();    // outputs "I'm using my left hand!"
6 Utils\Right\whichHand();  // outputs "I'm using my right hand!"
7
8 use Utils\Left;
9 whichHand();                 // outputs "I'm using my left hand!"
10
11 use Utils\Right;
12 whichHand();                 // outputs "I'm using my right hand!"
13

  现在,两个文件可以安全地包含在一起,并且我们指定了处理函数调用所需使用的名称空间。而且,对现有代码的影响很小,因为重构功能只需要我们在文件的顶部添加 use 语句,表示要使用的名称空间。

  可以对我们定义的 PHP 代码进一步扩展。在下一小节,我们将了解如何在名称空间内覆盖内部函数。

  覆盖内部函数名称

  虽然 PHP 的内部函数经常可以提供非常棒的实用方法,但有时它们不能按照我们期望的那样执行。我们需要增强它们的行为,以使函数符合我们的期望,但是我们也需要使用另一个名字重新定义函数,从而避免进一步混淆范围。

  文件系统函数就需要我们执行这些操作。假设我们需要确保 file_put_contents() 创建的任何文件具有某些权限集。比如,假设我们希望这些文件的权限为只读;我们可以使用一个新的名称空间重新定义函数,如下所示。

  清单 11. 在名称空间内定义 file_put_contents()

1 <?php
2 namespace Foo;
3
4 function file_put_contents( $filename, $data, $flags = 0, $context = null )
5 {
6     $return = \file_put_contents( $filename, $data, $flags, $context );
7     
8     chmod($filename, 0444);
9
10     return $return;
11 }
12 ?>
13

  我们在函数内调用内部 file_put_contents() 函数并使用一个反斜杠作为函数名的前缀,表示该函数应当在全局范围内处理,这表示将调用内部函数。调用了内部函数后,我们随后对文件执行 chmod() 命令来设置相应的权限。

  还有许多例子可以演示如何使用名称空间增强代码。在任何情况下,我们应避免执行不恰当的修改,比如将函数名或类名作为前缀以生成独特的名称。我们现在还了解了如何使用名称空间在大型应用程序中更加安全地包含第三方代码,同时不需要担心名称冲突。

  结束语

  PHP V5.3 的名称空间是该语言中一个非常受欢迎的新增特性,可以帮助开发人员合理地组织应用程序的代码。该特性使您能够避免使用标准来处理名称空间,允许您编写更高效的代码。尽管名称空间的出现经历了很长时间,但对于受名称冲突困扰的大型 PHP 应用程序来说,它是一个非常受欢迎的特性。

0
相关文章