Tony Messias

June 25, 2022

Environment-Specific Configs Using PHP8's Match

This is gonna be a short one. I previously shared this as a tweet, but thought it would make a nice little blog post. Recently I had the need of having the configuration of my disks in Laravel (docs). I started tinkering with how I wanted to be able to configure it, then I realized I already had a clean way using PHP8's `match` expression (docs):

<?php

// file: config/filesystems.php

return [
    // ...

    'disks' => [
        // ...

        'logos' => match (env('APP_ENV')) {
            'production' => [
                'driver' => 's3',
                'key' => env('AWS_ACCESS_KEY_ID'),
                'secret' => env('AWS_SECRET_ACCESS_KEY'),
                'region' => env('AWS_DEFAULT_REGION'),
                'bucket' => env('AWS_BUCKET'),
                'url' => env('AWS_URL'),
                'endpoint' => env('AWS_ENDPOINT'),
                'throw' => false,
            ],
            default => [
                'driver' => 'local',
                'root' => storage_path('app/logos'),
                'url' => env('APP_URL').'/logos',
                'visibility' => 'public',
                'throw' => false,
            ],
        },
    ],
];

Nice, isn't it? If I were only using a single `s3` disk, for instance, I could have described both env disks like so:

<?php

// file: config/filesystems.php

return [
    // ...

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

    'disks' => [
        // ...

        'logos_production' => [
            'driver' => 's3',
            'key' => env('AWS_ACCESS_KEY_ID'),
            'secret' => env('AWS_SECRET_ACCESS_KEY'),
            'region' => env('AWS_DEFAULT_REGION'),
            'bucket' => env('AWS_BUCKET'),
            'url' => env('AWS_URL'),
            'endpoint' => env('AWS_ENDPOINT'),
            'throw' => false,
        ],
        'logos_local' => [
            'driver' => 'local',
            'root' => storage_path('app/logos'),
            'url' => env('APP_URL').'/logos',
            'visibility' => 'public',
            'throw' => false,
        },
    ],
];

Then I could swap the `FILESYSTEM_DISK` environment variable on each env, and it would technically work, as long as I used the Storage component without specifying the actual disk:

Storage::put(...)

// vs.

Storage::disk('logos')->put(...)

I tend to prefer having multiple, feature-specific disks, even if they are using the same S3 credentials and bucket and the only thing that changes between them is the `root` option (which determines the "base path" to where files are going to be stored in the S3 Bucket).

That's it. See you soon.

About Tony Messias