sebastian.virlan's avatar

Image upload and resize using Intervention

What do you think about this approach? Do you think any refactor is needed?



    public function imageUpload(PropertyImageRequest $request)
    {

        $response = $this->uploadImage($request->file('image'), $request->input('property_id'));

        return response()->json([
            'response' => $response['response'],
        ], $response['code']);
    }

    protected function uploadImage($image, $property_id)
    {
        $imagePath          = public_path('/uploads/properties/'.$property_id.'/');
        $originalName       = $image->getClientOriginalName();
        $extension          = $image->getClientOriginalExtension();
        $imageSize          = $image->getSize();
        $newImageName       = join('.', [uniqid(), $extension]);
        $thumbSizes         = [[150, 150],[400,300], [50,50]];

        if(!file_exists($imagePath))
            File::makeDirectory($imagePath);

        if(!$image->move($imagePath, $newImageName))
            return ['response' => 'Error on uploading image to server', 'code' => 200];

        if(!$this->resizeImage($imagePath, $newImageName, [null, 900]))
            return ['response' => 'Error on resizing image', 'code' => 200];

        foreach($thumbSizes as $thumbSize)
        {

            if(!$this->fitImage($imagePath, $newImageName, [$thumbSize[0], $thumbSize[1]]))
                return ['response' => 'Error on creating thumb', 'code' => 200];
        }

        $imageDB                = new Image();
        $imageDB->property_id   = $property_id;
        $imageDB->name          = $newImageName;
        $imageDB->original_name = $originalName;
        $imageDB->file_size     = $imageSize;
        $imageDB->save();

        return ['response' => $imageDB, 'code' => 200];
    }

    protected function fitImage($imagePath, $imageName, $size)
    {
        $destinationPath = $imagePath.$size[0].'x'.$size[1];
        if(!file_exists($destinationPath))
            File::makeDirectory($destinationPath);

        if(IImage::make($imagePath.$imageName)->fit($size[0], $size[1])
            ->save($destinationPath.'/'.$imageName))
            return true;
    }

    protected function resizeImage($imagePath, $imageName, $size)
    {
        if(IImage::make($imagePath.$imageName)->resize($size[0], $size[1], function ($constraint) {
            $constraint->aspectRatio();
            $constraint->upsize();
        })->save($imagePath.$imageName));
            return true;
    }
0 likes
1 reply
DarkRoast's avatar

Yeah you could break up some of those methods a bit and maybe a separate class to handle Thumbnail creation. I would also consider storing image sizes as value objects:

$thumbSizes = [
    new ImageSize(150, 150),
    new ImageSize(400, 400),
    new ImageSize(50, 50),
];

Then your Thumbnailer class might look something like:

class Thumbnailer
{
    public function batch($path, $image, array $thumbs = [])
    {
        foreach ($imageSizes as $size)
        {
            $this->fit($path, $image, $size);
        }
    }

    protected function fit($path, $image, ImageSize $size)
    {
        $destinationPath = $path.$size->getWidth().'x'.$size->getHeight();
        
        // etc...
    }

    public function resize($path, $image, ImageSize $size)
    {
        // maybe a resize method here too...
    }
}
1 like

Please or to participate in this conversation.