我有Laravel应用程序,并且在控制器内部,我在多个控制器中使用了具有相同结构的相同方法(大多数但不是全部)
如何重构这些控制器以获得更清晰的代码结构?
我可以使用基本控制器并扩展所有控制器吗,或者可以使用trait
我将Datatable用于大多数控制器,因此我在这些控制器中有destroyMultiple
和updateStatus
方法。并且所有控制器中的代码内容是如此相似(例如:只有名称中有更改),我很难在我拥有的每15个控制器中复制此方法(并且随着系统中其他控制器的增长)
这是我的控制器代码:
<?php
namespace App\Http\Controllers\Admin;
use App\Library\AdminLib;
use App\Library\Datatable;
use App\Project;
use App\ProjectImage;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Session;
class ProjectController extends Controller {
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index () {
return view("admin.projects.index");
}
/**
* Show the form for creating a new resource.
*
* @return \Illuminate\Http\Response
*/
public function create () {
$token = AdminLib::setUploadSession();
return view("admin.projects.create" , compact('token'));
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store ( Request $request ) {
$this->validate($request , [
'title' => 'required' ,
'alt' => 'required|unique:projects' ,
]);
$project = new Project($request->only([
'image' ,
//its image file
'alt' ,
'title' ,
'description' ,
'meta_keywords' ,
'meta_description' ,
]));
$project->active = AdminLib::fixSwitch('active');
$project->save();
//save images that uploaded ajax ( relate them to this project )
$token = AdminLib::getUploadSession();
$images = ProjectImage::with([])
->where('token' , $token)->get();
$project->projectImages()
->saveMany($images);
#
$project->projectVideos()
->createMany(AdminLib::filterUrl($request->get('videos')));
return redirect(route('admin.projects.index'))->with('success' , 'Information has been added');
}
/**
* Show the form for editing the specified resource.
*
* @param \App\Project $project
* @return \Illuminate\Http\Response
*/
public function edit ( Project $project ) {
$token = AdminLib::setUploadSession();
return view("admin.projects.edit" , compact('project' , 'token'));
}
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param \App\Project $project
* @return \Illuminate\Http\Response
*/
public function update ( Request $request , Project $project ) {
$this->validate($request , [
'title' => 'required' ,
'alt' => 'required' ,
]);
$project->fill($request->only([
'image' ,
//its image file
'alt' ,
'title' ,
'alt' ,
'description' ,
'meta_keywords' ,
'meta_description' ,
]));
$project->active = AdminLib::fixSwitch('active');
$project->save();
//save images that uploaded ajax ( relate them to this project )
$token = AdminLib::getUploadSession();
$images = ProjectImage::with([])
->where('token' , $token)->get();
$project->projectImages()
->saveMany($images);
//save video
$project->projectVideos()
->delete();
$project->projectVideos()
->createMany(AdminLib::filterUrl($request->get('videos')));
return redirect(route('admin.projects.index'))->with('success' , 'Information has been updated');
}
/**
* Remove the specified resource from storage.
*
* @param \App\Project $project
* @return array
* @throws \Exception
*/
public function destroy ( Project $project ) {
$ok = $project->delete();
return compact('ok');
}
public function destroyMultiple () {
$count = Project::with([])
->whereIn('id' , \request('id_list'))
->delete();
$ok = true;
return compact('count' , 'ok');
}
public function updateStatus () {
//some code to update status
}
public function datatable ( Request $request ) {
$datatable = new Datatable();
$response = $datatable->setRequest($request)
->setQuery(Project::with([]))
->generalSearch(function ( Builder $query , $search ) {
return $query->where('title' , 'like' , "%$search%")
->orWhere('id' , "%$search%");
})
->manipulateData(function ( Project $record ) {
$record->action = [
//todo fix route
'edit' => route('admin.projects.edit' , $record->id) ,
'destroy' => route('admin.projects.destroy' , $record->id) ,
];
//todo use model to decorate this
$record->created = "{$record->created_at->toFormattedDateString()} - {$record->created_at->toTimeString()}";
return $record;
})
->getResponse();
return $response;
}
}
答案 0 :(得分:1)
如果您遵循REST,那么您的控制器应该看起来一样,并且在这种情况下继承并不是真正有用的,因为使用-r
标志生成宁静的控制器将始终为您提供所需的所有方法。
答案 1 :(得分:0)
所有数据库逻辑应由模型负责。如果您有多个销毁和更新调用,最好从基础模型扩展所有模型,并使用Eloquent query scopes在基础模型中实现这两种方法。
Laravel的作者泰勒·奥特威尔(Taylor Otwell):
如果我从PHP中学到的一件事是控制器应该 没做什么。那些东西存在于这个空灵的飞机上,就像这样 朦胧的雾,什么都不做,将东西传给某个领域 抽象服务层
尽管他在同一个演讲中也提到很多情况都取决于用例,而以上是理想的情况。