Je veux valider les paramètres de l'itinéraire dans la "demande de formulaire" mais je ne sais pas comment le faire.
Voici l'exemple de code, j'essaie avec:
Route
// controller Server
Route::group(['prefix' => 'server'], function(){
Route::get('checkToken/{token}',['as'=>'checkKey','uses'=> 'ServerController@checkToken']);
});
Contrôleur
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']
];
}
}
Mais quand j'essaye de valider une simple URL http: // myurl/server/checkToken/222 , j'obtiens la réponse: no " token " parameter set
.
Est-il possible de valider les paramètres dans une "demande de formulaire" séparée, ou dois-je tout faire dans un contrôleur?
ps. Désolé pour mon mauvais anglais.
La manière pour cela est de remplacer la méthode all()
pour CheckTokenServerRequest
comme ceci:
public function all()
{
$data = parent::all();
$data['token'] = $this->route('token');
return $data;
}
MODIFIER
La solution ci-dessus fonctionne en Laravel <5.5. Si vous souhaitez l'utiliser dans Laravel 5.5 ou supérieur, vous devez utiliser:
public function all($keys = null)
{
$data = parent::all($keys);
$data['token'] = $this->route('token');
return $data;
}
au lieu.
Remplacez la fonction all()
sur l'objet Request pour appliquer automatiquement des règles de validation aux paramètres d'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;
}
}
Accédez aux données normalement depuis le contrôleur comme ceci, après avoir injecté la requête:
$setEmailRequest->email // request data
$setEmailRequest->id, // url data
Les validateurs de demande de formulaire sont utilisés pour valider données de formulaire HTML qui sont envoyées au serveur via méthode [~ # ~] post [~ # ~]. Il est préférable de ne pas les utiliser pour valider les paramètres de l'itinéraire. les paramètres de route sont principalement utilisés pour récupérer les données de la base de données, afin de vous assurer que votre paramètre de route de jeton est correct, changez cette ligne de votre code
$token = Token::where('token', '=', $request->token)->first();
à
$token = Token::where('token', '=', $request->input(token))->firstOrFail();
firstOrFail () est une très bonne fonction, il envoie 404 à votre utilisateur, si l'utilisateur insère un jeton non valide.
vous obtenez no " token " parameter set
parce que Laravel suppose que votre paramètre "token" est une donnée POST qui ne l'est pas dans votre cas).
si vous insistez pour valider votre paramètre "token", par les validateurs de demande de formulaire, vous allez ralentir votre application, car vous effectuez deux requêtes sur votre base de données, une ici
$token = Token::where('token', '=', $request->token)->first();
et un ici
return [
'token' => ['required','exists:Tokens,token,executed_at,null']
];
Je suggère d'utiliser firsOrFail pour faire à la fois validation et récupération à la fois.
Un trait peut rendre cette validation relativement automagique.
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)
];
}
}
Si vous ne souhaitez pas spécifier chaque paramètre de route et simplement mettre tous les paramètres de route, vous pouvez remplacer comme ceci:
public function all()
{
return array_merge(parent::all(), $this->route()->parameters());
}
Pour \App\Http\Requests\CheckTokenServerRequest
vous pouvez ajouter use App\Http\Requests\CheckTokenServerRequest;
au sommet.
Si vous passez le token
par url
vous pouvez l'utiliser comme une variable dans 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);
}
$request->merge(['id' => $id]);
...
$this->validate($request, $rules);
ou
$request->merge(['param' => $this->route('param')]);
...
$this->validate($request, $rules);
ou laissez la plupart de la logique all
en place et remplacez la méthode input
de 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
);
}
FormRequest possède une méthode validationData()
qui définit les données à utiliser pour la validation. Il suffit donc de remplacer celui-ci avec les paramètres de route dans votre classe de demande de formulaire:
/**
* Use route parameters for validation
* @return array
*/
protected function validationData()
{
return $this->route()->parameters();
}
Vous venez de manquer le trait de soulignement avant le jeton. Remplacer par
_jeton
partout où vous le comparez au formulaire généré par laravel.
public function rules()
{
return [
'_token' => ['required','exists:Tokens,token,executed_at,null']
];