php命名空间_PHP命名空间

php命名空间

Namespaces were a long awaited feature in PHP. While many other important features were released with PHP 5, namespaces were not supported until version 5.3. This led to various techniques for emulating them which, though necessary, were messy and confusing. Although namespaces have been part of PHP for over a year now, such techniques still exist. Many developers simply don’t know how to use proper namespaces in their code. In this article I will explain why namespaces are important and how you can use them in your own PHP code.

命名空间是PHP中期待已久的功能。 虽然PHP 5发行了许多其他重要功能,但直到5.3版才支持名称空间。 这导致了各种模拟它们的技术,尽管有必要,但它们是混乱且混乱的。 尽管名称空间已经成为PHP的一部分,但是这种技术仍然存在。 许多开发人员根本不知道如何在代码中使用适当的名称空间。 在本文中,我将解释为什么命名空间很重要,以及如何在自己PHP代码中使用它们。

为什么要使用命名空间? (Why Use Namespaces?)

Imagine you work for a small company that doesn’t have many employees. When talking about a co-worker, you refer to him by his first name. After an exceptionally successful year, your boss decides to double the number of employees. Suddenly, when you mention “Tom,” people are no longer sure to whom you are referring since there now a number of Toms at the office. To differentiate between them, you start using their last names too.

假设您在一家没有很多员工的小公司工作。 在谈论同事时,您用他的名字称呼他。 经过了非常成功的一年,您的老板决定将雇员人数增加一倍。 突然,当您提到“汤姆”时,人们不再确定您指的是谁,因为现在办公室里有许多汤姆。 为了区分它们,您也开始使用它们的姓氏。

This metaphor illustrates the concept of namespaces. A namespace is a named container for identifiers such as class names and function names that you use in your programs. It groups them together and removes the possibility of name-clashes. In the example, the employees’ last names served as namespaces. Because family members are often grouped together, multiple Toms are able to co-exist without any ambiguity.

这个比喻说明了名称空间的概念。 名称空间是一个命名容器,用于存储您在程序中使用的标识符,例如类名和函数名。 它将它们组合在一起,消除了名称冲突的可能性。 在示例中,员工的姓氏用作名称空间。 由于家庭成员通常被分组在一起,因此多个Toms可以毫无歧义地共存。

Large applications often have hundreds or thousands of components, which lead to a large number of name-clashes. Namespaces allow you to elegantly group components and avoid this problem.

大型应用程序通常具有成百上千个组件,这导致大量的名称冲突。 命名空间使您可以优雅地对组件进行分组并避免此问题。

Before namespaces were available, developers emulated them in object-oriented code by prefixing each component’s classes with a component name. For example, one standard was to join component and class names using underscores; the mail class in the blog component was named Blog_Mail. This practice led to many long, and sometimes confusing, class names. Consider the name of a class in the PHPUnit framework, PHPUnit_Framework_MockObject_Matcher_StatelessInvocation. This obviously isn’t ideal, which is why programmers needed proper support for namespaces in PHP.

在命名空间可用之前,开发人员通过在每个对象的类前面加上一个组件名称,在面向对象的代码中模拟它们。 例如,一种标准是使用下划线连接组件名称和类名称。 博客组件中的邮件类名为Blog_Mail 。 这种做法导致了许多冗长的,有时是令人困惑的类名。 考虑一下PHPUnit框架中的类的名称PHPUnit_Framework_MockObject_Matcher_StatelessInvocation 。 这显然不是理想的,这就是为什么程序员需要对PHP中的名称空间的适当支持。

定义命名空间 (Defining Namespaces)

A namespace is defined with the namespace keyword and a name. It must be declared before any other code, with the exception of rarely used declare statements. Once defined, the scope of the namespace applies to the entire file.

名称空间是用namespace关键字和名称定义的。 除很少使用的declare语句外,必须在其他任何代码之前声明它。 定义后,名称空间的范围将应用于整个文件。

<?php
namespace MyNamespace;
// ...

A namespace may alternatively be defined by wrapping brackets around its contents. No code is allowed outside the brackets except for the previously mentioned declare.

命名空间也可以通过在其内容周围用括号来定义。 除了前面提到的declare外,方括号之外不允许有任何代码。

<?php
namespace MyNamespace {
    // ...
}

These two methods cannot be mixed, so choose one and stick to it.

这两种方法不能混合使用,因此请选择一种并坚持使用。

Nested namespaces can be defined by separating each level with a backslash.

可以通过用反斜杠分隔每个级别来定义嵌套的名称空间。

<?php
namespace MyProject\Blog\Admin;

Multiple namespaces may be defined in a single file by using the namespace keyword multiple times. In such instances, the scope of the preceding namespace ends once the next namespace definition appears.

