How to create custom file system in Laravel

In order to create a custom filesystem in Laravel

You need to

  1. Create a filesystem adapter
  2. Introduce the adapter to your project
  3. Update your config

For this example we will create a new custom filestore adapter. This adapter was to be created in my project to communicate via RestAPI with my custom filestorage server on my Virtual Private Server.

Let’s Go!

Short info: peskom_filestore, PeskomFilestoreAdapter are arbitary names, you can use any name you want.

1 Creating the filesystem adapter.

The adapter must extend the filesystemadapter interface which contains all methods that you have to implement. In the code below I throw an exception. In your case you need to update each method according to your needs

create file PeskomFilestoreAdapter.php in app/Media folder of your project.

You can create it anywhere but don’t forget to update the namespace.

<?php

namespace App\Media;

use League\Flysystem\FilesystemAdapter;
use League\Flysystem\Config;
use League\Flysystem\FileAttributes;
use League\Flysystem\UnableToWriteFile;
use League\Flysystem\FilesystemException;
use League\Flysystem\UnableToRetrieveMetadata;

class PeskomFilestoreAdapter implements FilesystemAdapter
{

    /**
     * @throws FilesystemException
     * @throws UnableToCheckExistence
     */
    public function fileExists(string $path): bool
    {
        return false;
    }

    /**
     * @throws FilesystemException
     * @throws UnableToCheckExistence
     */
    public function directoryExists(string $path): bool
    {
        return false;
    }

    /**
     * @throws UnableToWriteFile
     * @throws FilesystemException
     */
    public function write(string $path, string $contents, Config $config): void
    {
        throw new UnableToWriteFile();
    }

    /**
     * @param resource $contents
     *
     * @throws UnableToWriteFile
     * @throws FilesystemException
     */
    public function writeStream(string $path, $contents, Config $config): void
    {
        throw new FilesystemException();
    }

    /**
     * @throws UnableToReadFile
     * @throws FilesystemException
     */
    public function read(string $path): string
    {
        throw new FilesystemException();
    }

    /**
     * @return resource
     *
     * @throws UnableToReadFile
     * @throws FilesystemException
     */
    public function readStream(string $path)
    {
        throw new FilesystemException();
    }

    /**
     * @throws UnableToDeleteFile
     * @throws FilesystemException
     */
    public function delete(string $path): void
    {
        throw new FilesystemException();
    }

    /**
     * @throws UnableToDeleteDirectory
     * @throws FilesystemException
     */
    public function deleteDirectory(string $path): void
    {
        throw new FilesystemException();
    }

    /**
     * @throws UnableToCreateDirectory
     * @throws FilesystemException
     */
    public function createDirectory(string $path, Config $config): void {}

    /**
     * @throws InvalidVisibilityProvided
     * @throws FilesystemException
     */
    public function setVisibility(string $path, string $visibility): void
    {
        throw new FilesystemException();
    }

    /**
     * @throws UnableToRetrieveMetadata
     * @throws FilesystemException
     */
    public function visibility(string $path): FileAttributes
    {
        throw new FilesystemException();
    }

    /**
     * @throws UnableToRetrieveMetadata
     * @throws FilesystemException
     */
    public function mimeType(string $path): FileAttributes
    {
        throw new FilesystemException();
    }

    /**
     * @throws UnableToRetrieveMetadata
     * @throws FilesystemException
     */
    public function lastModified(string $path): FileAttributes
    {
        throw new UnableToRetrieveMetadata();
    }

    /**
     * @throws UnableToRetrieveMetadata
     * @throws FilesystemException
     */
    public function fileSize(string $path): FileAttributes
    {
        throw new UnableToRetrieveMetadata();
    }

    /**
     * @return iterable<StorageAttributes>
     *
     * @throws FilesystemException
     */
    public function listContents(string $path, bool $deep): iterable
    {
        return [];
    }

    /**
     * @throws UnableToMoveFile
     * @throws FilesystemException
     */
    public function move(string $source, string $destination, Config $config): void {}

    /**
     * @throws UnableToCopyFile
     * @throws FilesystemException
     */
    public function copy(string $source, string $destination, Config $config): void {}
}

2. Update app providers

Add the following to any ServiceProvider e.g AppServiceProvider.php

<?php


    // Register custom driver
    Storage::extend('peskom_filestore', function (Application $app, array $config) {
      $adapter = new PeskomFilestoreAdapter($config);
      return new FilesystemAdapter(
        new Filesystem($adapter, $config),
        $adapter,
        $config
      );
    });

Your AppServiceProvider should look like this

<?php

namespace App\Providers;

use Illuminate\Support\Facades\Storage;
use Illuminate\Support\ServiceProvider;
use App\Media\PeskomFilestoreAdapter;
use Illuminate\Filesystem\FilesystemAdapter;
use Illuminate\Contracts\Foundation\Application;
use League\Flysystem\Filesystem;

class AppServiceProvider extends ServiceProvider
{
  /**
   * Register any application services.
   */
  public function register(): void
  {
    //
  }

  /**
   * Bootstrap any application services.
   */
  public function boot(): void
  {
    // Register custom driver
    Storage::extend('peskom_filestore', function (Application $app, array $config) {
      $adapter = new PeskomFilestoreAdapter($config);
      return new FilesystemAdapter(
        new Filesystem($adapter, $config),
        $adapter,
        $config
      );
    });
  }
}

3. Update your config/filesystems.php file

Include the new filesystem by adding this to your config/filesystems.php file under the disks

      
        // add the custom file system
        'peskom_filestore' => [
            'driver' => 'peskom_filestore',
        ],

your file should look like this

<?php


return [

    /*
    |--------------------------------------------------------------------------
    | Default Filesystem Disk
    |--------------------------------------------------------------------------
    |
    | Here you may specify the default filesystem disk that should be used
    | by the framework. The "local" disk, as well as a variety of cloud
    | based disks are available to your application. Just store away!
    |
    */

    'default' => env('FILESYSTEM_DISK', 'local'),

    /*
    |--------------------------------------------------------------------------
    | Filesystem Disks
    |--------------------------------------------------------------------------
    |
    | Here you may configure as many filesystem "disks" as you wish, and you
    | may even configure multiple disks of the same driver. Defaults have
    | been set up for each driver as an example of the required values.
    |
    | Supported Drivers: "local", "ftp", "sftp", "s3"
    |
    */

    'disks' => [

        
        // add the custom file system
        'peskom_filestore' => [
            'driver' => 'peskom_filestore',
        ],

        'local' => [
            'driver' => 'local',
            'root' => storage_path('app'),
            'throw' => false,
        ],
        'public' => [
            'driver' => 'local',
            'root' => storage_path('app/public'),
            'url' => env('APP_URL') . '/storage',
            'visibility' => 'public',
            'throw' => false,
        ],

    ],
];

You can now use it in your project by setting the default filesystem e.g in your .env

FILESYSTEM_DISK=peskom_filestore


Comments

Leave a Reply

Your email address will not be published. Required fields are marked *