Registering Database Migrations in Laravel Packages
When a Laravel package needs its own database tables, its maintainers must decide how the host application will find the package’s migration…
In a Laravel application, the storage choice determines whether a browser can fetch a file directly or must ask Laravel to check the request first. Use public storage for files meant for anyone to view, such as public profile images. Store invoices, identity documents, and other user-specific files privately, then serve them through a route that checks the requester’s permissions.
Laravel uses disks, named configurations that tell it where files are stored and how to access them. A disk’s visibility setting tells the storage driver whether its files are public or private. Laravel authorization checks whether a requester may access a file; files exposed through a public web path remain reachable without that check.
Laravel’s public disk is intended for files that anyone with the URL can access. In a common local setup, php artisan storage:link creates a symbolic link (a filesystem pointer) from public/storage to storage/app/public. The web server can then serve those files directly. The Laravel symlink discussion describes this mapping.
For example, after storing avatars/example.jpg on the public disk, the file is reachable at a URL such as /storage/avatars/example.jpg. Laravel can generate the URL with Storage::disk('public')->url('avatars/example.jpg'). If the application uses the conventional symlink path, asset('storage/avatars/example.jpg') also builds a URL to the public path; reports about asset() URL generation show why the configured URL and deployed path need to match.
Use storage:link when the files in the linked directory are intentionally public. Every file under storage/app/public becomes reachable through the link without authentication, so do not put confidential uploads there. A predictable URL, such as one containing a user ID or document name, does not protect a file.
Keep protected files outside any directory the web server serves directly. When a user requests a private file, Laravel should handle the request and verify the user's identity. It should then check whether they can access the file and return it only if they have permission. Laravel’s storage middleware discussion covers serving files through a route rather than exposing their storage path.
A route can use authentication middleware, while the controller checks the user’s permission before returning the file:
use Illuminate\Support\Facades\Storage;
public function download(Document $document)
{
$this->authorize('view', $document);
return Storage::disk('private')->download($document->path);
}
The authorization check decides whether the signed-in user may access the document. download() returns the file only if the check passes. Load the file from a record the user is allowed to access, rather than accepting any filesystem path from the request. For a file meant to display in the browser rather than download, return an appropriate file response after the same permission check.
Laravel lets you define separate disks for public and private files in config/filesystems.php. For storage drivers that support it, a disk’s visibility setting tells the driver whether files should be public or private. The Laravel Nova discussion of file visibility illustrates this configuration.
Visibility does not make a web server enforce Laravel authorization. If a file sits under a publicly served path or a public symlink, changing visibility alone does not add a permission check to requests for its URL. Keep public files on a public disk and private files on a separate disk whose storage location is not linked into the web root.
Specify the disk when saving files so Laravel does not place an upload on an unintended default disk. If a generated URL points to a nonexistent or inaccessible location, check which disk stored the file and whether its URL configuration matches the deployed path. The discussion of unexpected temporary upload paths illustrates the confusion that follows when stored paths and public URLs do not line up.
A temporary URL is a link that stops granting access after a set time. The configured storage driver must support temporary URLs. Cloud storage drivers may provide temporary URLs through their provider’s signed-link mechanism. Laravel’s local disk does not create temporary URLs by default; developers who need them for local storage must configure a custom URL builder, as discussed in the temporary URL configuration thread.
A temporary link is useful when a recipient needs time-limited access without downloading through a Laravel controller on every request. Check whether the driver supports temporary URLs and whether you have configured them before relying on this feature. For sensitive files, a Laravel route that authenticates the requester and checks the file’s owner or access policy provides an explicit authorization step.
Give Vroni a GitHub issue, bug report, spec, or rough idea. It reads the repo, plans the change, writes code, runs checks, and works toward a review-ready pull request.
Take a look at vroni.com