所以我开始一个新项目并希望使用一些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';
?>
感谢您的帮助
答案 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
班。
现在,如果您使用许多不同的类并将它们分成几个文件(您应该这样做)会发生什么。您在文件顶部获得了许多不同的require
和use
语句。这就是自动加载的用武之地。
PHP中有一段spl_register_autoloader
函数已经有一段时间了。 PHP使用此函数来查找在实例化未知的类时要使用的文件,因为您没有require
该文件。在创建类时使用此函数,或者,当您use
类时,这是的关键部分。
这就是你的代码中发生的事情。您没有注册自动加载器,可以将实际类声明所需的文件中的use
语句翻译。
要解决此问题,建议您阅读PHP-FIG和PSR-4。这些人创造了标准(你可以遵循,但没有义务)。创建易于使用的库,例如Symfony组件。完成后,请阅读Composer。完成此操作后,您可以从代码中删除require
语句,并使用Composer自动加载您需要的所有类。