通过多次使用namespace关键字,可以在单个文件中定义多个命名namespace 。 在这种情况下,一旦出现下一个名称空间定义,前面的名称空间的范围就会结束。

<?php
namespace MyProject\Blog;
// following definitions are part of the MyProject\Blog namespace
// ...
namespace MyProject\Store;
// following definitions are now part of MyProject\Store
// ...

To set part of the file’s code in the global namespace, use the namespace keyword without a name. This feature can only be used in conjunction with the curly bracket syntax.

要在全局名称空间中设置文件代码的一部分,请使用不带名称的namespace关键字。 此功能只能与花括号语法一起使用。

<?php
namespace My\Project {
    // My\Project namespace
    // ...
}
namespace {
    // Global namespace
    // ...
}

引用命名空间标识符 (Referencing Namespaced Identifiers)

Although any code can appear within the namespace, only classes, interfaces, functions and constants are affected by it. These identifiers can be referenced in one of three ways:

尽管任何代码都可以出现在名称空间中,但是只有类,接口,函数和常量会受到其影响。 可以通过以下三种方式之一引用这些标识符:

  1. Fully-qualified name

    全限定名称

    A fully-qualified name is like an absolute path in a file system. It is the full name of the identifier; therefore there is no ambiguity about which identifier is being referenced. Fully-qualified names begin with a backslash. For example,

    完全限定的名称就像文件系统中的绝对路径。 它是标识符的全名; 因此,对于引用哪个标识符没有任何歧义。 完全限定的名称以反斜杠开头。 例如,

    My\Foo\Bar looks for the class Bar in the namespace My\Foo.

    My\Foo\Bar寻找类Bar命名空间中的My\Foo

  2. Qualified name

    合格名称

    A qualified name is like a relative path in a file system. It contains only part of the name and resolves relative to the current namespace. For example,

    限定名称就像文件系统中的相对路径。 它仅包含名称的一部分,并相对于当前名称空间进行解析。 例如,

    Foo\myFunction() in the namespace MyBaz resolves to \My\Baz\Foo\myFunction().

    MyBaz名称空间中的Foo\myFunction()解析为\My\Baz\Foo\myFunction()

  3. Unqualified name

    不合格的名字

    An unqualified name is identical to a qualified name except it refers to the current namespace only and not to any sub-namespaces. For example,

    非限定名称与限定名称相同,只是它仅引用当前名称空间,而不引用任何子名称空间。 例如,

    getPosts() in the namespace My\Foo\Blog resolves to Blog\getPosts(). If a function or constant is not found in the current scope, PHP won’t look for \My\Foo\getPosts(), rather it will just resolve the identifier to the global namespace.

    My\Foo\Blog命名空间中的getPosts()解析为Blog\getPosts() 。 如果在当前作用域中未找到函数或常量,则PHP不会查找\My\Foo\getPosts() ,而只会将标识符解析为全局名称空间。

Let’s look at an example. file1.php contains a couple of mock definitions namespaced as \MyProject\Blog.

让我们来看一个例子。 file1.php包含几个模拟定义,命名为\MyProject\Blog

<?php
namespace \MyProject\Blog;
class myClass {}
function myFunction() {}

Now file2.php declares the MyProject namespace, includes file1.php, and defines mock definitions that would seemingly conflict. The definitions don’t, though, because they live in separate namespaces. Then the file goes on to show examples of how fully-qualified, qualified, and unqualified names are resolved.

现在, file2.php声明MyProject命名空间,包括file1.php ,并定义似乎冲突的模拟定义。 但是,定义不是,因为它们位于单独的命名空间中。 然后,该文件继续显示如何解析完全限定,限定和不限定名称的示例。

<?php
namespace \MyProject;
require_once "file1.php";
class myClass {}
function myFunction() {}

// fully-qualified names
\MyProject\myFunction();
\MyProject\Blog\myFunction(); 

// qualified name
\Blog\myFunction(); //resolves to \MyProject\Blog\myFunction();

// unqualified name
$test = new myClass(); // resolves to \MyProject\myClass
myFunction(); // resolves to \MyProject\myFunction

Notice that to reference classes and interfaces in the global namespace, you must begin their names with a backslash, i.e., use their fully-qualified name. This is not required for functions and constants unless an identifier with the same name is found in the current scope. To illustrate this, consider the following example:

注意,要引用全局名称空间中的类和接口,必须以反斜杠开头它们的名称,即使用其完全限定的名称。 除非在当前作用域中找到具有相同名称的标识符,否则函数和常量都不需要这样做。 为了说明这一点,请考虑以下示例:

<?php
namespace \Foo\Bar;
function file_exists($filename) { return true; }

// Incorrect: "Fatal error: Class '\Foo\Bar\ArrayObject' not found..."
$obj = new ArrayObject();
// Correct
$obj = new \ArrayObject();

