Использую фреймворк Laravel 5. Есть реальный пример, на котором бы хотелось понять какой можно применить шаблон проектирования, либо какой-то другой подход, чтобы
убрать дублирование кода.
В проекте существует много контроллеров с однотипным кодом создать/обновить сущность (новости, комментарии, отзывы и т.д.).
Возьмем новости:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\Post;
class PostsController
{
/**
* Создание новой записи.
*
* @param Request $request
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function store(Request $request)
{
$post = new Post;
$post->author_id = $request->user()->id;
$post->title = trim($request->get('title'));
$post->slug = str_slug($post->title);
$post->description = trim($request->get('description'));
$post->content = $request->get('content');
if ($request->hasFile('cover')) {
$file = $request->file('cover');
$fileName = str_random(8) . '.' . $file->getClientOriginalExtension();
$fileDirectory = '/storage/' . strtolower(substr($fileName, 0, 2));
$file->move(public_path($fileDirectory), $fileName);
$post->cover = "$fileDirectory/$fileName";
}
$post->save();
}
/**
* Обновление записи.
*
* @param Request $request
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function update(Request $request, $id)
{
$post = Post::find($id);
$post->title = trim($request->get('title'));
$post->slug = str_slug($post->title);
$post->description = trim($request->get('description'));
$post->content = $request->get('content');
if ($request->hasFile('cover')) {
$file = $request->file('cover');
$fileName = str_random(8) . '.' . $file->getClientOriginalExtension();
$fileDirectory = '/storage/' . strtolower(substr($fileName, 0, 2));
$file->move(public_path($fileDirectory), $fileName);
$post->cover = "$fileDirectory/$fileName";
}
$post->save();
}
}
Первое, что приходит в голову — создать приватный метод в контроллере:
class PostsController
{
public function store(Request $request)
{
$post = new Post;
$this->save($request, $post);
}
public function update(Request $request, $id)
{
$post = Post::find($id);
$this->save($request, $post);
}
private function save($request, $post)
{
$post->title = trim($request->get('title'));
$post->slug = str_slug($post->title);
$post->description = trim($request->get('description'));
$post->content = $request->get('content');
if ($request->hasFile('cover')) {
$file = $request->file('cover');
$fileName = str_random(8) . '.' . $file->getClientOriginalExtension();
$fileDirectory = '/storage/' . strtolower(substr($fileName, 0, 2));
$file->move(public_path($fileDirectory), $fileName);
$post->cover = "$fileDirectory/$fileName";
}
$post->save();
}
}
На GitHub я встречал несколько проектов, в которых такая проблема решалась с использованием репозитория:
App\Repositories\PostRepository.php<?php
class PostRepository
{
public function __construct(Post $post)
{
$this->post = $post;
}
public function store(Request $request)
{
$post = new $this->post;
$this->save($request, $post);
return $post;
}
public function update(Request $request, Post $post)
{
return $this->save($request, $post);
}
private function save($request, $post)
{
$post->title = trim($request->get('title'));
$post->slug = str_slug($post->title);
$post->description = trim($request->get('description'));
$post->content = $request->get('content');
if ($request->hasFile('cover')) {
$file = $request->file('cover');
$fileName = str_random(8) . '.' . $file->getClientOriginalExtension();
$fileDirectory = '/storage/' . strtolower(substr($fileName, 0, 2));
$file->move(public_path($fileDirectory), $fileName);
$post->cover = "$fileDirectory/$fileName";
}
return $post->save();
}
}
App\Http\Controllers\PostController.php
class PostController extends Controller
{
protected $postRepository;
public function __construct(PostRepository $postRepository)
{
$this->postRepository = $postRepository;
}
public function store(Request $request)
{
if ($this->postRepository->create($request)) {
// Created
} else {
// Fail
}
}
public function update(Request $request, $id)
{
$post = Post::find($id);
if ($this->postRepository->update($request, $post)) {
// Updated
} else {
// Fail
}
}
}
но т.к. я плохо знаком с шаблонами проектирования, то не уверен, что это правильный подход.