I'm working on a File Manager module for Yii2 where the goal is to provide the user with an option to use different sources for directory browsing, like
To accomplish this, I wrote an interface which will be implemented by different adapters that the user wants to use. For example, here are a few lines of code from the interface with common functions:
<?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);
}
I started with the LocalDirectoryAdapter
; it's attached as a component with the module via a config file,
'modules' => [
'filemanager' => [
'class' => 'buttflattery\filemanager\Module',
'components' => [
'adapter' => [
'class' => 'buttflattery\filemanager\adapters\local\LocalDirectoryAdapter',
'rootDir' => 'tinyii-uploads'
]
],
],
],
It all works fine, until I came across a situation after I started implementing the Dropbox adapter.
There are a couple of methods that will be using exactly the same code. For instance, the listFolder()
is the same in both LocalDirectoryAdapter
and DropoxAdapter
.
The reason is because there is a FileIndexer
component which queries the file tree and writes it down to a JSON file, and then all the listing and browsing is done via that JSON file by the FileIndexer
component.
At that point, I figured I needed to change the interface to an abstract
class, add those methods that are common, and leave those methods as abstract which will need to be implemented specifically to the Directory source I am using. That is where I got puzzled:
The LocalDirectoryAdapter
class is declared as
class LocalDirectoryAdapter extends Component implements DirectoryInterface{
}
Once I change the interface to an abstract class, I am bound to use extend
, and in that case, I cant extend the yii\base\Component
class.
How can I get around this problem?
You can make your abstract adapter extend the yii\base\Component
then by extending your abstract adapter the child class will also inherit from Component.
For example like this
abstract class BaseDirectoryAdapter extends Component
{
}
class LocalDirectoryAdapter extends BaseDirectoryAdapter
{
}
But I think it's not a good practice to force usage of your abstract base class. You don't know what adapters might be implemented in future.
What you can do is to use both. The interface that would define minimal requirements for adapter and abstract base class that would provide standard impelmentations for common methods.
interface DirectoryInterface
{
}
abstract class BaseDirectoryAdapter extends Component implements DirectoryInterface
{
}
class LocalDirectoryAdapter extends BaseDirectoryAdapter
{
}
This allows you to benefit from implementations in BaseDirectoryAdapter but doesn't force you to use it.
Yii uses this approach, you can for example see it with yii\db\ActiveRecord
, yii\db\BaseActiveRecord
and yii\db\ActiveRecordInterface
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.