// Doesn't need backslash; resolves to native function
echo strlen("Hello, world!");
// Resolves to dummy function, \Foo\Bar\file_exists()
echo file_exists('non-existent-file'); // True
// Resolves to real function
echo \file_exists('non-existent-file'); // False

use关键字 (The use Keyword)

In a large application that contains many, deeply-nested namespaces, it can become cumbersome to write out identifier names. To avoid this, you can import namespaces, classes and interfaces using the use keyword. This allows them to be referenced by an alias instead of their full name. use statements must be declared in the outermost scope of the file.

在包含许多深度嵌套的名称空间的大型应用程序中,写出标识符名称可能变得很麻烦。 为避免这种情况,您可以使用use关键字导入名称空间,类和接口。 这样就可以用别名而不是其全名来引用它们。 use语句必须在文件的最外层范围内声明。

Here is an example:

这是一个例子:

<?php
use \Very\Long\Namespace;
use \Another\Long\Namespace\ClassName;

// resolves to \Very\Long\Namespace\aFunction();
Namespace\aFunction();
// resolves to \Another\Long\Namespace\ClassName
$obj = new ClassName();

Only unqualified and qualified names are affected by aliases; fully-qualified names are not. Therefore, the following will not be affected by the defined aliases:

别名仅影响不合格和合格的名称; 完全合格的名称不是。 因此,以下将不受定义的别名的影响:

<?php
$obj = new \ClassName();

To specify a specific alias, use the as keyword followed by the alias.

要指定特定的别名,请使用as关键字,后跟别名。

<?php
use \Very\Long\Namespace as MyNamespace;
// resolves to \Very\Long\Namespace\ClassName
$obj = new MyNamespace\ClassName();

For convenience, PHP lets you separate multiple namespace declarations with commas.

为了方便起见,PHP使您可以用逗号分隔多个名称空间声明。

<?php
use \Very\Long\Namespace as MyNamespace,
    \Another\Long\Namespace\ClassName;

To explicitly use the current namespace and avoid aliases, use the namespace keyword before the identifier name.

要显式使用当前名称空间并避免使用别名,请在标识符名称之前使用namespace关键字。

<?php
// resolves to current namespace, not \Another\Long\Namespace\ClassName
$obj = new namespace\ClassName();

动态功能 (Dynamic Features)

PHP offers some support for using namespaces dynamically, as well. The magic __NAMESPACE__ constant is defined by PHP at compile time and contains the current namespace as a string. In the global namespace, __NAMESPACE__ contains an empty string.

PHP还为动态使用名称空间提供了一些支持。 神奇的__NAMESPACE__常量由PHP在编译时定义,并包含当前名称空间作为字符串。 在全局名称空间中, __NAMESPACE__包含一个空字符串。

Namespaced identifiers can be dynamically referenced just like normal identifiers, with one exception: identifiers can only be referenced using fully-qualified names. For example:

可以像普通标识符一样动态引用命名空间标识符,但有一个例外:只能使用完全限定的名称来引用标识符。 例如:

<?php
$class = '\MyProject\Blog\MyClass';
$obj = new $class();

You should always escape backslashes when they are in double-quoted strings, since certain character combinations have special meanings. For example, “n” is the newline character, “t” is the tab character, etc. Failing to do so can lead to unexpected results. For example, the following code will not work as expected:

当反斜杠在双引号中时,您应始终转义反斜杠,因为某些字符组合具有特殊含义。 例如,“ n”是换行符,“ t”是制表符,等等。否则可能会导致意外结果。 例如,以下代码将无法正常工作:

<?php
// "\n" in "\newFunction" seen as newline
$function = "\MyProject\Blog\newFunction";
$function(); // Fatal error: "Call to undefined function..."

The correctly escaped string is "\\MyProject\\Blog\\newFunction".

正确转义的字符串是"\\MyProject\\Blog\\newFunction"

摘要 (Summary)

Namespaces are a powerful language feature that can be used to effectively group components in an application without fear of collision. This article covered the reasons why you should use namespaces and the syntax for defining and using them. You also saw how the use keyword allows you to alias namespaces, and how to use namespaced classes and functions dynamically. Now you should have a complete understanding of namespaces and be ready to start using them in your own applications.

命名空间是一种强大的语言功能,可用于在应用程序中有效地对组件进行分组,而不必担心发生冲突。 本文介绍了为什么应使用名称空间的原因以及用于定义和使用名称空间的语法。 您还看到了use关键字如何允许您为命名空间加上别名,以及如何动态使用命名空间的类和函数。 现在,您应该完全了解名称空间,并准备好在自己的应用程序中开始使用它们。

翻译自: https://www.sitepoint.com/php-namespaces/

php命名空间

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值