【问题标题】:Parent Controller class to call child overridden methods (Laravel)父控制器类调用子覆盖方法(Laravel)
【发布时间】:2021-09-12 08:56:52
【问题描述】:

我知道这可能看起来很反常,很多人会向我扔石头,但请听我说完。

我想创建一个通用控制器来支持许多引用表(主要是 id、label)。所以我做了这样的事情:

class GenericController extends Controller
{
    public function index($modelName)
    {
        $x = '\\App\\Models\\'.$modelName;
        $data = $model->all();
        return view('generic.list', ['model'=>$model, 'data'=>$data]);
    }
}

这样我在web.php 的路线将减少到最小,如下所示:

//List
Route::get('/{model}', function ($model) {
    return App::call('\App\Http\Controllers\GenericController@index', ['modelName' => $model]);
});

它与存储、更新等简单的 CRUD 操作配合得非常好。但是我知道我过度简化了设计,因为有时我需要从索引列表中的连接表中返回一个字段。这就是我走向死胡同的地方,有点。

我的第一个想法是为每个继承自 GenericController 的模型创建一个控制器,如下所示:

class CategoryController extends GenericController
{
}

每当我需要重写 GenericController 方法时,我只需将它添加到子类中即可。但是,如何从 GenericController 内部执行此操作(从父类调用子类中的方法)?因为否则我将不得不为每个模型创建路线,这违背了我的意愿。

所以基本上我正在寻找这样的东西:

class GenericController extends Controller
{
    public function index($modelName)
    {
        $x = '\\App\\Models\\'.$modelName;            
        //this thing I'm looking for is something like this:
        //Check if we have CategoryController and it has a definition for index
        //if yes do something like $data = CategoryController->index();
        //otherwise just call $data = $model->all();
        return view('generic.list', ['model'=>$model, 'data'=>$data]);
    }
}

所以我知道这看起来很奇怪和反模式,但除此之外,我该如何创建我的通用路由和控制器操作?

【问题讨论】:

    标签: laravel oop design-patterns subclassing


    【解决方案1】:

    你是对的,这并不是所谓的“最佳实践”。但是,从 POO 的角度来看,这是一个有趣的问题。

    这是你可以做的:

    class GenericController extends Controller
    {
        protected function getData(string $model)
        {
            return $model::all();
        }
    
        public function index($modelName)
        {
            $model = '\\App\\Models\\'.$modelName;  
              
            $data = $this->getData($model);
    
            return view('generic.list', ['model'=>$model, 'data'=>$data]);
        }
    }
    

    默认情况下,将使用“简单方式”检索数据,使用$data = $this->getData($model);

    但是,如果您创建 CategoryController:

    class CategoryController extends GenericController
    {
        protected function getData(string $model)
        {
            return Category::query()->with('something')->where('hello','world')->get();
        }
    }
    

    您只需要覆盖CategoryController 中的getData 方法。

    如果您想要干净的东西,这就是要走的路。当然,您的categories 路由必须使用CategoryController 而不是GenericController

    【讨论】:

    • 谢谢,我希望避免为已实现的控制器添加路由并控制通用控制器及其路由的所有内容。到目前为止,我的解决方案是从 GenericController->getData() 方法内部启动 CategoryController。
    • 你可以这样做,从技术上讲它会起作用,但它是在 Laravel 反模式之上添加 POO 反模式......不理想:p
    • 我明白了,这都是为了大项目的抽象和快速开发。
    猜你喜欢
    • 2017-11-11
    • 2020-05-15
    • 2017-11-18
    • 1970-01-01
    • 2018-03-18
    • 2014-05-11
    • 1970-01-01
    • 2020-11-04
    • 1970-01-01
    相关资源
    最近更新 更多