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

Anaxarchos's avatar

Trying to understand Storage::path() and public_path()

In my Laravel App I have a typical storage link to 'storage/app/public/' directory. Now I have an jpg in a directory 'images'. In the browser I can access the image via the url 'https://my-domain.com/images/my-image.jpg'

When I do a dd($path) on

$path = public_path('images/my-image.jpg') i get
'/var/www/html/my-app/public/images/my-image.jpg'

and when I do a dd($path) on

$path = Storage::path('images/my-image.jpg') I get
'/var/ww/html/my-app/storage/app/images/my-image.jpg'

But only if I add a 'public' to my relative path the Storage::path() returns a desired output. So I am certainly missing something, but have no idea. Any hint appreciated, thank you.

0 likes
5 replies
LaryAI's avatar
Level 58

In Laravel, the public_path() and Storage::path() functions serve different purposes and point to different directories. Let's break down their usage and the behavior you're observing.

public_path()

The public_path() function returns the absolute path to the public directory of your Laravel application. This is where your publicly accessible files (like images, CSS, JavaScript) are stored.

For example:

$path = public_path('images/my-image.jpg');
dd($path); // Outputs: '/var/www/html/my-app/public/images/my-image.jpg'

This is correct because the public_path() function is designed to point to the public directory.

Storage::path()

The Storage::path() function is used to get the absolute path to a file stored in the storage directory. By default, Laravel's filesystem configuration is set up to use the local disk, which points to the storage/app directory.

For example:

$path = Storage::path('images/my-image.jpg');
dd($path); // Outputs: '/var/www/html/my-app/storage/app/images/my-image.jpg'

This is also correct because Storage::path() is designed to point to the storage/app directory.

Understanding the Storage Link

When you run php artisan storage:link, Laravel creates a symbolic link from public/storage to storage/app/public. This allows you to access files stored in storage/app/public via a URL.

To access files in the storage/app/public directory, you should use the public disk in Laravel's filesystem configuration.

For example:

$path = Storage::disk('public')->path('images/my-image.jpg');
dd($path); // Outputs: '/var/www/html/my-app/storage/app/public/images/my-image.jpg'

This is the correct way to get the path to a file stored in the storage/app/public directory.

Summary

  • Use public_path() to get the absolute path to files in the public directory.
  • Use Storage::path() to get the absolute path to files in the storage/app directory.
  • Use Storage::disk('public')->path() to get the absolute path to files in the storage/app/public directory, which are accessible via the public/storage URL.

Example Code

Here is an example to clarify the usage:

// Path to a file in the public directory
$publicPath = public_path('images/my-image.jpg');
dd($publicPath); // Outputs: '/var/www/html/my-app/public/images/my-image.jpg'

// Path to a file in the storage/app directory
$storagePath = Storage::path('images/my-image.jpg');
dd($storagePath); // Outputs: '/var/www/html/my-app/storage/app/images/my-image.jpg'

// Path to a file in the storage/app/public directory
$storagePublicPath = Storage::disk('public')->path('images/my-image.jpg');
dd($storagePublicPath); // Outputs: '/var/www/html/my-app/storage/app/public/images/my-image.jpg'

I hope this clarifies the differences and helps you understand how to use these functions correctly!

Anaxarchos's avatar

@LaryAI This seems a bit odd to me, because when I do a check with file_exists on both paths, I get a false. This is correct since the absolute path to the jpg is in this case

/var/www/html/my-app/storage/app/public/images/my-image.jpg

Neither public_path nor Storage::path return this correct output by default.

jlrdw's avatar

Without a symbolic link, you would have to serve the images through a script, but the symbolic link allows you to serve them with an image tag.

For secure images I use a script and authentication anyway.

There are good previous post on setting up an image controller.

Snapey's avatar

storage/app/public === public/storage

What you do to one, is identical to the other because of the symlink

public/images is a totally different folder.

puklipo's avatar

As is common in Laravel, if the driver is not specified, the default setting will be used.
Many people don't understand this because it's invisible.

// If the default is local, these two are the same.
Storage::path();
Storage::disk('local')->path();

local disk and public disk are similar but different.

    'disks' => [

        'local' => [
            'driver' => 'local',
            'root' => storage_path('app'),
            'throw' => false,
        ],

        'public' => [
            'driver' => 'local',
            'root' => storage_path('app/public'),
            'url' => env('APP_URL').'/storage',
            'visibility' => 'public',
            'throw' => false,
        ],

https://github.com/laravel/laravel/blob/11.x/config/filesystems.php

root paths are different, so the path() results are also different.

Storage::disk('local')->path();
Storage::disk('public')->path();

If you go back to when you uploaded the file, you should have specified public.

$request->file('...')->store('...', 'public');

If you save it to the public disk, use the public disk when reading it. Be aware of the differences between disks.

Please or to participate in this conversation.