[PHP][PrestaShop]加载机制

PHP中当需要使用另一个文件中的类或对象时,需要先require或include这个文件。require和include的区别是require失败后出告警,include失败后出warning。

PrestaShop在加载这部分有一些自己独到的处理,一起看下。

1. 访问顺序:

index.php -> config/config.inc.php -> config/autoload.php -> classes/PrestaShopAutoload.php

index.php是PrestaShop的总入口

config.inc.php做一些配置,其中还调用了defines.inc.php(包含了大部分路径的定义),settings.inc.php(包含了数据库定义)等等

autoload.php感觉这一步有点多余,完全可以在config.inc.php里直接require PrestaShopAutoload。也许是保留做未来功能扩展或者是为了支持多商店,who knows

PrestaShopAutoload.php生成所有用到的.php文件的列表,并存储在cache/class_index.php文件中;定义了供spl_autoload_register使用的回调函数,后面重点分析下这个class


2. PrestaShop使用了spl_autoload_register,我们先来简单看下这个函数的意义

spl_autoload_register — 注册给定的函数作为 __autoload 的实现

这是php.net上的原话,我理解就是通过它php提供了由用户自己来处理autoload的可能,并且他相对与用户实现__autoload()来说更进一步,相当于可以定义多个__autoload()函数。

在PrestaShop中是这样使用这个函数的:

require_once(_PS_CLASS_DIR_.'PrestaShopAutoload.php');

spl_autoload_register(array(PrestaShopAutoload::getInstance(), 'load'));

(autoload.php)

这个可以理解为把PrestaShopAutoload类中的load方法作为autoload的处理函数


3. PrestaShopAutoload::getInstance(),看看初始化做了些啥

首先,getInstance()方法中是经典的单例模式的实际运用,确保一个类只有一个对象。顺便一说,Presta大量使用了单例模式。

在__construct中做了两件事情,判断有没有cache/class_index.php这个文件,有就include这个文件,没有则初始化这个文件,这个文件是所有类的一个索引,供load方法使用,结构如下:

  'Dispatcher' => 
  array (
    'path' => '',
    'type' => 'class',
    'override' => false,
  ),
  'DispatcherCore' => 
  array (
    'path' => 'classes/Dispatcher.php',
    'type' => 'class',
    'override' => false,
  ),

初始化读取了classes,controllers,override/classes,override/controllers下的所有的php文件。


4. load方法探究

Presta的这个机制还是很有意思的,不但很好的解决了自动加载的问题,还顺便带来了核心类都可以被overload的好处。上面我们看到Dispatcher这个方法在索引中的存储结构,那我们看下他是如何被引入和初始化的。

这是index.php的第二行:

Dispatcher::getInstance()->dispatch();

初看有点唬人,没引入呢,就直接用了。但我们看过上面的描述就应该知道,在这个地方如果Dispatcher并没有被引入过,那么就会由load()这个方法来处理。

load()收到的$classname是Dispatcher,那么他会首先判断这个类名是不是以Core结尾的,如果是,那么加载Core所指向的文件。如果不是,先判断索引里面该类下有没有path,如果有,则把这个自定义的类和core类一起加载。从这里看,这个自定义类应该需要继承core类。如果没有则只加载core类,并自动添加一个继承core类的名为Dispatcher的类,方便调用。


总结:至此,大概了解了Presta的加载机制,对我们在Presta中做二次开发有如下好处:

1. 看中哪个类了,只要在classes/controllers/override这些目录下,直接类名::getInstance()使用即可

2. 看着那个类的功能不满意,自己写一个继承它的类放在override中即可直接使用

你可能感兴趣的:([PHP][PrestaShop]加载机制)