controller中重复代码是使用BaseController还是trait,或者?

1. 运行环境#

1). 当前使用的 Laravel 版本?#

Laravel 9

2). 当前使用的 php/php-fpm 版本?#

PHP 版本:
8.1

2. 问题描述?#

在多个 controller 中有大量重复代码,各位大佬是怎么操作的

代码已被折叠,点此展开

如上,这是一个简单的 curd 的控制器,其中各个方法的内容大部分都是可以复用的,
只有视图名、模型名有变化,请问如何优雅的处理这些重复的代码,而不用反复的复制粘贴,修改模型名称?
目前我直接考虑了两种,BaseController 或者 trait,大概逻辑如下:

class BaseController extends Controller
{
    protected $model ;
    protected $viewPath = '';
    /**
     * Display a listing of the resource.
     * @return View
     */
    public function index(): View
    {
        return view($this->viewPath . 'index')
            ->with('dicts', $this->model::dicts());
    }
}
trait Curd
{
    protected $model ;
    protected $viewPath = '';
    /**
     * Display a listing of the resource.
     * @return View
     */
    public function index(): View
    {
        return view($this->viewPath . 'index')
            ->with('dicts', $this->model::dicts());
    }
}
class TestController extends BaseController
{
    //不继承BaseController,使用trait
    //use Curd;
    protected $model ;
    protected $viewPath = '';
    public function __construct(Request $request)
    {
        $this->viewPath = 'test.';
        $this->model = Test::class;
    }
}

还有其他更优雅的处理方法吗?

《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
fatrbaby
最佳答案

你举例的重复代码,这两种解决方案都不太好。代码不仅包含 “复用” 问题,还包含 “职责” 问题。这两种方案代码是复用了,但职责不清了。这种情况个人觉得比较好的方法是使用脚手架生成 CRUD 代码。

但是 Spring 框架的创始人 Rod Johnson 说过:如果是能生成的代码为什么要生成它?

所以更好的方案是设计一套机制,类似于 Laravel 的 资源型控制器 机制来处理他。

2年前 评论
____Laravel (楼主) 2年前
fatrbaby (作者) 2年前
____Laravel (楼主) 2年前
fatrbaby (作者) 2年前
____Laravel (楼主) 2年前
讨论数量: 8
fatrbaby

你举例的重复代码,这两种解决方案都不太好。代码不仅包含 “复用” 问题,还包含 “职责” 问题。这两种方案代码是复用了,但职责不清了。这种情况个人觉得比较好的方法是使用脚手架生成 CRUD 代码。

但是 Spring 框架的创始人 Rod Johnson 说过:如果是能生成的代码为什么要生成它?

所以更好的方案是设计一套机制,类似于 Laravel 的 资源型控制器 机制来处理他。

2年前 评论
____Laravel (楼主) 2年前
fatrbaby (作者) 2年前
____Laravel (楼主) 2年前
fatrbaby (作者) 2年前
____Laravel (楼主) 2年前
fatrbaby

你举例的重复代码,这两种解决方案都不太好。代码不仅包含 “复用” 问题,还包含 “职责” 问题。这两种方案代码是复用了,但职责不清了。这种情况个人觉得比较好的方法是使用脚手架生成 CRUD 代码。

但是 Spring 框架的创始人 Rod Johnson 说过:如果是能生成的代码为什么要生成它?

所以更好的方案是设计一套机制,类似于 Laravel 的 资源型控制器 机制来处理他。

2年前 评论
____Laravel (楼主) 2年前
fatrbaby (作者) 2年前
____Laravel (楼主) 2年前
fatrbaby (作者) 2年前
____Laravel (楼主) 2年前
class MacroServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap services.
     * @return void
     */
    public function boot()
    {
        $this->registerRouteMacro();
    }

    public function registerRouteMacro()
    {
        if (!Route::hasMacro('curd')) {
            Route::macro('curd', function ($path, $model) {
                Route::get($path . '/index', function () use ($path, $model) {
                    $prefix = request()->route()->getPrefix();
                    $viewPath = str((filled($prefix) ? $prefix . '/' : '') . $path)
                        ->replace('/', '.')->trim('.');
                    return view($viewPath . '.index')
                        ->with('dicts', $model::dicts())
                        ->with('searchList', $model::dictAppends());
                });
                Route::post($path . '/data', function () use ($path, $model) {
                    list($where, $offset, $limit) = search_param(request());
                    $query = $model::extWhere($where);
                    $list = $query->skip($offset)->limit($limit)->get()
                               ->append($model::dictAppends());
                    return json($list, $query->count());
                });
            });
        }
    }
}

感谢 @fatrbaby 大佬 实现了,后续考虑加入一个控制器是否存在判断,如果存在控制器且存在控制器方法,优先使用控制器方法。

2年前 评论
九霄道长

trait 属于 has a 继承 属于 is a

2年前 评论