跳转到主要内容
goodwong 提交于 7 July 2013

------------------------------------------------------------------------------------ 【备注】:本文正在校对中,对PHP命名空间熟悉的朋友请帮忙一起校对!谢谢! ------------------------------------------------------------------------------------

 

原文链接:https://drupal.org/node/1353118

 

PHP 5.3 introduces namespaces to the language. This page documents how namespaces should be referenced within Drupal and it assumes that you are familiar with the concept of namespaces. PHP 5.3 版本引入了命名空间机制,本文介绍Drupal与命名空间的关系,并假设你熟悉命名空间的概念(译者注:若你不了解命名空间的一些术语,可以参考这两篇文章名称解析规则命名空间)。

Not all files in Drupal declare a namespace. As of Drupal 8 an increasing number of files do, but not all. Prior to Drupal 8 virtually no code used namespaces, in order to remain compatible with PHP 5.2. There are therefore two slightly different standards. 并非所有的Drupal文件都声明了命名空间,从Drupal8开始命名空间用得越来越多,但也只是部分文件而已。在Drupal8之前为了兼容php 5.2,几乎没有使用命名空间的代码。因此,有两套略有不同的标准。

用“use”语法导入类("use"-ing classes)

  • Classes and interfaces with a backslash \inside their fully-qualified name (for example: Drupal\simpletest\WebTestBase) must not use their fully-qualified name inside the code. If the namespace differs from the namespace of the current file, put a usestatement on the top of the file. For example: 若类或接口的全名中带有反斜杠(比如:Drupal\simpletest\WebTestBase),则代码中不可使用完全限定名称。如果要导入外部的命名空间,请先在文件头部使用"use"。
    <?php
    namespace Drupal\mymodule\Tests\Foo;
    
    use Drupal\simpletest\WebTestBase;
    
    /**
    * Tests that the foo bars.
    */
    class BarTest extends WebTestBase {
    ?>
  • Classes and interfaces without a backslash \inside their fully-qualified name (for example, the built-in PHP Exception class) must be fully qualified when used in a namespaced file. For example: new \Exception();. 在命名空间中使用那些全名中不带反斜杠\的类或者接口(比如PHP内置的Exception异常类),必须使用完全限定名称。比如:new \Exception();。
  • In a file that does not declare a namespace (and is therefore in the global namespace), classes in any namespace other than global must be specified with a "use" statement at the top of the file. 在一个没有声明命名空间的文件里(即算为全局命名空间),如果你要使用自其它非全局的命名空间的类,你得在文件头使用"use"关键字声明这些类。
  • When importing a class with "use", do not include a leading \. (The PHP documentation makes the same recommendation.) 使用"use"关键字导入类时,请不要使用反斜杠\号开头(PHP官方文档里也是这么建议的)
  • When specifying a class name in a string, use its full name including namespace, without leading \. 当在字符串中指定类名时,请使用带命名空间的全类名,并且不要以\开头。

    Escape the namespace separator in double-quoted strings: "Drupal\\Context\\ContextInterface" 如果在双引号中使用命名空间,请转义命名空间分割符:"Drupal\\Context\\ContextInterface"

    Do not escape it in single-quoted strings: 'Drupal\Context\ContextInterface' 在单引号里面的命名空间分割符就不必转义了:'Drupal\Context\ContextInterface'

    As stated elsewhere, single-quoted strings are generally preferred. 除非特别要求,一般首选单引号字符串,更方便。

  • Specify a single class per use statement. Do not specify multiple classes in a single use statement. 每个“use”语句只导入一个类,而不是在一个“use”语句中导入多个类名。(译者注:虽然语法上允许,但这不是个好的编码习惯)
  • API documentation (in .api.php files) should use full class names. Note that if a class is used more than once in multiple hook signatures, it must still be "use"ed, and then only the short names of the class should be used in the function. API文档(在.api.php文件里的)中请使用类的全名,你得知道别人若要在多个hook中使用一个类,他们首先得"use"你这个类,然后才能在函数里面使用你这些类的简短别名。

Example: 样例:

<?php
/**
* @file
* Contains \Drupal\Subsystem\Foo.
*/

namespace Drupal\Subsystem;

// This imports just the Cat class from the Drupal\Othersystem namespace.
// 仅仅导入Drupal\Othersystem命名空间里的Cat类
use Drupal\Othersystem\Cat;

// Bar is a class in the Drupal\Subsystem namespace in another file.
// It is already available without any importing.
// Bar是另一个文件里的类,也属于Drupal\Subsystem命名空间

/**
* Defines a Foo.
* 定义一个东西。
*/
class Foo {

  /**
   * Constructs a new Foo object.
   * Foo对象的构造函数
   */
  public function __construct(Bar $b, Cat $c) {
    // Global classes must be prefixed with a \ character.
    // 在命名空间中使用全局类,必须在类名前面使用反斜杠。
    $d = new \DateTime();
  }

}
?>

<?php
/**
* @file
* The Example module.
* 一个模块样例
*
* This file is not part of any namespace, so all global namespaced classes
*  are automatically available.
* 这个文件不属于任何命名空间,因此所有的属于全局命名空间的类都是不用导入即可直接使用的。
*/

use Drupal\Subsystem\Foo;

/**
* Does stuff with Foo stuff.
* 让Foo做点事
*
* @param \Drupal\Subsystem\Foo $f
*   A Foo object used to bar the baz.
*   怎么译啊.
*/
function do_stuff(Foo $f) {
  // The DateTime class does not need to be imported as it is already global
  // 因为DateTime这个类本来就是全局的,就不用导入了
  $d = new DateTime();
}
?>

类的别名(Class aliasing)

PHP allows classes to be aliased when they are imported into a namespace. In general that should only be done to avoid a name collision. If a collision happens, alias both colliding classes by prefixing the next higher portion of the namespace. 当你把一个类导入到当前命名空间时,可以给它起个别名,主要是为了避免命名冲突。一旦两个类重名了,可以将各自命名空间里的上一级别的名字拿出来作为相应的前缀。

Example: 比如:

<?php
use Foo\Bar\Baz as BarBaz;
use Stuff\Thing\Baz as ThingBaz;

/**
* Tests stuff for the whichever.
* 各做一些测试
*/
function test() {
  $a = new BarBaz(); // This will be Foo\Bar\Baz
  $b = new ThingBaz(); // This will be Stuff\Thing\Baz
}
?>

That helps keep clear which one is which, and where it comes from. Aliasing should only be done to avoid name collisions. 这样既能分清谁是谁,也知道它们来自哪个命名空间。虽然如此,一般也只在命名冲突时,才建议使用别名。

模块(Modules)

Modules creating classes should place their code inside a custom namespace. The convention for those namespaces is 模块里的类应该声明在相应的命名空间下面,通常是遵照以下惯例

namespace Drupal\example_module

To support autoloading, these classes should be placed inside the correct folder: 你得把类文件放在与命名空间一致的文件夹里,这样才能自动加载你的类文件。 sites/all/modules/example_module/lib/Drupal/example_module <module folder> /lib/ <namespace>