我正在为 Yii2 开发一个文件管理器模块,其目标是为用户提供使用不同来源进行目录浏览的选项,例如
为了实现这一点,我编写了一个接口,该接口将由用户想要使用的不同适配器实现。例如,下面是来自具有常用功能的界面的几行代码:
<?php
namespace buttflattery\filemanager\adapters;
/**
* File Manager Interface class
*/
interface DirectoryInterface
{
public function listFolder(string $directory, array $sortParams);
public function removeFile(string $file);
public function createFolder(string $folder, string $parentDirectory);
public function uploadFile(string $file, string $destinationDirectory);
public function downloadFile(string $zipFile);
public function renameFile(string $oldFile, string $newFile);
public function moveFiles(array $filesList, string $destination);
public function copyFiles(array $files, string $destination);
}
我从LocalDirectoryAdapter
; 它通过配置文件作为模块的组件附加,
'modules' => [
'filemanager' => [
'class' => 'buttflattery\filemanager\Module',
'components' => [
'adapter' => [
'class' => 'buttflattery\filemanager\adapters\local\LocalDirectoryAdapter',
'rootDir' => 'tinyii-uploads'
]
],
],
],
一切正常,直到我在开始实施 Dropbox 适配器后遇到了一个情况。
有几种方法将使用完全相同的代码。例如,listFolder()
在两个相同的LocalDirectoryAdapter
和DropoxAdapter
。
原因是因为有一个FileIndexer
组件会查询文件树并将其写入一个 JSON 文件,然后所有的列表和浏览都是由FileIndexer
组件通过该 JSON 文件完成的。
那时,我想我需要将接口更改为一个abstract
类,添加那些通用方法,并将这些方法保留为抽象方法,这些方法需要专门针对我正在使用的 Directory 源实现。这就是我不解的地方:
在LocalDirectoryAdapter
类被声明为
class LocalDirectoryAdapter extends Component implements DirectoryInterface{
}
一旦我将接口更改为抽象类,我就必须使用extend
,在这种情况下,我无法扩展yii\base\Component
该类。
我怎样才能解决这个问题?
您可以使用 aTrait
而不是抽象类来处理此公共代码。使用 Trait 的一个原因是,它允许您保持类层次结构不变,而且还可以重用否则会重复的代码。
以下是将 trait 注入到你实现的类中的方法:
<?php
class LocalDirectoryAdapter extends yii\base\Component implements DirectoryInterface{
use DirectoryTrait;
public function removeFile(string $file) { }
public function createFolder(string $folder, string $parentDirectory) { }
public function uploadFile(string $file, string $destinationDirectory) { }
public function downloadFile(string $zipFile) { }
public function renameFile(string $oldFile, string $newFile) { }
public function moveFiles(array $filesList, string $destination) { }
public function copyFiles(array $files, string $destination) { }
}
和特质本身:
<?php
trait DirectoryTrait {
public function listFolder(string $directory, array $sortParams) {
//implement the listFolder things
}
}
您甚至可以通过简单地排除该use AdapterTrait
行来选择性地选择让您的适配器使用或不使用 Trait 。这是一个小的工作示例 ( trait.php
)。看看如何DirectoryAdapterNoTrait
不使用特性。
<?php
interface AdapterInterface {
public function listFiles(string $dir);
}
trait AdapterTrait {
public function listFiles(string $dir)
{
echo "Doing TRAIT listFiles" . PHP_EOL;
}
}
class DirectoryAdapterTrait extends yii\base\Component implements AdapterInterface {
use AdapterTrait;
}
class DirectoryAdapterNoTrait extends yii\base\Component implements AdapterInterface {
public function listFiles(string $dir)
{
echo "NOT TRAIT listFiles" . PHP_EOL;
}
}
$adapterTrait = new DirectoryAdapterTrait();
$adapterTrait->listFiles("some_dir");
$adapterNoTrait = new DirectoryAdapterNoTrait();
$adapterNoTrait->listFiles("some_dir");
echo PHP_EOL;
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句