skip to Main Content

I have a problem with the methods in the controller getting very large and hard to read. In the code below that I will place is a method for ecommerce categories that stores data in the database.

At the beginning, I have to save the file on the local disk where the larger code is and then write it into the database.
I have to copy all the same code for storing the file in the local directory in the UPDATE method, where the code is duplicated and difficult to read and maintain.

How would it be best to separate all of this into smaller units?

class CategoryController extends EcommerceController
{
    /**
     * Store a newly created resource in storage.
     */
    public function store(CategoryPostRequest $request)
    {
        // Store uploaded file
        if($request->hasFile('image')) {
            $image = $request->file('image');
            $name = pathinfo($image->getClientOriginalName(), PATHINFO_FILENAME);
            $extension = $image->getClientOriginalExtension();
            $path = config('ecommerce.catalog_category_upload_dir').'/'.str_replace(' ', '-', strtolower($request->input('name')));
            $image_upload_path = $path.'/'.$name.'.'.$extension;

            // Rename duplicate filename (rename file adding number)
            if($this->ecommercePublicDisk()->exists($image_upload_path)) {
                $i = 1;
                while ($this->ecommercePublicDisk()->exists($image_upload_path)) {
                    $image_upload_path = $path.'/'.$name.'_'.$i.'.'.$extension;
                    $i++;
                }
                $this->ecommercePublicDisk()->put($image_upload_path, file_get_contents($image));
            }

            $this->ecommercePublicDisk()->put($image_upload_path, file_get_contents($image));
        }

        // Create category
        $category = Category::create([
            'parent_id' => $request->input('parent_id'),
            'name' => $request->input('name'),
            'slug' => $request->input('slug'),
            'description' => $request->input('description'),
            'meta_title' => $request->input('meta_title'),
            'meta_description' => $request->input('meta_description'),
            'image' => $image_upload_path  ?? '',
            'status' => $request->input('status') == 'on' ? 1 : 0,
            'sort_order' => $request->input('sort_order')
        ]);

        // Create category in slected stores
        $category->stores()->attach($request->input('stores'));

        return redirect()->route('categories.index')
            ->with('success', 'Category '. $category->name .' created successfully');
    }

    
/**
 * Update the specified resource in storage.
 */
public function update(CategoryUpdateRequest $request, int $id)
{
    $category = Category::where('id',$id)->firstOrFail();


    // HERE REPEAT ALL LOGIC FOR UPLOAD FILE 
  

    $category->update([
        'parent_id' => $request->input('parent_id'),
        'name' => $request->input('name'),
        'slug' => $request->input('slug'),
        'description' => $request->input('description'),
        'meta_title' => $request->input('meta_title'),
        'meta_description' => $request->input('meta_description'),
        'image' =>  $request->file('image') ?? '',
        'status' => $request->input('status') == 'on' ? 1 : 0,
        'sort_order' => $request->input('sort_order')
    ]);

    $category->stores()->sync($request->input('stores'));


    return redirect()->route('categories.edit', $category->id)
        ->with('success', 'Category '. $category->name .' successfully updated');
}

}

Can someone advise me how to solve this? Should I maybe create separate controllers for each method?

Thanks!

2

Answers


  1. You can always move the repetitive code to separate functions inside the same class or maybe in a separate service. Here is an example of your refactored code.

    public function store(CategoryPostRequest $request)
    {
        $image_upload_path = $this->storeUploadedFile($request);
    
        $category = $this->createCategory($request, $image_upload_path);
    
        $this->createCategoryStores($category, $request);
    
        return redirect()->route('categories.index')
            ->with('success', 'Category '. $category->name .' created successfully');
    }
    
    private function storeUploadedFile($request)
    {
        $image_upload_path = '';
        if ($request->hasFile('image')) {
            $image = $request->file('image');
            $name = pathinfo($image->getClientOriginalName(), PATHINFO_FILENAME);
            $extension = $image->getClientOriginalExtension();
            $path = config('ecommerce.catalog_category_upload_dir').'/'.str_replace(' ', '-', strtolower($request->input('name')));
            $image_upload_path = $this->renameDuplicateFilename($path, $name, $extension);
            $this->ecommercePublicDisk()->put($image_upload_path, file_get_contents($image));
        }
        return $image_upload_path;
    }
    
    private function renameDuplicateFilename($path, $name, $extension)
    {
        $image_upload_path = $path.'/'.$name.'.'.$extension;
        if ($this->ecommercePublicDisk()->exists($image_upload_path)) {
            $i = 1;
            while ($this->ecommercePublicDisk()->exists($image_upload_path)) {
                $image_upload_path = $path.'/'.$name.'_'.$i.'.'.$extension;
                $i++;
            }
        }
        return $image_upload_path;
    }
    
    private function createCategory($request, $image_upload_path)
    {
        return Category::create([
            'parent_id' => $request->input('parent_id'),
            'name' => $request->input('name'),
            'slug' => $request->input('slug'),
            'description' => $request->input('description'),
            'meta_title' => $request->input('meta_title'),
            'meta_description' => $request->input('meta_description'),
            'image' => $image_upload_path,
            'status' => $request->input('status') == 'on' ? 1 : 0,
            'sort_order' => $request->input('sort_order')
        ]);
    }
    
    private function createCategoryStores($category, $request)
    {
        $category->stores()->attach($request->input('stores'));
    }
    
    public function update(CategoryUpdateRequest $request, int $id)
    {
        $category = Category::where('id', $id)->firstOrFail();
    
        $image_upload_path = $this->storeUploadedFile($request);
    
        $category->update($this->getCategoryUpdateData($request, $image_upload_path));
    
        $this->syncCategoryStores($category, $request);
    
        return redirect()->route('categories.edit', $category->id)
            ->with('success', 'Category '. $category->name .' successfully updated');
    }
    
    private function getCategoryUpdateData($request, $image_upload_path)
    {
        return [
            'parent_id' => $request->input('parent_id'),
            'name' => $request->input('name'),
            'slug' => $request->input('slug'),
            'description' => $request->input('description'),
            'meta_title' => $request->input('meta_title'),
            'meta_description' => $request->input('meta_description'),
            'image' => $request->file('image') ?? $image_upload_path,
            'status' => $request->input('status') == 'on' ? 1 : 0,
            'sort_order' => $request->input('sort_order')
        ];
    }
    
    private function syncCategoryStores($category, $request)
    {
        $category->stores()->sync($request->input('stores'));
    }
    
    Login or Signup to reply.
  2. Instead of two methods you can use single method:

    $category = Category::updateOrCreate(
    [
        'name' => $request->input('name'),
        'slug' => $request->input('slug')
    ],
    [
        'parent_id' => $request->input('parent_id'),
        'description' => $request->input('description'),
        'meta_title' => $request->input('meta_title'),
        'meta_description' => $request->input('meta_description'),
        'image' =>  $request->file('image') ?? '',
        'status' => $request->input('status') == 'on' ? 1 : 0,
        'sort_order' => $request->input('sort_order')
    ]
    

    );

    if ($category->wasRecentlyCreated === true) {
        $category->stores()->attach($request->input('stores'));
        return redirect()->route('categories.index')
            ->with('success', 'Category '. $category->name .' created successfully');
    } else {
        $category->stores()->sync($request->input('stores'));
        return redirect()->route('categories.edit', $category->id)
            ->with('success', 'Category '. $category->name .' successfully updated');
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search