Laravel 5 how to validate route parameters?

折月煮酒 提交于 2019-12-02 18:03:17

The way for this is overriding all() method for CheckTokenServerRequest like so:

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

EDIT

Above solution works in Laravel < 5.5. If you want to use it in Laravel 5.5 or above, you should use:

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

instead.

Override the all() function on the Request object to automatically apply validation rules to the URL parameters

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;
    }
}

Access the data normally from the controller like this, after injecting the request:

$setEmailRequest->email // request data
$setEmailRequest->id, // url data

The form request validators are used for validating HTML form data that are sent to server via POST method. It is better that you do not use them for validating route parameters. route parameters are mostly used for retrieving data from data base so in order to ensure that your token route parameter is correct change this line of your code, from

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

to

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

firstOrFail() is a very good function, it sends 404 to your user, if the user insert any invalid token.

you get no " token " parameter set because Laravel assumes that your "token" parameter is a POST data which in your case it is not.

if you insist on validating your "token" parameter, by form request validators you gonna slow down your application, because you perform two queries to your db, one in here

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

and one in here

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

I suggest to use firsOrFail to do both validating and retrieving at once.

A trait can cause this validation to be relatively automagic.

Trait

<?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;
    }

}

Usage

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)
        ];
    }
}
mk_

If you dont want to specify each route param and just put all route params you can override like this:

Laravel < 5.5:

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

Laravel 5.5 or above:

public function all($keys = null)
{
   // Add route parameters to validation data
   return array_merge(parent::all(), $this->route()->parameters());
}

For \App\Http\Requests\CheckTokenServerRequest you can add use App\Http\Requests\CheckTokenServerRequest; at the top.
If you pass the token by url you can use it likes a variable in 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);
}

You just missing the underscore before token. Replace with

_token

wherever you check it against the form generated by laravel.

public function rules()
{

    return [
        '_token' => ['required','exists:Tokens,token,executed_at,null']
    ];
$request->merge(['id' => $id]);
...
$this->validate($request, $rules);

or

$request->merge(['param' => $this->route('param')]);
...
$this->validate($request, $rules);

FormRequest has a method validationData() that defines what data to use for validation. So just override that one with route parameters in your form request class:

    /**
     * Use route parameters for validation
     * @return array
     */
    protected function validationData()
    {
        return $this->route()->parameters();
    }

or leave most of the all logic in place and override input method from 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
        );
    }
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!