38

我想验证“表单请求”中的路由参数,但不知道该怎么做。

下面是代码示例,我正在尝试:

路线

// controller Server
Route::group(['prefix' => 'server'], function(){
    Route::get('checkToken/{token}',['as'=>'checkKey','uses'=> 'ServerController@checkToken']);
});

控制器

namespace App\Http\Controllers;


use App\Http\Controllers\Controller;

use Illuminate\Http\Request;
use App\Http\Requests;


class ServerController extends Controller {
    public function checkToken( \App\Http\Requests\CheckTokenServerRequest $request) // OT: - why I have to set full path to work??
        {   
            $token = Token::where('token', '=', $request->token)->first();      
            $dt = new DateTime; 
            $token->executed_at = $dt->format('m-d-y H:i:s');
            $token->save();

            return response()->json(json_decode($token->json),200);
        }
}

CheckTokenServerRequest

namespace App\Http\Requests;

use App\Http\Requests\Request;

class CheckTokenServerRequest extends Request {

        //autorization

        /**
         * Get the validation rules that apply to the request.
         *
         * @return array
         */
        public function rules()
        {

            return [
                'token' => ['required','exists:Tokens,token,executed_at,null']
            ];
        }

}

但是当我尝试验证一个简单的 url http://myurl/server/checkToken/222时,我得到了响应: no " token " parameter set

是否可以在单独的“表单请求”中验证参数,或者我必须在控制器中完成所有操作?

附言。对不起,我的英语不好。

4

10 回答 10

55

对于 Laravel < 5.5:
这样做的方法是重写all()方法,CheckTokenServerRequest如下所示:

public function all() 
{
   $data = parent::all();
   $data['token'] = $this->route('token');
   return $data;
}

编辑
Laravel >= 5.5:
上述解决方案适用于Laravel < 5.5。如果你想在Laravel 5.5 或更高版本中使用它,你应该使用:

public function all($keys = null) 
{
   $data = parent::all($keys);
   $data['token'] = $this->route('token');
   return $data;
}

反而。

于 2016-05-31T16:03:36.453 回答
14

覆盖all()Request 对象上的函数以自动将验证规则应用于 URL 参数

class SetEmailRequest
{

    public function rules()
    {
        return [
            'email'    => 'required|email|max:40',
            'id'       => 'required|integer', // << url parameter
        ];
    }

    public function all()
    {
        $data = parent::all();
        $data['id'] = $this->route('id');

        return $data;
    }

    public function authorize()
    {
        return true;
    }
}

注入请求后,像这样从控制器正常访问数据:

$setEmailRequest->email // request data
$setEmailRequest->id, // url data
于 2016-06-28T02:03:00.517 回答
9

如果您不想指定每个路由参数而只放置所有路由参数,您可以像这样覆盖:

Laravel < 5.5

public function all()
{
   return array_merge(parent::all(), $this->route()->parameters());
}

Laravel 5.5 或更高版本

public function all($keys = null)
{
   // Add route parameters to validation data
   return array_merge(parent::all(), $this->route()->parameters());
}
于 2017-03-07T22:20:52.210 回答
5

表单请求验证器用于验证通过POST方法发送到服务器的HTML 表单数据。最好不要将它们用于验证路由参数。路由参数主要用于从数据库中检索数据,因此为了确保您的令牌路由参数正确,请从

$token = Token::where('token', '=', $request->token)->first();

$token = Token::where('token', '=', $request->input(token))->firstOrFail();

firstOrFail() 是一个非常好的函数,如果用户插入任何无效令牌,它会向您的用户发送 404。

你得到no " token " parameter set是因为 Laravel 假设你的“令牌”参数是一个 POST 数据,在你的情况下它不是。

如果你坚持验证你的“令牌”参数,通过表单请求验证器你会减慢你的应用程序,因为你对你的数据库执行两个查询,一个在这里

$token = Token::where('token', '=', $request->token)->first();

和一个在这里

return [
            'token' => ['required','exists:Tokens,token,executed_at,null']
        ];

我建议使用firsOrFail同时进行验证检索

于 2016-06-02T19:08:18.887 回答
3

一个特征可以导致这个验证相对自动化。

特征

<?php

namespace App\Http\Requests;

/**
 * Class RouteParameterValidation
 * @package App\Http\Requests
 */
trait RouteParameterValidation{

    /**
     * @var bool
     */
    private $captured_route_vars = false;

    /**
     * @return mixed
     */
    public function all(){
        return $this->capture_route_vars(parent::all());
    }

    /**
     * @param $inputs
     *
     * @return mixed
     */
    private function capture_route_vars($inputs){
        if($this->captured_route_vars){
            return $inputs;
        }

        $inputs += $this->route()->parameters();
        $inputs = self::numbers($inputs);

        $this->replace($inputs);
        $this->captured_route_vars = true;

        return $inputs;
    }

    /**
     * @param $inputs
     *
     * @return mixed
     */
    private static function numbers($inputs){
        foreach($inputs as $k => $input){
            if(is_numeric($input) and !is_infinite($inputs[$k] * 1)){
                $inputs[$k] *= 1;
            }
        }

        return $inputs;
    }

}

用法

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class MyCustomRequest extends FormRequest{
    use RouteParameterValidation;

    /**
     * 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 [
            //
            'any_route_param' => 'required'//any rule(s) or custom rule(s)
        ];
    }
}
于 2017-07-10T22:22:42.847 回答
1

因为\App\Http\Requests\CheckTokenServerRequest您可以use App\Http\Requests\CheckTokenServerRequest;在顶部添加。
如果你通过tokenurl可以使用它就像一个变量在controller.

public function checkToken($token) //same with the name in url
{

    $_token = Token::where('token', '=', $token)->first();      
    $dt = new DateTime; 
    $_token->executed_at = $dt->format('m-d-y H:i:s');
    $_token->save();

    return response()->json(json_decode($token->json),200);
}
于 2016-06-07T09:26:27.993 回答
0

您只是缺少标记前的下划线。用。。。来代替

_token

无论您在哪里检查它与 laravel 生成的表单。

public function rules()
{

    return [
        '_token' => ['required','exists:Tokens,token,executed_at,null']
    ];
于 2016-06-07T15:02:35.127 回答
0
$request->merge(['id' => $id]);
...
$this->validate($request, $rules);

或者

$request->merge(['param' => $this->route('param')]);
...
$this->validate($request, $rules);
于 2019-03-20T19:19:43.667 回答
0

FormRequest 有一个方法validationData()来定义用于验证的数据。因此,只需在表单请求类中使用路由参数覆盖那个:

    /**
     * Use route parameters for validation
     * @return array
     */
    protected function validationData()
    {
        return $this->route()->parameters();
    }
于 2019-04-25T15:40:15.900 回答
0

或保留大部分all逻辑并覆盖input方法trait \Illuminate\Http\Concerns\InteractsWithInput

     /**
     * Retrieve an input item from the request.
     *
     * @param string|null $key
     * @param string|array|null $default
     * @return string|array|null
     */
    public function input($key = null, $default = null)
    {
        return data_get(
            $this->getInputSource()->all() + $this->query->all() + $this->route()->parameters(), $key, $default
        );
    }
于 2019-05-24T08:48:57.233 回答