命名空间
要知道,不能有两个同名的类,因为在创建新对象时,PHP 无法知道引用的是哪个类。为了解决这个问题,PHP 允许使用命名空间,它就像文件系统中的路径一样。这样,只要把同名的类定义在不同的命名空间中,就可以拥有尽可能多的同名类。值得注意的是,尽管命名空间和文件路径通常是相同的,但这是由开发人员而不是语言来执行的;实际上,你可以使用任何与文件系统无关的命名空间。
指定命名空间必须是在文件中做的第一件事。为此,请使用 namespace
关键字,然后再使用命名空间。命名空间的每一部分都用 \
分隔,就像不同的目录一样。如果不指定命名空间,类将属于基命名空间或根命名空间。在两个文件(Book.php
和 Customer.php
)的开头添加以下内容:
<?php
namespace Bookstore\Domain;
前面的代码将我们的类的命名空间设置为 Bookstore\Domain
。这样,我们的类的全称就是 Bookstore\Domain\Book
和 Bookstore\ 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
前缀,这样你就可以使用 Book
和 Customer
了。这种解决方案的缺点是,你不能轻易引用其他命名空间的类,因为任何对类的引用都会以该命名空间为前缀。
最好的解决方案是使用关键字 use
。这个关键字允许你在文件开头指定一个完整的类名,然后在文件的其余部分使用简单的类名。让我们来看一个例子:
<?php
use Bookstore\Domain\Book;
use Bookstore\Domain\Customer;
require_once __DIR__ . '/Book.php';
require_once __DIR__ . '/Customer.php';
//...
在前面的文件中,我们每次引用 Book
或 Customer
时,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
中的那个类。问题解决了!