尝试使用Symfony组件并具有名称空间问题

时间:2013-11-05 18:55:39

标签: symfony

所以我开始一个新项目并希望使用一些Symfony组件。我之前没有使用PHP的名称空间,我熟悉java中的工作概念。

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

我在想我对名称空间的了解不足。 /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';
?>

感谢您的帮助

1 个答案:

答案 0 :(得分: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类。哎呀,如果你这样做,PHP如何知道要使用哪个Client类呢?

<?php
$client = new Client();

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

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

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

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

这样可以正常工作。

我认为您可能在较旧的PHP库中遇到了Foo_Client符号。这是在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班。

自动加载

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

PHP中有一段spl_register_autoloader函数已经有一段时间了。 PHP使用此函数来查找在实例化未知的类时要使用的文件,因为您没有require该文件。在创建类时使用此函数,或者,当您use类时,这是的关键部分。

这就是你的代码中发生的事情。您没有注册自动加载器,可以将实际类声明所需的文件中的use语句翻译。

很好,我该如何解决?

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