Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Bacchus's avatar

Storage symlink or asset() path not working.

Hello,

I have multiple files uploaded per Product in my application. I am using the local storage at this point, but will use s3 in production. When I do the following, it works:

            <img id="prod-img" class="min-w-10 border border-red-600"
                src="{{  explode("/", $product->images[0]->path)[2] }}" alt="">
            <script>

This translates to

vv4S2dQoIJaLPG6K5Pd1cDeDsrdK1zagjZEPCSfl.jpeg

However just calling the regular asset() method does not work:

<img id="prod-img" class="min-w-10 border border-red-600" src="{{  asset($product->images[0]->path) }}"
                alt="">

This translates to:

http://dol-store-laravel.test/public/products/vv4S2dQoIJaLPG6K5Pd1cDeDsrdK1zagjZEPCSfl.jpeg

Why is asset() returning an invalid path? I will need a functional fully qualified uri at some point. I also find it strange that the image loads with no relative path, just the image name... laravel magic happening somewhere? I'm new to this framework.

I ran php artisan storage:link.

Thanks.

0 likes
9 replies
Bacchus's avatar

I assumed it would return a URL that actually worked as the src in an image tag.

Do you know why the image name with no path works? The local storage disk places the images in:

/storage/app/public/products

The symlink appears to have been created at

/public/storage/ within which there is a products directory containing the images.

This would lead me to believe that the correct fully qualified path is

http://dol-store-laravel.test/storage/products/vv4S2dQoIJaLPG6K5Pd1cDeDsrdK1zagjZEPCSfl.jpeg

but instead I get

http://dol-store-laravel.test/public/products/vv4S2dQoIJaLPG6K5Pd1cDeDsrdK1zagjZEPCSfl.jpeg

Here's my controller code storing the images. I think this is where I am going wrong.

        $images = $request->file('image');
        foreach ($images as $key => $image) {
            if ($request->file('image')[$key]->isValid()) {
                $path = $request->image[$key]->store('public/products');
                Image::create([
                    'product_id' => $product->id,
                    'path' => $path
                ]);
            }
        }
        return redirect('/admin/products');

So I think that images have to be stored in a different directory? But even here, I should be able to access them at storage/public/products and I cannot.

Thank you.

ahmeddabak's avatar

in the controller change this line to look like this

  $path = $request->image[$key]->store('products','public');

in the view

{{  asset('storage/'.$product->images[0]->path) }}
Bacchus's avatar

Yes, unfortunately this still does not work.

This results in a path stored in the database as follows;

products/OUGxqaEYJmHKlUqY1sQblCtTbCzrnFD0IcRS4T9c.jpeg

But when rendered to the DOM using asset('storage/' . $product->images[0]->path) it comes out like this:

<img id="prod-img" class="min-w-10 border border-red-600" src="http://dol-store-laravel.test/storage/products/OUGxqaEYJmHKlUqY1sQblCtTbCzrnFD0IcRS4T9c.jpeg" alt="">

Which does not supply the correct path.

My current folder structure appears as follows:

/storage/app/products/*.jpg /public/storage

edit: I see using php artisan help storage:link that it creates the symlink only to 'public', so I think that means I must use the public directory if I wish to access using asset()

a4ashraf's avatar

@bacchus

you should call your storage in your blade file as following


{{  asset('storage/app/'.$product->images[0]->path) }}


ahmeddabak's avatar

yes you should be using php artisan help storage:link and change the controller and view to the code i posted in my last comment.

Snapey's avatar

you should also fix your web server so that public does not appear in the urls and the web server root is the content of the public folder

Bacchus's avatar

@a4ashraf

This doesn't work unfortunately. I tried it anyway, but your suggestion yeilds a path of

http://dol-store-laravel.test/storage/app/public/JRegEAPLGpG6MqqAx6WTbNPWAhcQ0Nu1Msk0klCb.jpeg

because the $path stored in the database which comes from the file()->store('public') operation is always public/*.jpg and the symlink that is referred to by asset() expects storage/*.jpg for some reason.

@ahmeddabak

Thank you. I did try your code and have been using php artisan storage:link from the beginning , but it does not work. When I use file('images')->store('products') in the controller, it places the images in /storage/app/products, but php artisan storage:link specifically creates a link to /storage/app/public, making products/ and public/ sister directories.

I was able to get this working by storing with file('images')->store('public') and retrieving with {{ asset('storage/' . explode("/", $image->path)[0] }}, because I have to trim off the public/ part of the path returned by the file()->store() operation.

My question is this: why does file('images')->store('public') give me a faulty path?

Also @snapey I am using Laravel Forge with AWS, and I think the default configuration is web server root at public/, but I agree I would not push to prod with it like this.

ahmeddabak's avatar

My bad, i forget to add 'public' as the second argument, please try again.

Please or to participate in this conversation.