laravel/framework: Enums now accepted in FilesystemManager::set(), forgetDisk() and purge()
Contributed by riesjart
Part of the framework v13.35.0 release
Laravel's filesystem manager has accepted backed enums in Storage::disk() for some time, but the companion methods that manage resolved disks — set(), forgetDisk() and purge() — still required plain strings. Passing an enum to any of them either crashed with a TypeError or, in the case of forgetDisk(), silently did nothing. Pull request #61868 fixes all three by normalizing enum arguments through the framework's enum_value() helper, bringing these methods in line with the enum support developers already rely on elsewhere in the Storage facade.
What changed
Three methods on Illuminate\Filesystem\FilesystemManager now accept enums in place of (or alongside) string names:
set($name, $disk)stores the instance underenum_value($name)instead of using the raw enum object as an array key.forgetDisk($disk)normalizes each entry withenum_value()and switches its argument coercion from an(array)cast toArr::wrap().purge($name)resolves the name withenum_value()before unsetting; anullargument still falls back to the default driver, becauseenum_value()passesnullstraight through.
The argument docblocks were widened to \UnitEnum|string (and array<\UnitEnum|string> for forgetDisk()), the Storage facade docblock for set() was updated to match, and new tests cover all three methods using a string-backed enum.
The two bugs behind the fix
The first bug is the TypeError. PHP arrays can only be keyed by integers and strings, and enums are objects. With the old code, Storage::set(Disk::Backup, $fake) evaluated $this->disks[Disk::Backup] = $fake, and PHP threw TypeError: Cannot access offset of type Disk on array. The same applied to unset($this->disks[$name]) inside purge(). The inconsistency was the frustrating part: Storage::disk(Disk::Backup) worked, while Storage::purge(Disk::Backup) — a method you would naturally pair with it — crashed.
The second bug is subtler. forgetDisk() iterated with foreach ((array) $disk as $diskName). Casting a backed enum to an array does not produce a one-element array; it produces the enum's property table: ['name' => 'Backup', 'value' => 'backup']. The loop therefore iterated over the strings 'name' and 'value', and unset() removed keys that do not exist in $this->disks — a no-op. No exception was thrown, but the cached disk survived untouched. Arr::wrap() fixes this by wrapping non-array values as [$value], preserving the enum so enum_value() can convert it into its backing string.
What it looks like now
namespace App\Enums;
enum Disk: string
{
case Backup = 'backup';
case Archive = 'archive';
}
use App\Enums\Disk;
use Illuminate\Support\Facades\Storage;
// Inject a fake/mock disk (handy in tests) — threw a TypeError before
Storage::set(Disk::Backup, $fakeDisk);
// Force these disks to be re-resolved on next access — was a silent no-op before
Storage::forgetDisk([Disk::Backup, Disk::Archive]);
// Disconnect one disk and drop it from the cache — also threw before
Storage::purge(Disk::Backup);
Because enum_value(Disk::Backup) returns 'backup', the disk is keyed exactly as if you had passed the string. The new test testCanSetDiskUsingEnum demonstrates this: a disk set with the enum is immediately retrievable via $filesystem->disk('local'), so Storage::disk('backup') and Storage::disk(Disk::Backup) resolve the same instance.
Upgrade impact
This is a widening of accepted input, not a breaking change:
- Existing string-based calls behave identically;
enum_value()passes strings through untouched. - Code that previously crashed calling
set()orpurge()with an enum now works. - Code that "worked" by calling
forgetDisk()with an enum was silently doing nothing; it now actually forgets the disk. That is the behavior you want, but worth knowing if any test depended on stale disk instances persisting. purge()called with no argument (ornull) still disconnects the default driver, sinceenum_value(null)resolves tonulland the??fallback kicks in.- If you subclass
FilesystemManagerand override any of these methods, normalize arguments withenum_value()the same way the base class now does, so enum and string keys line up.
No configuration, container or environment changes are required — the upgrade is simply a matter of pulling the framework version.
Takeaways
FilesystemManager::set(),forgetDisk()andpurge()now accept backed enums, matching the existingStorage::disk()behavior.enum_value()converts enums to their string keys, so enum and string lookups share the same resolved-disk cache slots.- The
(array)cast bug inforgetDisk()is fixed withArr::wrap(), so enums are no longer exploded intoname/valueentries. - The change is purely additive: nothing to do for string usage, and only custom subclasses overriding these methods deserve a second look.
Category: Bug fix (9)