Php 控制器中的验证

Php 控制器中的验证,php,validation,unit-testing,laravel,Php,Validation,Unit Testing,Laravel,我对Laravel很陌生,我需要一些重构代码的帮助。 现在,100%的测试中并没有包括该方法,因为我无法模拟验证器对象及其响应。 我有下面的方法 public function store(Request $request) { $data = $request->only([ 'name', 'email', 'message', ]); $validator = Validator::make($data, $t

我对Laravel很陌生,我需要一些重构代码的帮助。 现在,100%的测试中并没有包括该方法,因为我无法模拟验证器对象及其响应。 我有下面的方法

public function store(Request $request)
{
    $data = $request->only([
        'name',
        'email',
        'message',
    ]);

    $validator = Validator::make($data, $this->validatorRules);

    if ($validator->fails()) {
        return $this->response->errorFromValidator($validator);
    }

    $savedItem = $this->repository->store($data);

    if (!$savedItem) {
        return $this->response->error('Cannot save');
    }

    return $this->response->succesItem($savedItem);
}
我尝试在控制器的构造函数中插入验证器:

function __construct(Response $response, Repository $repository, Validator $validator)
{
    $this->response = $response;
    $this->repository = $repository;
    $this->validator= $validator;
}
并在方法中使用它:

$this->validator::make($data, $this->validatorRules);
但我得到了语法错误,意外的“:”(T_PAAMAYIM_NEKUDOTAYIM)。
如何在方法之外抽象验证器,以便在测试中模拟验证器?

为什么要使用验证器验证数据

  • 使用请求将保持控制器干净且最小。但有些 在控制器中使用验证器是明智的,例如,您知道 只有一个字段需要验证,那么它就是 使用FormRequest的技巧过火了。因此,这是一个偏好的问题
  • 请求类是验证请求的更好方法,因为它们 帮助从构造函数方法提取此功能,该方法 应该尽可能干净
我建议您使用请求来验证表单数据,而不是在控制器中使用验证器。从您的代码中,我可以注意到您正在尝试保存联系人表单,因此我的建议如下:

运行此命令,将在“请求”文件夹中创建ContactRequest文件:

ContactRequest文件:

<?php

namespace App\Http\Requests;

use App\Http\Requests\Request;

class ContactRequest extends Request
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
            'name' => 'required|min:5|max:20|alpha',
            'email' => 'required|email',
            'message' => 'required|max:250'
        ];
    }
}
在视图文件中,您可以处理如下错误:

    @if (count($errors) > 0)
        <div class="alert alert-danger">
        <button class="close" data-close="alert"></button>
                @foreach ($errors->all() as $error)
                    <span>{{ $error }}</span>
                @endforeach
        </div>
    @endif
{!! $errors->first('name', '<small class="help-block">:message</small>') !!}
{!! $errors->first('email', '<small class="help-block">:message</small>') !!}
{!! $errors->first('message', '<small class="help-block">:message</small>') !!}
@if(计数($errors)>0)
@foreach($errors->all()作为$error)
{{$error}}
@endforeach
@恩迪夫
或者,如果您喜欢逐个显示错误,您可以这样做:

    @if (count($errors) > 0)
        <div class="alert alert-danger">
        <button class="close" data-close="alert"></button>
                @foreach ($errors->all() as $error)
                    <span>{{ $error }}</span>
                @endforeach
        </div>
    @endif
{!! $errors->first('name', '<small class="help-block">:message</small>') !!}
{!! $errors->first('email', '<small class="help-block">:message</small>') !!}
{!! $errors->first('message', '<small class="help-block">:message</small>') !!}
{!!$errors->first('name',':message')
{!!$errors->first('email',':message')
{!!$errors->first('message',':message')
只有通过ContactRequest验证数据时,才会存储数据


现在,您的方法应该包含在测试中,您可以注意到控制器变得多么干净。

如果您以这种方式实例化验证器类,则不需要使用

使用
$this->validator->make($data,$this->validatorRules)

顺便提一下,为什么要嘲笑你的验证?它是纯代码,不涉及外部服务,因此您应该考虑让这些验证规则在测试期间运行

您不能执行
$this->validator::make
,它是一个对象,而不是一个类。。。因此,您应该做一些更像
$this->validator=validator::make
的事情。我喜欢使用自定义请求类的方法。控制器的确更干净。但我正在开发的不是一种联系方式。字段的名称只是一个例子(它们具有误导性)。我正在开发RESTAPI应用程序,我没有准备任何视图。我已经准备了一些
response
类,它有
errorFromValidator
方法:
return$this->response->errorFromValidator($validator)我在
$validator->fails()时使用它。该方法将HTTP Repsonse设置为“400:Bad request”,并显示来自验证程序的错误。如何使用您的方法从验证器传递错误?