From 67d40b222f1a02975f7b7293705776d5249f174d Mon Sep 17 00:00:00 2001 From: "Joseph.Rawlings" Date: Sun, 30 Nov 2025 08:29:57 -0500 Subject: [PATCH] feat: add ensureStorageSymlinkExists method to AppServiceProvider for managing storage symlink --- app/Providers/AppServiceProvider.php | 82 ++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 18a224ee1..7f3de5c4e 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -18,6 +18,7 @@ use Illuminate\Queue\Events\JobFailed; use Illuminate\Queue\Events\JobProcessed; use Illuminate\Routing\UrlGenerator; use Illuminate\Support\Facades\Event; +use Illuminate\Support\Facades\File; use Illuminate\Support\Facades\Gate; use Illuminate\Support\Facades\Queue; use Illuminate\Support\ServiceProvider; @@ -91,6 +92,9 @@ class AppServiceProvider extends ServiceProvider */ public function boot(): void { + // Ensure storage symlink exists for public access + $this->ensureStorageSymlinkExists(); + // Change livewire url \Livewire\Livewire::setUpdateRoute(function ($handle) { return \Illuminate\Support\Facades\Route::post('/paymenter/update', $handle)->middleware('web')->name('paymenter.'); @@ -160,4 +164,82 @@ class AppServiceProvider extends ServiceProvider }); } } + + /** + * Ensure the storage symlink exists for public file access + */ + protected function ensureStorageSymlinkExists(): void + { + $publicStoragePath = public_path('storage'); + $targetStoragePath = storage_path('app/public'); + + // Check if symlink doesn't exist or is broken + if (!file_exists($publicStoragePath) || !is_link($publicStoragePath)) { + // Remove broken symlink or existing file/directory if it exists + if (file_exists($publicStoragePath)) { + if (is_link($publicStoragePath)) { + @unlink($publicStoragePath); + } elseif (is_dir($publicStoragePath)) { + // If it's a directory, we can't safely remove it automatically + // Log a warning instead + \Log::warning('Storage symlink cannot be created: public/storage exists as a directory. Please remove it manually and run: php artisan storage:link'); + return; + } else { + @unlink($publicStoragePath); + } + } + + // Ensure target directory exists + if (!file_exists($targetStoragePath)) { + File::makeDirectory($targetStoragePath, 0755, true); + } + + // Create the symlink using Laravel's filesystem links + try { + $links = config('filesystems.links', []); + foreach ($links as $link => $target) { + if (file_exists($link)) { + continue; + } + + if (PHP_OS_FAMILY === 'Windows') { + // Windows requires administrator privileges for symlinks + // Try to create junction instead + if (function_exists('exec')) { + $command = sprintf( + 'mklink /J "%s" "%s"', + str_replace('/', '\\', $link), + str_replace('/', '\\', $target) + ); + @exec($command, $output, $return); + if ($return !== 0) { + \Log::warning('Storage symlink creation failed on Windows. Please run: php artisan storage:link'); + } + } else { + \Log::warning('Storage symlink cannot be created on Windows. Please run: php artisan storage:link'); + } + } else { + // Unix/Linux - create symlink + symlink($target, $link); + } + } + } catch (\Exception $e) { + \Log::warning('Storage symlink creation failed: ' . $e->getMessage() . '. Please run: php artisan storage:link'); + } + } elseif (is_link($publicStoragePath)) { + // Check if symlink is broken (points to non-existent target) + $linkTarget = readlink($publicStoragePath); + if ($linkTarget && !file_exists($linkTarget) && $linkTarget !== $targetStoragePath) { + // Symlink is broken, recreate it + @unlink($publicStoragePath); + try { + if (PHP_OS_FAMILY !== 'Windows') { + symlink($targetStoragePath, $publicStoragePath); + } + } catch (\Exception $e) { + \Log::warning('Storage symlink recreation failed: ' . $e->getMessage() . '. Please run: php artisan storage:link'); + } + } + } + } }