【问题标题】:Laravel 5 variable type hinting for requestsLaravel 5 请求的变量类型提示
【发布时间】:2015-05-04 16:09:04
【问题描述】:

我正在尝试为 Laravel 构建一个非常通用的 CRUD,但我卡在了验证上。

我有一个 RESTful 资源控制器,它将处理任何实体的基本操作:

class CrudController extends Controller {
  public function store(StoreRequest $request) {...}
  public function update(UpdateRequest $request) {...}
  ...
}

每个实际实体都有自己的控制器来扩展它,比如:

  • ArticleController 扩展 CrudController
  • CategoryController 扩展 CrudController
  • TagController 扩展 CrudController

所以当你在 ArticleController() 中调用 create() 方法时,它基本上会调用 CrudController::create()。

到目前为止一切顺利。现在是验证问题:

对于 Article 实体,我将在以下位置定义验证规则:

  • app/Http/Requests/StoreArticleRequest.php

  • app/Http/Requests/UpdateArticleRequest.php

但是请求的类已经在 CrudController 中定义了,所以 Laravel 将使用这些类进行类型提示,所以执行的验证将是来自 StoreRequest 的验证,而不是我想要一个,StoreArticleRequest

如何将这些类传递给 CrudController 中的 create()update() 方法?

不能:

我不想在ArticleController中重新定义create()方法,因为复制粘贴create()函数逻辑每个 EntityController 都会导致重复的代码。此外,它们会有不同的参数,这会触发“应该与”PHP 错误。

已经尝试过:

在 CrudController 中:

use App\Http\Requests\StoreCRUDRequest as StoreRequest;
use App\Http\Requests\UpdateCRUDRequest as UpdateRequest;

class CrudController extends Controller {
  public function store(StoreRequest $request) {...}
  public function update(UpdateRequest $request) {...}
  ...
}

在 ArticleController 中:

use App\Http\Requests\StoreArticleRequest as StoreRequest;
use App\Http\Requests\UpdateArticleRequest as UpdateRequest;

class ArticleController extends CrudController {
  ...
  // the create() and store() methods are no longer defined here
}

但它不起作用,因为 ArticleController Laravel 仍然从​​ CrudController 中定义的 App\Http\Requests\StoreCRUDRequest 运行验证。

知道如何实现这一点吗?

【问题讨论】:

  • 另一种理想的解决方案是在 CrudController 中基于变量定义 create 方法,例如: public function store({$store_request_type_name} $request) {}
  • StoreArticleRequest 可以从StoreCRUDRequest 扩展,通过这种方式,您可以在满足类型提示的每个孩子中注入请求类
  • 您找到解决方案了吗?偶然发现这个试图做类似的事情
  • 可悲的是,只有一些我不太自豪的事情:在子控制器中,我创建了一些新方法,它们调用父方法。所以在上面的例子中,ArticleController 有 createArticle(StoreRequest $request) 和 updateArticle(UpdateRequest $request),分别调用 parent::create() 和 parent::update()。不是很自豪……但它确实有效。如果你发现别的东西,请告诉我。这真的让我很烦。

标签: php laravel-5


【解决方案1】:

您可以使用resolve() 帮助器来解析FormRequest 类,而不是类型提示。请参阅第 33 行的 FormRequestServiceProviderhelper docs

abstract class CrudController extends Controller {

    protected $modelClassName;   # Name of your model class
    protected $storeRequest;     # Name of your store FormRequest class
    protected $updateRequest;    # Name of your update FormRequest class

    public function store(): Model {
        $modelClassName = $this->modelClassName;
        $request = resolve($this->storeRequest);
        $instance = $modelClassName::create($request->validated());
        return $instance;
    }

    public function update($id): Model {
        $modelClassName = $this->modelClassName;
        $instance = $modelClassName::find($id);
        $request = resolve($this->updateRequest);
        $instance->fill($request->validated())->save();
        return $instance;
    }

}

【讨论】:

    【解决方案2】:

    有什么理由反对将 Request 对象传递给构造函数并让 Laravel 在运行时注入它们?

    例子:

    <?php
    class ArticleController extends CrudController {
    
        use CreateOperation;
    
        public function __construct(StoreArticleRequest $storeRequest, UpdateArticleRequest $updateRequest)
        {
            $this->storeRequest  = $storeRequest;
            $this->updateRequest = $updateRequest;
    
            parent::__construct();
        }
    }
    
    
    trait CreateOperation
    {
        /**
         * @var Request
         */
        private $storeRequest;
    
        public function setStoreRequest(Request $storeRequest): void
        {
            $this->storeRequest = $storeRequest;
        }
    
        public function storeCrud()   // parameter removed
        {
            $request = $this->storeRequest;
    
            ...
            ...
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-09-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-21
      • 2019-08-10
      • 1970-01-01
      • 2010-12-20
      相关资源
      最近更新 更多