How to Fix Laravel Public Storage

by webmaster 2018-12-04 #laravel

Update (September 15, 2020): This issue is still present and relevant in Laravel 8. I ran into it while testing a fresh installation with Jetstream teams, trying to update my user profile photo.

When I ran into this particular problem with Laravel's filesystem, I had less experience with it than I do today (relatively speaking).

To give a little background, for my Laravel development environment I use Homestead on Mac and Windows both.

In one project I wanted to upload some images to the public folder. The Laravel documentation says that you should run the php artisan storage:link command in order to symlink the public folder (it maps storage/app/public to public/storage). By default, uploaded files are private.

In my case, the command seemed to succeed locally but in the browser I couldn't load the images even though they appeared to be in the correct folder. Eventually I determined that the symlink in the Homestead environment was incorrect.

Digging deeper, the problem is that the artisan command seems to create an absolute link to the storage folder, which (if you run the command locally) propagates to the synced environment (Homestead) which has an entirely different project structure for your website. As a result, if you check where the created symbolic link on the server (storage/app/public) is pointing to, you will see something to the effect of:

/Users/LocalUserName/code/MyProjectName

Which, of course, is not the same as public/storage.

So what happens if I run php artisan storage:link in the Vagrant box? I get this fairly bizarre error.

symlink(): No such file or directory

  at vendor/laravel/framework/src/Illuminate/Filesystem/Filesystem.php:315
    311▕      */
    312▕     public function link($target, $link)
    313▕     {
    314▕         if (! windows_os()) {
  ➜ 315▕             return symlink($target, $link);
    316▕         }
    317▕
    318▕         $mode = $this->isDirectory($target) ? 'J' : 'H';
    319▕

      +16 vendor frames
  17  artisan:37
      Illuminate\Foundation\Console\Kernel::handle()

Hmm... what now?

The solution proved simple:

First, ssh to the server, navigate to your project folder, then delete the symlink from the public folder:

cd public
unlink storage

Finally, run the command to create the symlink manually (assuming we are still in public/):

ln -s ../storage/app/public storage

Voila, now your images should work correctly.

Liked this article? Share it on your favorite platform.