PHP 'use' 关键字如何工作(在 Symfony 2 中)?
How does the PHP 'use' keyword work (in Symfony 2)?
在 Symfony 2 中,所有请求都通过 app_dev.php
(或 app.php
)路由。
前几行看起来像:
<?php
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Debug\Debug;
...
理论上,我知道这只是将指定的命名空间(或 class)导入当前范围。我不明白的是 PHP 如何将其映射到文件。例如,Debug
class 位于:
vendor/symfony/symfony/src/Symfony/Component/Debug/Debug.php
PHP 怎么知道要在 vendor/symfony/symfony/src/
中查找?
我可能误解了发生的事情,但如有任何澄清,我们将不胜感激。
知道 class 所在的文件不是语言的工作,而是自动加载器的工作。
use
关键字所做的就是此实例创建一个别名:
use Symfony\Component\HttpFoundation\Request;
这是在下面的脚本中说的,当我提到 Request
时,我 真的 是指 Symfony\Component\HttpFoundation\Request
。如果我以某种方式使用 Request
对象(通过创建实例或在其上调用静态方法),那么自动加载器将去尝试加载 class 定义的文件,如果它没有'尚未加载。
不过,自动加载器的内部工作原理因项目而异。自动加载器行为标准化 à la PSR-4,但语言中没有任何内容表明您必须遵守该标准。例如,你可以有一个方案,其中 all class 文件驻留在一个目录中,而你的自动加载器只从那里加载所有 classes,不管是什么他们所在的命名空间。
每个名字只能有一个 class 这一事实会影响该方案,但没有什么能阻止您这样做。
回答您的问题:"How does it know that "Symfony\Component\Debug\Debug" 是一个有效的命名空间吗?"
它没有,因为此时它实际上并没有出去并试图加载 class。如果在任何随机 PHP 脚本中,您将类似这样的内容放在顶部:
use \Non\Existant\ObjectClass;
但实际上永远不要在任何地方使用 ObjectClass
,你不会得到任何错误。但是,如果您尝试说 new ObjectClass
,您将收到 class not found 错误。
简单地说,您必须预先将所有文件加载到内存中 PHP。 PHP 对于文件所在的位置没有任何固有的标准,加载文件的规则必须由您的代码完成。
当 PHP 尝试加载文件时,如果 class 定义存在,它将检查其内存,如果不存在,它将尝试自动加载可能包含您的 class 的文件定义;见 PHP: Autoloading Classes and spl_autoload_register
PHP Framework Interop Group定义了一些常见的自动加载策略:
在这种情况下,自动加载由 Composer, all you need to do is include vendor/autoload.php
in any of your scripts and vendor code downloaded via composer can be autoloaded. You can manually add classes into the composer autoloader as well. See: Composer Autoloading
完成
在 Symfony 2 中,所有请求都通过 app_dev.php
(或 app.php
)路由。
前几行看起来像:
<?php
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Debug\Debug;
...
理论上,我知道这只是将指定的命名空间(或 class)导入当前范围。我不明白的是 PHP 如何将其映射到文件。例如,Debug
class 位于:
vendor/symfony/symfony/src/Symfony/Component/Debug/Debug.php
PHP 怎么知道要在 vendor/symfony/symfony/src/
中查找?
我可能误解了发生的事情,但如有任何澄清,我们将不胜感激。
知道 class 所在的文件不是语言的工作,而是自动加载器的工作。
use
关键字所做的就是此实例创建一个别名:
use Symfony\Component\HttpFoundation\Request;
这是在下面的脚本中说的,当我提到 Request
时,我 真的 是指 Symfony\Component\HttpFoundation\Request
。如果我以某种方式使用 Request
对象(通过创建实例或在其上调用静态方法),那么自动加载器将去尝试加载 class 定义的文件,如果它没有'尚未加载。
不过,自动加载器的内部工作原理因项目而异。自动加载器行为标准化 à la PSR-4,但语言中没有任何内容表明您必须遵守该标准。例如,你可以有一个方案,其中 all class 文件驻留在一个目录中,而你的自动加载器只从那里加载所有 classes,不管是什么他们所在的命名空间。
每个名字只能有一个 class 这一事实会影响该方案,但没有什么能阻止您这样做。
回答您的问题:"How does it know that "Symfony\Component\Debug\Debug" 是一个有效的命名空间吗?"
它没有,因为此时它实际上并没有出去并试图加载 class。如果在任何随机 PHP 脚本中,您将类似这样的内容放在顶部:
use \Non\Existant\ObjectClass;
但实际上永远不要在任何地方使用 ObjectClass
,你不会得到任何错误。但是,如果您尝试说 new ObjectClass
,您将收到 class not found 错误。
简单地说,您必须预先将所有文件加载到内存中 PHP。 PHP 对于文件所在的位置没有任何固有的标准,加载文件的规则必须由您的代码完成。
当 PHP 尝试加载文件时,如果 class 定义存在,它将检查其内存,如果不存在,它将尝试自动加载可能包含您的 class 的文件定义;见 PHP: Autoloading Classes and spl_autoload_register
PHP Framework Interop Group定义了一些常见的自动加载策略:
在这种情况下,自动加载由 Composer, all you need to do is include vendor/autoload.php
in any of your scripts and vendor code downloaded via composer can be autoloaded. You can manually add classes into the composer autoloader as well. See: Composer Autoloading