verism's avatar

How do I make my image storing method reusable?

I've been getting to grips with how to incorporate an image upload facility, and have basically written a stand-alone class to deal with this

class PortraitController extends Controller
{

    public function create()
    {
        return view('test');
    }

    public function store(Request $request)
    {
        $this->validate($request, [
            'user_portrait' => 'required|mimes:jpeg,png|dimensions:min_width=800,max_width:1800|max:2048'
        ]);

        $file_basename = time();
        $file_extension = $request->user_portrait->extension();

        $user_id = '234567890'; // test purposes
        $filepath = 'user/' . $user_id . '/uploads/';

        $small = Image::make( $request->user_portrait )->resize(200, null, function($constraint){
            $constraint->aspectRatio();
        })->stream();
        $medium = Image::make( $request->user_portrait )->resize(800, null, function($constraint){
            $constraint->aspectRatio();
        })->stream();
        $large = Image::make( $request->user_portrait )->resize(1000, null, function($constraint){
            $constraint->aspectRatio();
        })->stream();

        Storage::disk('public')->put( $filepath.$file_basename.'_small.'.$file_extension, $small, 'public');
        Storage::disk('public')->put( $filepath.$file_basename.'_medium.'.$file_extension, $medium, 'public');

        // return redirect()->route('dashboard');
        return back();
    }
}

Happily, the images are processed and stored perfectly - however I'm not sure of the best way to incorporate this into my project. I will need to call the store method from at least two areas - once in the user registration process (I'll be customising the default RegisterController somehow) and again from one or more custom forms.

I started looking for information on how to call a method from another controller, only to discover that's a huge no-no, so how should I translate the above into something I can reuse at will?

0 likes
2 replies
Cronix's avatar
Cronix
Best Answer
Level 67

You can make a trait, and use the trait where needed. I'd have a method in the trait that would accept the name of the file input so that isn't hardcoded.

something like:

trait UserUpload
{
    public function saveAndResize($inputName) {
        $file_basename = time();
        $file_extension = $request->$inputName->extension();

        $user_id = '234567890'; // test purposes
        $filepath = 'user/' . $user_id . '/uploads/';

        $small = Image::make( $request->$inputName )->resize(200, null, function($constraint){
            $constraint->aspectRatio();
        })->stream();
        $medium = Image::make( $request->$inputName )->resize(800, null, function($constraint){
            $constraint->aspectRatio();
        })->stream();
        $large = Image::make( $request->$inputName )->resize(1000, null, function($constraint){
            $constraint->aspectRatio();
        })->stream();

        Storage::disk('public')->put( $filepath.$file_basename.'_small.'.$file_extension, $small, 'public');
        Storage::disk('public')->put( $filepath.$file_basename.'_medium.'.$file_extension, $medium, 'public');
    }
}
use App\UserUpload;

class PortraitController extends Controller
{
    public function store(Request $request)
    {
        use UserUpload;

        $this->validate($request, [
            'user_portrait' => 'required|mimes:jpeg,png|dimensions:min_width=800,max_width:1800|max:2048'
        ]);

        $this->saveAndResize('user_portrait');

        return back();
    }
}

I'd do a bit more like return if it was successful, etc.

1 like
verism's avatar

That's a huge help, thanks. I had to alter the trait a little, so that all references to $request->$inputName were $inputName instead, but it works like a charm.

Please or to participate in this conversation.