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
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.
Instead of two methods you can use single method:
);