4

Currently running into issues on my server with links to files in my Laravel application.

I currently have a images folder in storage/app/public and I linked the storage/app/public folder to public with php artisan storage:link.

Now i have a image.jpg in the images folder. On my local system while using valet I can see the image with the tow following links:

  1. /images/image.jpg
  2. /storage/images/image.jpg

On my server only the second one works (which I assume is correct as there is no images folder directly in the public-directory.

Problem is, I often run into issues when deploying as customers can't see images online (as the link is not working). This wouldn't be an issue if I could not see images local while testing the UI.

Anyone also has this issue and can lead me to some kind of solution?

Oli
  • 240
  • 1
  • 10
  • "I often run into issues when deploying as customers can't see images online (as the link is not working)." can you clarify, this is difficult to understand. Do you mean that after you deploy the symlink stops working? – sam Apr 09 '18 at 14:03
  • No the symlink works (as does the second URL) but the first one (without storage) works locally (and I think it shouldn't) but does not work on the server I deploy to. – Oli Apr 09 '18 at 14:41
  • Have you created a symlink in the past on your local machine that you've forgotten about? What happens if you run `stat public/images` from the laravel application's directory on your local machine? Valet doesn't do anything like this by default. – sam Apr 09 '18 at 14:49
  • `stat public/images` returns "No such file or directory" – Oli Apr 09 '18 at 15:18
  • That's really strange, I cannot reproduce the issue and looking through the [Valet source code](https://github.com/laravel/valet) I can find nothing that would cause `public/images` to return files from `app/storage/public`. Can you reproduce this with a new Laravel project locally? Have you tried reinstalling Valet? There is, presumably, some configuration somewhere that you've forgotten about. – sam Apr 09 '18 at 15:25
  • I just reinstalled valet and I got this in several projects. This also happens on two different macs and some of my colleagues got the same issues... – Oli Apr 09 '18 at 15:34
  • For clarity, just to ensure we're on exactly the same page, the issue that you and others can reproduce is: "When running a Laravel project locally with Valet, requests to `/images` are routed to `storage/app/public`, e.g: `https://example.dev/images/example.png` returns the contents of `storage/app/public/images/example.png`"? – sam Apr 09 '18 at 15:41
  • that's exactly it. – Oli Apr 09 '18 at 15:44
  • I was wrong, I missed the functionality that does this when reviewing the source code. I've submitted an answer with the fix for you :-) – sam Apr 09 '18 at 15:53

2 Answers2

4

The issue is that the LaravelValetDriver has a fallback test; if the file doesn't exist in the public directory then it will check the public storage directory.

You can find that here:

if ($this->isActualFile($storagePath = $sitePath.'/storage/app/public'.$storageUri)) {
    return $storagePath;
}

You can prevent this behaviour by creating your own Valet Driver that extends the LaravelValetDriver and overrides the isStaticFile method, e.g:

class NoStorageFallbackLaravelValetDriver extends LaravelValetDriver
{

    public function isStaticFile($sitePath, $siteName, $uri)
    {
        if (file_exists($staticFilePath = $sitePath. '/public' . $uri)
       && is_file($staticFilePath)) {
            return $staticFilePath;
        }

        return false;
    }
}
sam
  • 5,459
  • 6
  • 32
  • 53
0

Using the public disk is straight forward and should work without problems out of the box.

The public disk uses the 'local' driver which by default uses the storage/app directory.


The command:

php artisan storage:link 

will create a symbolic link 'storage' inside your public folder that links to the non-public folder storage/app/public.

When the link is working, you can use the following command:

Storage::disk('local')->put('public/file.txt', 'Contents');

This will store file.txt to

storage/app/public/file.txt 

You won't be accessing the file at storage/app/public.file.txt instead you will be accessing it using the symlink public/storage...

Therefore your saved file will publicly accessible at

public/storage/file.txt

Use the asset helper you can get the location of the file:

echo asset('file.txt');
Giovanni S
  • 2,050
  • 18
  • 33
  • this already works. My current problem is, that links without specifying the `storage/images` but only `images` also work locally (and I can't get why). They should not, but do. And this leads to manual UI test that succeed as images are visible (no one wants to clutter witch checking the image paths...) – Oli Apr 09 '18 at 15:19
  • Ahh, the initial post looked like it said you were having problems rendering the files on the production server... So, what happens when you do something like, 'ls -la' in the yourapp/public folder? Do you see the files there or any weird sym link locally or on the server? – Giovanni S Apr 09 '18 at 15:24
  • 'ls -la' returns my storage symlink and the files really present there.. can not see anything for the `images`. – Oli Apr 09 '18 at 15:34