2

所以我正在开始一个新项目并想使用一些 Symfony 组件。我以前没有在 PHP 中使用过名称空间,我对我在 java 中的工作很熟悉这个概念。

我有这段简单的代码,当我运行它时出现错误: PHP 致命错误:在 /home/me/scrapes/Symfony/Component/CssSelector/CssSelector 中找不到类'Symfony\Component\CssSelector\XPath\Translator' /CssSelector.php 第 52 行

我认为这是我对名称空间的了解不足。/home/me/scrapes/Symfony/Component/CssSelector/CssSelector/XPath/Translator.php 确实存在。

<?php
set_include_path('/home/me/html/inc');
require 'functions.php';
require 'Symfony/Component/DomCrawler/Crawler/Crawler.php';
require 'Symfony/Component/CssSelector/CssSelector/CssSelector.php';

use Symfony\Component\DomCrawler\Crawler;
use Symfony\Component\CssSelector\CssSelector;

$crawler = new Crawler();
$crawler->addContent('<html><body><p>Hello World!</p></body></html>');
print $crawler->filter('body > p')->text();

curl_close($ch);    

require 'cleanup.php';
?>

谢谢你的帮助

4

1 回答 1

5

我认为这是因为,如果您查看所需的文件(例如Symfony/Component/DomCrawler/Crawler/Crawler.php),您会看到这些文件使用它们自己的use语句(加载其他类)。

命名空间

让我们从命名空间开始。命名空间用于在不同的包中轻松创建具有相同名称的类。假设我有一个名为的包Foo和一个名为Bar. 这两个包都包含一个Client用于执行某些客户端工作的类(例如,一个调用 Google Maps API,另一个调用 Facebook Graph API)。我们还假设两个包都没有使用命名空间。

如果我执行以下代码:

<?php
require 'Foo/Client.php';
require 'Bar/Client.php';

这是行不通的,因为两个包都声明了一个Client类。Client糟糕,如果您这样做,PHP 将如何知道要使用哪个类?

<?php
$client = new Client();

它不知道Client使用哪个,所以它放弃并抛出错误。

如果您使用命名空间(namespace在文件顶部使用 PHP 中的关键字声明,就在下面<?php),您可以防止这种情况发生。包Foo可以在命名空间中创建Client类,在Foo命名空间中创建BarBar。现在我们可以实际使用这两个文件并创建一个客户端:

<?php
require 'Foo/Client.php'
require 'Bar/Client.php'

$fooClient = new Foo\Client();
$barClient = new Bar\Client();

这将正常工作。

Foo_Client我想您可能已经在较旧的 PHP 库中遇到过这种表示法。这是在 PHP 原生支持命名空间之前创建命名空间的旧方法。

Foo\Bar\Baz\Client()“但是”,我听到你说,“每次我想实例化一个类时都写起来很麻烦”。

是的,这就是use关键字的来源。使用use关键字时,我可以告诉 PHP 我想使用特定的客户端并只使用类名,如下所示:

<?php
require 'Foo/Bar/Baz/Client.php'
use Foo\Bar\Baz\Client;

$client = new Client();

如果您使用该use Foo\Bar\Baz\Client语句,这将起作用,因为您告诉 PHP “好的,我想使用命名空间中的Client类,Foo\Bar\Baz以便在我使用Client该类时使用。

自动加载

现在,如果您使用许多不同的类并将它们分成几个文件(您应该这样做),会发生什么。你会在一个文件的顶部得到很多不同的require和语句。use这就是自动加载的用武之地。

PHP中有一个spl_register_autoloader函数已经有很长一段时间了。当您实例化一个由于您没有require该文件而未知的类时,PHP 使用此函数来找出要使用哪些文件。该函数在创建类时使用,或者,这是创建类时的关键部分use

这就是您的代码中发生的事情。您没有注册可以将use文件中的语句转换为实际类声明的自动加载器。

太好了,我该如何解决?

要修复它,我建议您阅读PHP-FIGPSR-4。这些人创建了标准(您可以遵循但没有义务)。创建易于使用的库,例如 Symfony 组件。完成后,阅读Composer。完成此操作后,您可以require从代码中删除语句并使用 Composer 自动加载您需要的所有类。

于 2013-11-05T21:34:02.470 回答