【问题标题】:laravel application having same method in controllerslaravel 应用程序在控制器中具有相同的方法
【发布时间】:2018-11-12 19:15:28
【问题描述】:

我有 Laravel 应用程序和内部控制器,我在多个控制器中有相同的方法和相同的结构(大部分但不是全部)

如何重构这些控制器以获得更简洁的代码结构?

我可以使用基本控制器并扩展我的所有控制器吗?或者是否可以为此使用 trait

更新:

我的大多数控制器都使用 Datatable ,因此我在这些控制器中有 destroyMultipleupdateStatusmethod 。并且所有控制器中的代码内容都非常相似(例如:仅更改型号名称)并且我觉得在我拥有的每 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;
    }
}

【问题讨论】:

  • 继承在标准 OOP 规则方面是首选。特质也很有用,但不要滥用:)
  • 取决于你想做什么重构。没有一个正确的解决方案,一切都取决于用例。这个问题没有用例或代码就模棱两可
  • 我用代码@Paras 更新了问题

标签: laravel controller


【解决方案1】:

如果您遵循 REST,那么您的控制器应该看起来相同,并且在这种情况下继承并不是真正有用,因为生成带有 -r 标志的 RESTful 控制器将始终为您提供所需的所有方法。

【讨论】:

  • -r 标志将创建所有方法但没有实现!除了 laravel 创建的资源方法之外,我还有 2 个方法。我更新问题并添加代码。也许它有助于澄清我的问题
【解决方案2】:

所有数据库逻辑都应该由模型负责。如果您有多个销毁和更新调用,最好从基本模型扩展所有模型并使用Eloquent query scopes 在基本模型中实现这两种方法。

来自 Laravel 的创建者 Taylor Otwell:

如果我从 PHP 中学到的一件事是控制器应该 没做什么。那些东西存在于这个空灵位面,就这样 朦胧的雾,什么都不做,把东西传递给某个领域 抽象服务层

尽管他在同一次演讲中也提到很大程度上取决于用例,而以上是理想的场景。

【讨论】:

    猜你喜欢
    • 2019-04-09
    • 2013-06-14
    • 2017-10-17
    • 2014-08-26
    • 1970-01-01
    • 1970-01-01
    • 2015-12-07
    • 2017-09-23
    • 2018-09-10
    相关资源
    最近更新 更多