如何覆盖作为 SilverStripe 框架一部分的现有 class、FlysystemAssetStore 的现有方法

How to override the existing method of an existing class, FlysystemAssetStore that is part of the framework in SilverStripe

我正在开发一个 SilverStripe 项目,在我的项目中,我需要更改作为 SilverStripe 框架一部分的 class 的行为。我需要修改的class是SilverStripe\Assets\Flysystem\FlysystemAssetStore。例如,我现在正在尝试修改 class 的 exists 方法。我尝试使用两个选项 Injector 和 Extension。两者均无效。

我尝试的第一个选项是使用 Injector。这是我做的。

首先,我创建了一个名为 CustomFlysystemAssetStore 的 class。

然后我在mysite.yml

中添加了下面的代码
SilverStripe\Assets\Flysystem\FlysystemAssetStore:
    class: CustomFlysystemAssetStore

我声明调用的 public 函数存在于 CustomFlysystemAssetStore class 中以覆盖现有行为。但它没有用。新class中的新方法根本没有执行。

我尝试的第二个选项是使用扩展。这是我做的。

首先,我创建了一个名为 CustomFlysystemAssetStore 的 class,它扩展了 DataExtension class。

然后,我将以下代码片段添加到 mysite.yml。

SilverStripe\Assets\Flysystem\FlysystemAssetStore:
  extensions:
    - CustomFlysystemAssetStore

然后我在新的class调用exists中声明了一个public方法,看看是否调用了新方法

不幸的是,第二种方法也没有用。我如何覆盖作为框架一部分的 SilverStripe\Assets\Flysystem\FlysystemAssetStore class 的方法?

这是我的 assets.yml 文件

---
Name: silverstripes3-flysystem
Only:
  envvarset: AWS_BUCKET_NAME
After:
  - '#assetsflysystem'
---
SilverStripe\Core\Injector\Injector:
  Aws\S3\S3Client:
    constructor:
      configuration:
        region: '`AWS_REGION`'
        version: latest
  League\Flysystem\Adapter\Local:
    class: League\Flysystem\Adapter\Local
    constructor:
      root: '`TEMP_PATH`'

  SilverStripe\S3\Adapter\PublicAdapter:
    constructor:
      s3Client: '%$Aws\S3\S3Client'
      bucket: '`AWS_BUCKET_NAME`'
      prefix: '`AWS_PUBLIC_BUCKET_PREFIX`'
  League\Flysystem\Cached\Storage\Memory.public:
    class: League\Flysystem\Cached\Storage\Memory
  League\Flysystem\Cached\Storage\Adapter.public:
    class: League\Flysystem\Cached\Storage\Adapter
    constructor:
      adapter: '%$League\Flysystem\Adapter\Local'
      file: 's3metadata/public'
      expire: 259200
  SilverStripe\Assets\Flysystem\PublicAdapter:
    class: SilverStripe\S3\Adapter\PublicCachedAdapter
    constructor:
      adapter: '%$SilverStripe\S3\Adapter\PublicAdapter'
      cache: '%$League\Flysystem\Cached\Storage\Adapter.public'

  SilverStripe\S3\Adapter\ProtectedAdapter:
    constructor:
      s3Client: '%$Aws\S3\S3Client'
      bucket: '`AWS_BUCKET_NAME`'
      prefix: '`AWS_PROTECTED_BUCKET_PREFIX`'
  League\Flysystem\Cached\Storage\Adapter.protected:
    class: League\Flysystem\Cached\Storage\Adapter
    constructor:
      adapter: '%$League\Flysystem\Adapter\Local'
      file: 's3metadata/protected'
      expire: 259200
  SilverStripe\Assets\Flysystem\ProtectedAdapter:
    class: SilverStripe\S3\Adapter\ProtectedCachedAdapter
    constructor:
      adapter: '%$SilverStripe\S3\Adapter\ProtectedAdapter'
      cache: '%$League\Flysystem\Cached\Storage\Adapter.protected'
#---
Name: silverstripes3-assetscore
Only:
  envvarset: AWS_BUCKET_NAME
After:
  - '#assetscore'
---
SilverStripe\Core\Injector\Injector:
  SilverStripe\Assets\Storage\AssetStore:
    class: CustomFlysystemAssetStore

在 Silverstripe 4.5 中,我们可以扩展 FlysystemAssetStore 并定义我们自己的 exists 方法。

首先我们在项目中创建一个CustomFlysystemAssetStore.php文件:

app/src/CustomFlysystemAssetStore.php

use SilverStripe\Assets\Flysystem\FlysystemAssetStore;

class CustomFlysystemAssetStore extends FlysystemAssetStore {

    public function exists($filename, $hash, $variant = null)
    {
        // Custom logic goes here
        // ...

        // Fallback to the parent exists function
        return parent::exists($filename, $hash, $variant);
    }
}

然后我们将其设置为我们希望系统通过 yml 配置文件使用的 AssetStore。我们创建一个 assets.yml 文件:

app/_config/assets.yml

---
Name: app-assetscore
After:
  - '#assetscore'
---

SilverStripe\Core\Injector\Injector:
  SilverStripe\Assets\Storage\AssetStore:
    class: CustomFlysystemAssetStore