config.yml 中的 SilverStripe 类扩展


SilverStripe class extensions in config.yml

我注意到在某些情况下,当你编写一个扩展现有类的类时,你需要在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 模式。

  1. 简单子类化

这几乎是许多语言(包括PHP和Java)的标准方式,用于自定义类从另一个类继承一些逻辑并能够声明自己的ala:

class MyObject extends DataObject {
}

这里没有特定于SilverStripe的内容,在这种情况下它是本机(PHP)。

  1. 装饰者

当您子类Extension或其任何一个子类时,例如 DataExtensionSiteTreeExtensionLeftAndMainExtension根据您的示例,您正在"装饰"现有类以及当前库或框架的"装饰器"模式的实现。

在 SilverStripe 中,这两种方法之间的很大区别在于,对于子类化,新类将在数据库中创建一个新表(您可以在其中声明静态$db)。使用装饰器(在 YML 中声明的Extension子类或通过类本身中的$extension静态)不会创建新表,您只需将新字段和逻辑"附加"到现有对象及其表上。

后一种方法的实用性的一个常见示例是Member类。 对其进行子类化,对修改/自定义 SilverStripe 的成员资格和权限系统没有太大帮助,装饰它会

请参阅有关SilverStripe此功能的专用页面:https://docs.silverstripe.org/en/3.3/developer_guides/extending/extensions/