类自动加载
Joomla 实例包含数千个 PHP 源文件,以及数量相当的 PHP 类。很明显,对每个源文件执行 require
操作,以使 PHP 解释器了解所有类是不切实际的。那么 Joomla 如何避免在尝试访问 PHP 解释器无法识别的类时出现 PHP 类未找到的致命错误?答案是它使用 类自动加载。
当 Joomla 初始化时,它会使用以下方法(在 libraries/loader.php setup()
中)设置多个自动加载器,例如
spl_autoload_register(['JLoader', 'loadByPsr']);
如果 PHP 解释器遇到类似以下的代码行
if (class_exists($classname)) ...
并且它无法识别类名,那么它会将类名传递给注册的自动加载器,并调用例如
loadByPsr($classname)
传递类名。从 Joomla 4 开始,这应该是一个完全限定的类名。
自动加载器的职责是尝试找到包含该类的源文件,并在其上执行 include_once
操作,以便 PHP 随后能够识别该类。对于组件、模块和插件(包括 Joomla 和第三方扩展),Joomla 使用 PSR4 方法将类名映射到源文件。
在初始化期间,Joomla 会查看站点和管理员的组件、模块和插件目录,以查找所有清单 XML 文件。然后,它会加载 XML 并查找 <namespace>
元素,并根据这些元素构建一组将命名空间前缀映射到目录的映射。由于这涉及相当多的工作,因此结果会被缓存在 administrator/cache/autoload_psr4.php 中 - 可以看看它!。
然后,loadByPsr
函数会使用此映射和 使用 PSR4 查找类 中描述的用于查找源文件的 PSR4 规则来确定包含该类的文件名称。它会检查该文件是否存在,如果存在,则在其上执行 include_once
操作,然后返回。
如果自动加载器 loadByPsr
函数成功找到了该类,那么 PHP 会将 class_exists($classname)
表达式视为 true
,然后继续执行代码。如果它没有找到该类,那么 PHP 会抛出类未找到异常。
Joomla 具有多个自动加载器函数 - 并非所有类都使用 PSR4 加载。例如,库类都具有将 FQN 映射到该类的单个源文件的映射 - 可以看看 libraries/vendor/composer/autoload_classmap.php。
在 libraries/classmap.php 中,还存在从以 J 开头的旧全局库名(例如 JModelAdmin)到 FQN 等效项的映射,但在 Joomla 6 中此映射会消失。