Laravel 5.1当一个方法需要字段而另一个方法不需要字段时,如何对两个方法使用相同的表单请求规则


Laravel 5.1 How to use the same form request rules for two methods when a field is required in one but not in the other method?

我有一个包含3个文件输入字段的表单,用户应该至少上传一个文件。我有一个表单请求,我在其中验证它们如下:

public function rules()
    {
     $this->prepInput();
        return [
            'comment' => 'max:2000',
            'source' => 'different:target',
            'file1'=>'required_without_all:file2,file3|between:1,15360|mimes:txt,pdf',
            'file2'=>'required_without_all:file1,file3|between:1,15360|mimes:txt,pdf',
            'file3'=>'required_without_all:file1,file2|between:1,15360|mimes:txt,pdf'
        ];
    } 

为了更新相同的表单,我在控制器中使用update方法,这与store方法几乎相同。唯一的区别是更新表单中不需要文件。有没有办法将相同的表单请求与storeupdate方法一起使用,并选择性地应用所需的规则?

我基本上为两个请求都使用了一个抽象基类,然后在子类中添加任何所需的规则。这将保留DRY,并为添加规则提供了一种灵活的方式。例如:

abstract class CompanyBaseRequest extends FormRequest
{
    ...
    public function rules()
    {
        return [
            'name' => ['required', 'string', 'max:255'],
            'category_id' => ['required', 'exists:company_categories,id'],
            'short_description' => ['required', 'string', 'max:2000'],
            'video' => ['nullable', 'file', 'mimes:mp4', 'max:30000'],
        ];
    }
}

然后是两个子类:

class CompanyStoreRequest extends CompanyBaseRequest
{
    ...
    public function rules()
    {
        return array_merge(parent::rules(), [
            'logo' => ['required', 'file', 'mimes:png,jpg,jpeg', 'max:1024'],
        ]);
    }
}
class CompanyUpdateRequest extends CompanyBaseRequest
{
    ...
    public function rules()
    {
        return array_merge(parent::rules(), [
            'logo' => ['nullable', 'file', 'mimes:png,jpg,jpeg', 'max:1024'],
        ]);
    }
}

您应该在需要的地方使用其中一个子类,它们都将包含基类中的规则和它们自己的规则。

这比公认的答案要好,因为表格本身明确地说明了他们以自己的名义做什么,而不仅仅适用于一个条件(不清楚他们检查了什么(。

由于您正在使用方法$this->prepInput();,我建议您更改一点代码以重用。

  1. 您必须为两个路由创建命名路由create&编辑我想你正在使用足智多谋的路由
  2. 更改您的代码,如下面的

    public function isEditRequestCalled()
    {
      return app('router')->getCurrentRoute()->getName() == 'YOUR_EDIT_ROUTE_NAME';
    }
    

在你的请求方法中,你会像这样改变

    public function rules()
    {
      $this->prepInput();
      return $this->isEditRequestCalled() ? [
        //YOUR EDIT RULES GOES HERE
      ] : [//YOUR CREATE RULES GOES HERE
        'comment' => 'max:2000',
        'source' => 'different:target',
        'file1'=>'required_without_all:file2,file3|between:1,15360|mimes:txt,pdf',
        'file2'=>'required_without_all:file1,file3|between:1,15360|mimes:txt,pdf',
        'file3'=>'required_without_all:file1,file2|between:1,15360|mimes:txt,pdf'
      ];
    }

我使用了以下技巧并成功了:

 public function rules()
    {
    $this->prepInput();
        $rules= [
            'comment' => 'max:2000',
            'source' => 'different:target',
            'file1'=>'required_without_all:file2,file3|between:1,15360|mimes:txt,pdf',
            'file2'=>'required_without_all:file1,file3|between:1,15360|mimes:txt,pdf',
            'file3'=>'required_without_all:file1,file2|between:1,15360|mimes:txt,pdf'
        ];
        if($this->myprojects){
            $rules['file1'] = 'between:1,15360|mimes:txt,pdf';
            $rules['file2'] = 'between:1,15360|mimes:txt,pdf';
            $rules['file3'] = 'between:1,15360|mimes:txt,pdf';
        }
          return  $rules;
    }

这里我的路线信息如下:

myprojects/{myprojects}/edit | myprojects.edit | App'Http'Controllers'MyProjectsController@edit

所以我的myprojects实体的id是$this->myprojects。如果它为空,它将创建一个myprojects,如果它有一个值,它将更新相应的myprojects

我使用单独的Rule类,它们基本上只存储我在FormRequest类中使用和重用所需的$rules$messages

class RulePrep
{
    /**
     * @var array
     */
    public $rules = [];
    /**
     * @var array
     */
    public $messages = [];
}
class RuleProjects
{
    /**
     * @var array
     */
    public $rules = [];
    /**
     * @var array
     */
    public $messages = [];
}

你可以试试吗?您需要单独的FormRequest类,但它可能比所有绑定到一个带有条件逻辑的类中更整洁。