命名空间

要知道,不能有两个同名的类,因为在创建新对象时,PHP 无法知道引用的是哪个类。为了解决这个问题,PHP 允许使用命名空间,它就像文件系统中的路径一样。这样,只要把同名的类定义在不同的命名空间中,就可以拥有尽可能多的同名类。值得注意的是,尽管命名空间和文件路径通常是相同的,但这是由开发人员而不是语言来执行的;实际上,你可以使用任何与文件系统无关的命名空间。

指定命名空间必须是在文件中做的第一件事。为此,请使用 namespace 关键字,然后再使用命名空间。命名空间的每一部分都用 \ 分隔,就像不同的目录一样。如果不指定命名空间,类将属于基命名空间或根命名空间。在两个文件(Book.phpCustomer.php)的开头添加以下内容:

<?php
namespace Bookstore\Domain;

前面的代码将我们的类的命名空间设置为 Bookstore\Domain。这样,我们的类的全称就是 Bookstore\Domain\BookBookstore\ Domain\Customer 。如果你试图从浏览器中访问 init.php 文件,你会看到一个错误,说没有找到类 Book 或类 Customer。但我们已经包含了这些文件,不是吗?出现这种情况是因为 PHP 认为你正试图从根访问 \Book\Customer。别担心,有几种方法可以解决这个问题。

一种方法是在引用时指定类的全名,即使用 $customer = new Bookstore\Domain\Book(); 而不是 $book = new Book();。但这听起来不太现实,不是吗?

另一种方法是说 init.php 文件属于 BookStore\Domain 命名空间。这意味着在 init.php 文件中引用的所有类都将带有 BookStore\Domain 前缀,这样你就可以使用 BookCustomer 了。这种解决方案的缺点是,你不能轻易引用其他命名空间的类,因为任何对类的引用都会以该命名空间为前缀。

最好的解决方案是使用关键字 use。这个关键字允许你在文件开头指定一个完整的类名,然后在文件的其余部分使用简单的类名。让我们来看一个例子:

<?php
use Bookstore\Domain\Book;
use Bookstore\Domain\Customer;

require_once __DIR__ . '/Book.php';
require_once __DIR__ . '/Customer.php';
//...

在前面的文件中,我们每次引用 BookCustomer 时,PHP 都会知道我们实际上要使用的是完整的类名,即带有 Bookstore\Domain\ 前缀的类名。这种解决方案使您在引用这些类时代码简洁,同时还能在需要时引用其他命名空间的类。

但如果要在同一个文件中包含两个同名的不同类呢?如果您设置了两个 use 语句,PHP 将不知道该选择哪个,因此我们仍然会遇到和以前一样的问题!要解决这个问题,要么每次引用任何一个类时都使用带有命名空间的完整类名,要么使用别名。

假设我们有两个图书类,第一个在命名空间 Bookstore\Domain 中,第二个在 Library\Domain 中。要解决这个冲突,你可以这样做:

use Bookstore\Domain\Book;
use Library\Domain\Book as LibraryBook;

关键字 as 设置了该类的别名。在该文件中,无论何时引用 LibraryBook 类,实际上都是引用 Library\Domain\Book 类。而在引用 Book 时,PHP 将使用 Bookstore 中的那个类。问题解决了!