0

I'm creating logic about uploading avatars to users:

blade.php

<image src="{{ $user->profile->image ? storage_path() . '/  app/public/' . $user->profile->image : '' }}"/>
<input type="file" id="avatar" name="avatar"  style="display:none;"/>
<label for="avatar">{{ __('text.select_file') }}</label>

Controller (update method):

public function update(User $user)
{
    $this->authorize('update', $user->profile);

    $data = request()->validate([
        'name' => 'required',
    ]);

    if (request('avatar')) {
        $imagePath = request('avatar')->store('uploads/avatars', 'public');

        $image = Image::make(storage_path("app/public/{$imagePath}"))->fit(800, 800);
        $image->save();

        $imageArray = ['image' => $imagePath];
    }

    auth()->user()->profile->update(array_merge(
        $data,
        $imageArray ?? []
    ));

    return redirect("/profile/{$user->id}");
}

When I upload a picture it is stored in storage/app/public/uploads/avatars in DB value for avatar is uploads/avatars/name.jpeg

As you can see I have hard code app/public/ in controller and in view files, this is by default, I didn't change any paths, here is filesystem.php:

<?php

return [

    'default' => env('FILESYSTEM_DRIVER', 'local'),

    'disks' => [

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

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

        's3' => [
            'driver' => 's3',
            'key' => env('AWS_ACCESS_KEY_ID'),
            'secret' => env('AWS_SECRET_ACCESS_KEY'),
            'region' => env('AWS_DEFAULT_REGION'),
            'bucket' => env('AWS_BUCKET'),
            'url' => env('AWS_URL'),
            'endpoint' => env('AWS_ENDPOINT'),
            'use_path_style_endpoint' => env('AWS_USE_PATH_STYLE_ENDPOINT', false),
        ],

    ],

    'links' => [
        public_path('storage') => storage_path('app/public'),
    ],

];

So how do I avoid these coded paths? And why Laravel default store folder is in storage and not in public directory ? Should I upload avatars to public directory or to leave them in storage? I'm looking for best and correct practices ?

1 Answers1

1

I'm not well versed in Laravel, but I think you should be storing everything publicly accessible in /public/ with public_path(): Difference between storing files in public directory and in storage in Laravel 5.4

Just calling public_path($user->profile->image) should work, but you'll probably want to keep some path in there to make sure the avatars are in their own directory. Perhaps you could write another helper function:

function avatar_path($filename){
  return public_path('avatars/'.$filename);
}

Then use avatar_path() everywhere rather than storage_path()/public_path(). I'm not sure if something as straightforward as that is the "Laravel way" though.

Jonathon Reinhart
  • 132,704
  • 33
  • 254
  • 328
Quasipickle
  • 4,383
  • 1
  • 31
  • 53