我注意到在某些情况下,当你编写一个扩展现有类的类时,你需要在config.yml文件中声明类扩展。
例如,我最近编写了此代码以删除CMS后端中的"帮助"按钮。
mysite/code/Tweak.php
class Tweak extends LeftAndMainExtension
{
public function init()
{
parent::init();
/* Remove help link */
CMSMenu::remove_menu_item('Help');
}
}
mysite/code/Config.yml
LeftAndMain:
extensions:
- Tweak
问题 1:为什么某些类扩展需要在 config.yml 中声明?为什么这个额外的步骤对于其他类扩展(例如扩展 DataObject 或 Page_Controller)不是必需的?
问题2:关于上述代码的具体问题,为什么我在配置文件中将Tweaks声明为LeftAndMain的扩展,而在php文件中我实际上是在扩展LeftAndMainExtension?
问题 1:为什么某些类扩展需要在 config.yml 中声明?为什么这个额外的步骤对于其他类扩展(例如扩展 DataObject 或 Page_Controller)不是必需的?
PHP和SilverStripe术语之间有一个重要的区别。
在 SilverStripe 中,扩展是在 SilverStripe 中实现的框架功能,它允许您修改对象的行为,而无需访问公共内容以外的任何内容。在这方面,它与Ruby相似。
在 PHP 中,使用 extends
关键字定义现有类的子类。
在您的示例中,您使用的是 LeftAndMainExtension
,这是一个 SilverStripe "扩展" - 这允许您修改 SilverStripe 管理区域中 CMS 菜单的行为,同时它不会从字面上扩展(用 PHP 术语)LeftAndMain
类。
问题2:关于上述代码的具体问题,为什么我在配置文件中将Tweaks声明为LeftAndMain的扩展,而在php文件中我实际上是在扩展LeftAndMainExtension?
如上所述,这就是SilverStripe的扩展系统的工作方式。它基本上遵循以下过程:
- 您创建一个在继承中的某个点
extends
(PHP 关键字)Extension
的类(您使用LeftAndMainExtension
,它扩展Extension
)。对于数据对象,请改用DataExtension
。 - 你告诉 SilverStripe 将扩展应用于对象,在这种情况下它是
LeftAndMain
命名是经过深思熟虑的,因此您可以轻松/直观地将对象及其相关扩展组合在一起:
约定是扩展类名称以扩展结尾。这不是要求,但更清楚
- SilverStripe开发人员文档
注意我一直故意将扩展大写,以表示它是一个 SilverStripe 扩展类,而不是类的 PHP 扩展 (class Foo extends Bar
)。
有关框架如何执行此过程的示例,它基本上是这样的:
- 对象已初始化
- 框架分析扩展的 YAML 配置(或通过
Object::add_extension()
应用的扩展) - 框架循环扩展,将
$this->owner
设置为当前对象,以便扩展可以从中访问公共方法和属性 - 框架返回最终对象
更多信息在这里。
您实际上在这里谈论的是两种基本的 OO 模式。
- 简单子类化
这几乎是许多语言(包括PHP和Java)的标准方式,用于自定义类从另一个类继承一些逻辑并能够声明自己的ala:
class MyObject extends DataObject {
}
这里没有特定于SilverStripe的内容,在这种情况下它是本机(PHP)。
- 装饰者
当您子类Extension
或其任何一个子类时,例如 DataExtension
,SiteTreeExtension
或LeftAndMainExtension
根据您的示例,您正在"装饰"现有类以及当前库或框架的"装饰器"模式的实现。
在 SilverStripe 中,这两种方法之间的很大区别在于,对于子类化,新类将在数据库中创建一个新表(您可以在其中声明静态$db
)。使用装饰器(在 YML 中声明的Extension
子类或通过类本身中的$extension
静态)不会创建新表,您只需将新字段和逻辑"附加"到现有对象及其表上。
后一种方法的实用性的一个常见示例是Member
类。 对其进行子类化,对修改/自定义 SilverStripe 的成员资格和权限系统没有太大帮助,装饰它会。
请参阅有关SilverStripe此功能的专用页面:https://docs.silverstripe.org/en/3.3/developer_guides/extending/extensions/