Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How can I make a custom adapter method discoverable by Filesystem? #1804

Open
reypm opened this issue Jul 30, 2024 · 1 comment
Open

How can I make a custom adapter method discoverable by Filesystem? #1804

reypm opened this issue Jul 30, 2024 · 1 comment

Comments

@reypm
Copy link

reypm commented Jul 30, 2024

Question

I am using Flysystem and so far so good. I want to create an adapter with a "custom" method that will perform a few actions, and yes, I can do exactly the same with the available functions from Flysystem but I would like to encapsulate all of that code into a function. This is how my custom Adapter class looks like:

class LocalAdapter extends LocalFilesystemAdapter {
    public function MyCustomFunction() {
        // do something here
    }
}

then I initialize Flysystem using this LocalAdapter:

$adapter = new LocalAdapter(__DIR__);
$filesystem = new Filesystem($adapter);

but from there I cannot access $filesystem->MyCustomFunction() because the method is not callable:

Fatal error: Uncaught Error: Call to undefined method League\Flysystem\Filesystem::MyCustomFunction()

What I am missing here?

Q A
Flysystem Version 3.28.0
@SamMousa
Copy link

SamMousa commented Aug 8, 2024

The filesystem abstracts the implementation using the strategy pattern.

If the function you're implementing could work on any adapter it's probably cleaner to implement it on the filesystem instead of the adapter.

Personally I'd prefer to use composition instead of extending library classes.

This can be done using functions or classes:

function mySpecialFileSystemOperation(FilesystemWriter $filesystem) {
   // Do your stuff here.
}
class SpecialFileSystemService {

    public function __construct(private FilesystemWriter $filesystem) {
    }

    public function doSpecialThingWithPath(string $path) {
        // Your special stuff here
    }
}

These patterns will keep your logic more separated from underlying library code.

If you prefer not to have many dependencies in your consuming code (ie you only want to pass 1 filesystem object and not an additional service object for your functionality) I'd use the decorator pattern instead of extending.

class MyFilesystemWithExtendedFunctionality implements FileSystemOperator {

    public function __construct(private readonly FileSystemOperator $filesystem) {

    }

    // For each function in the FileSystemOperator interface create a forwarding function.    public function 
    public function fileExists(string $location): bool {
        return $this->filesystem->fileExists($location);
    }


    public function mySpecialFunction() {
        // Your magic here
    }
}

While this is more work at first it is often cleaner to compose than to extend third party library code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants