ユーザーが生年月日を更新できるフォームを処理しています。このフォームは、day
、month
、およびyear
の3つの個別のフィールドをユーザーに提供します。もちろんサーバー側では、これら3つの個別のフィールドを1つの値、つまりyyyy-mm-dd
として扱います。
したがって、データベースを検証および更新する前に、フォーム要求を変更して、year
、month
、およびday
をdate_of_birth
文字と連結して-
フィールドを作成し、日付形式を作成します。必要です(そして、おそらく元の3つのフィールドの設定を解除します)。
私のコントローラーでこれを手動で達成することは問題ではありません。入力を取得し、-
文字で区切られたフィールドを結合して設定解除するだけです。その後、処理を処理するコマンドに渡す前に、手動で検証できます。
ただし、FormRequest
を使用して検証を処理し、それをコントローラーメソッドに挿入することをお勧めします。したがって、検証を実行する前にフォームリクエストを実際に変更する方法が必要です。
同様の次の質問を見つけました: Laravel 5 Request-altering data
フォームリクエストのall
メソッドをオーバーライドして、検証前にデータを操作するためのロジックを含めることをお勧めします。
<?php namespace App\Http\Requests;
class UpdateSettingsRequest extends Request {
public function authorize()
{
return true;
}
public function rules()
{
return [];
}
public function all()
{
$data = parent::all();
$data['date_of_birth'] = 'test';
return $data;
}
これはすべて検証に適していますが、all
メソッドをオーバーライドしても、フォームリクエストオブジェクトのデータは実際には変更されません。そのため、コマンドの実行に関しては、フォームリクエストには変更されていない元のデータが含まれています。オーバーライドされたall
メソッドを使用してデータを引き出す場合を除きます。
特定のメソッドの呼び出しを必要としないフォームリクエスト内のデータを変更する、より具体的な方法を探しています。
乾杯
in laravel 5.1あなたはそれを行うことができます
<?php namespace App\Http\Requests;
class UpdateSettingsRequest extends Request {
public function authorize()
{
return true;
}
public function rules()
{
return [];
}
protected function getValidatorInstance()
{
$data = $this->all();
$data['date_of_birth'] = 'test';
$this->getInputSource()->replace($data);
/*modify data before send to validator*/
return parent::getValidatorInstance();
}
自分をいじってから、次のことを思いつきました。
app/Http/Requests/Request.php
<?php namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
abstract class Request extends FormRequest {
/**
* Override the initialize method called from the constructor to give subclasses
* an opportunity to modify the input before anything happens.
*
* @param array $query
* @param array $request
* @param array $attributes
* @param array $cookies
* @param array $files
* @param array $server
* @param null $content
*/
public function initialize(array $query = array(), array $request = array(), array $attributes = array(), array $cookies = array(), array $files = array(), array $server = array(), $content = null)
{
parent::initialize($query, $request, $attributes, $cookies, $files, $server, $content);
// Grab the input
$data = $this->getInputSource()->all();
// Pass it off to modifyInput function
$data = $this->modifyInput($data);
// Replace modified data back into input.
$this->getInputSource()->replace($data);
}
/**
* Function that can be overridden to manipulate the input data before anything
* happens with it.
*
* @param array $data The original data.
* @return array The new modified data.
*/
public function modifyInput(array $data)
{
return $data;
}
}
次に、クラスを拡張するときに、次のようにmodifyInput
メソッドをオーバーライドできます。
app/Http/Requests/TestRequest.php
<?php namespace App\Http\Requests;
class TestRequest extends Request {
public function authorize()
{
return true;
}
public function rules()
{
return [];
}
/**
* Modify the input.
*/
public function modifyInput(array $data)
{
$data['date_of_birth'] = 'something';
// Make sure to return it.
return $data;
}
}
これは私のニーズに合っているようです。この方法で行うことの欠点はわかりませんので、コメントや批評を歓迎します。
上記のShift Exchangeによる回答も問題なく機能します。
Laravel 5.4なので、FormRequestクラスでprepareForValidation
メソッドを使用できます。
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class StorePostRequest extends FormRequest
{
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'title' => 'required|max:200',
'body' => 'required',
'tags' => 'required|array|max:10',
'is_published' => 'required|boolean',
'author_name' => 'required',
];
}
/**
* Prepare the data for validation.
*
* @return void
*/
protected function prepareForValidation()
{
$this->merge([
'title' => fix_typos($this->title),
'body' => filter_malicious_content($this->body),
'tags' => convert_comma_separated_values_to_array($this->tags),
'is_published' => (bool) $this->is_published,
]);
}
}
より詳細な説明がここにあります: https://sampo.co.uk/blog/manipulating-request-data-before-performing-validation-in-laravel
私はこれがそうするための最良のアプローチだと思います: Laravel 5.1フォームリクエストの検証の前に入力を変更します
Laravel 5.4+では、このようなもの専用のメソッドがあるので、それを使用します:prepareForValidation
私はジュリア・ログビナと同様のアプローチを取りましたが、この方法は検証前にフィールドを追加/変更するためのわずかにエレガントな方法だと思います(Laravel 5.1)
_<?php
namespace App\Http\Requests;
use App\Http\Requests\Request;
class UpdateSettingsRequest 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 [];
}
/**
* Extend the default getValidatorInstance method
* so fields can be modified or added before validation
*
* @return \Illuminate\Contracts\Validation\Validator
*/
protected function getValidatorInstance()
{
// Add new data field before it gets sent to the validator
$this->merge(array('date_of_birth' => 'test'));
// OR: Replace ALL data fields before they're sent to the validator
// $this->replace(array('date_of_birth' => 'test'));
// Fire the parent getValidatorInstance method
return parent::getValidatorInstance();
}
}
_
これにより、デフォルトのgetValidatorInstance
が拡張されるため、バリデーターに到達する前にリクエストの入力値を変更できます(元の変更されていないデータの使用を防止します)。データが変更されると、元のgetValidatorInstance
が起動され、その後はすべてが通常どおり続行されます。
$this->replace(array())
または$this->merge(array())
のいずれかを新しいフィールドをリクエストに使用できます。上記のスニペットに両方を行う方法の例を含めました。
replace()
は、すべてのフィールドを指定した配列に置き換えます。
merge()
は、リクエストに新しいフィールドを追加します。
それでもall()
メソッドをオーバーライドしますが、次のように試してください
public function all()
{
$input = $this->all();
$input['date_of_birth'] = $input['year'].'-'.$input['month'].'-'.$input['day'];
$this->replace($input);
return $this->all();
}
次に、実際にはcallメソッドを使用しないでください-ルールを実行するときにバリデーター自体によって呼び出されます。
私もこれを達成するための迅速で汚い方法が必要でした。 The Shift Exchangesソリューションを使用したかったのですが、無限の再帰ループを作成する$this
の呼び出しが原因で機能しませんでした。代わりに親メソッドを参照するように簡単に変更すると、問題が修正されます。
public function all()
{
$input = parent::all();
$input['date_of_birth'] = $input['year'].'-'.$input['month'].'-'.$input['day'];
$this->replace($input);
return parent::all();
}
HTH他の人が必要です。