skip to content

In Laravel, what does storePublicly() change compared with store() on an UploadedFile, and what does it not change?

level: middleimportance: should knowfreq 32%

answer

  1. the visibility option set to public
  2. same random hashName() file name
  3. local driver: chmod the file to 0644
  4. does not move files under public/
  5. storePubliclyAs() for a chosen name

basics

~20 s

storePublicly() is store() with the visibility option forced to public: same generated name, same disk rules. It changes permissions or object access on the disk, but it does not make a file on a private local disk reachable by URL.

solid answer

~40 s

`storePublicly($path, $options)` parses the options exactly like `store()`, sets `$options['visibility'] = 'public'`, and calls `storeAs()` with `hashName()`; `storePubliclyAs($path, $name, $options)` does the same with your file name. Visibility is Flysystem's portable permission flag: on the local driver it maps to Unix permissions (0644 for public files, 0600 for private ones by default), and on S3 the adapter turns it into an object ACL. It does **not** change the disk, the directory or the name, so a photo written with `storePublicly('avatars')` to the default `local` disk still lives under `storage/app/private` with no URL. Web access comes from choosing a disk that is served, such as `public`, whose config already sets `'visibility' => 'public'`.

code

php · 19 lines
php
<?php

use Illuminate\Http\Request;

public function store(Request $request)
{
    $photo = $request->file('photo');

    // default local disk (storage/app/private): permissions 0644, still no URL
    $a = $photo->storePublicly('avatars');

    // object storage: written with public visibility, fetchable from the bucket
    $b = $photo->storePublicly('avatars', 's3');

    // public disk already defaults to 'visibility' => 'public'
    $c = $photo->store('avatars', 'public');

    return compact('a', 'b', 'c');
}

go deeper

for a junior

Know that storePublicly() saves like store() but marks the file public, and that storePubliclyAs() lets you choose the name.

for a middle

Explain Flysystem visibility, what it becomes on the local and S3 drivers, and why it does not create a URL on a private local disk.

for a senior

Choose disks and visibility per media type, and keep sensitive images private behind controllers or temporary URLs instead of public objects.

for a principal

Decide the media access model for the product, public buckets, signed access or proxying, and its cost and privacy implications.

## Four storage methods, one code path `Illuminate\Http\UploadedFile` has four methods for writing an upload to a disk, and all of them end in `storeAs()`: | Method | File name | Visibility option | |---|---|---| | `store($path, $options)` | `hashName()` (random) | whatever the disk defaults to | | `storeAs($path, $name, $options)` | the name you pass | whatever the disk defaults to | | `storePublicly($path, $options)` | `hashName()` (random) | forced to `public` | | `storePubliclyAs($path, $name, $options)` | the name you pass | forced to `public` | In each, `$options` may be a disk name string, which is turned into `['disk' => $name]`, or an array. `storeAs()` pulls the `disk` key out, resolves that disk and calls its `putFileAs()`, passing the remaining options, including `visibility`, down to Flysystem. ## What "visibility" means Laravel's filesystem layer is built on **Flysystem**, which models access as a portable **visibility** of `public` or `private` and lets each adapter translate it: - **Local driver.** Visibility becomes Unix permissions, applied with `chmod` when the file is written. The defaults in Flysystem's converter are `0644` for public files and `0600` for private ones (`0755` / `0700` for directories), and a disk can override them with a `permissions` array. When neither the call nor the disk config sets a visibility, as on the skeleton's `local` disk, no `chmod` happens and the file keeps whatever the process umask produced. - **S3 driver.** Visibility becomes an object ACL on write, so a public object can be fetched by anyone with its URL, as long as the bucket accepts ACLs. - **Other drivers** map it to whatever access model they have, or ignore it. ## What storePublicly() does not do This is where interview answers go wrong. `storePublicly()` does **not**: 1. switch to the `public` disk: it uses the default disk unless you pass another; 2. put the file under the `public/` web root; 3. create a URL, a symlink or a route. So on a fresh Laravel 13 app, `storePublicly('avatars')` writes to the default `local` disk, rooted at `storage/app/private`, and merely gives the file `0644` permissions. A browser still cannot load it, because no web server path points there. ## Getting a dating-profile photo onto the web The straightforward options are: - **Use the `public` disk**: `store('avatars', 'public')`. The skeleton's `public` disk is rooted at `storage/app/public`, has a `url` of `APP_URL/storage`, and already sets `'visibility' => 'public'`, so `storePublicly()` adds nothing there. The disk still needs its public symlink in place to be served. - **Use object storage** with `storePublicly('avatars', 's3')` when photos should be fetched straight from the bucket. - **Keep photos private** and serve them through a controller or temporary URL when only matched users may see them, which is often the right product decision on a dating app. ## Choosing between them - Prefer **`store()`** when the disk's default visibility is already right; it keeps the choice in configuration. - Use **`storePublicly()`** when the disk defaults to private but this particular object must be publicly readable, typically on a cloud disk. - Use the **`...As`** variants only when the name must be predictable, and build that name from server-side values. - Do not treat visibility as access control for sensitive images: public means anyone who learns the URL can fetch it. ## Checking the result Visibility is part of the write. When Flysystem cannot apply it, for example because a bucket refuses ACLs, the disk's `put()` catches the visibility failure along with write failures and, with the skeleton's `'throw' => false`, returns `false`; `storePublicly()` then returns `false` too. Always check the returned path, or enable `throw` on disks where a silent failure would leave a user without a photo. You can read the current value back later with the disk's `getVisibility()` and change it with `setVisibility()`, which is how a dating app might publish a photo only after moderation approves it.

  • Is storePublicly() the same as store() with ['visibility' => 'public'] in the options?
    Effectively yes. `storePublicly()` parses the options, sets `visibility` to `public` and calls `storeAs()` with `hashName()`, which is exactly what `store()` does with that option supplied. The named method just makes the intent explicit and stops a caller from forgetting the option.

saying these in an interview costs you the question

  • storePublicly() writes to the public disk automatically
  • storePublicly() moves the file under the public/ directory
  • Public visibility means the file gets a URL on any disk
  • storePublicly() keeps the client's original file name