Я обрабатываю форму, в которой пользователь может обновить дату своего рождения. Форма дает пользователю 3 отдельных поля для day
, month
и year
. Конечно, на стороне сервера я хочу рассматривать эти 3 отдельных поля как одно значение, т. yyyy-mm-dd
.
Поэтому перед проверкой и обновлением моей базы данных я хочу изменить запрос формы, чтобы создать поле date_of_birth
year
, month
и day
с символами -
для создания date_of_birth
формата даты (и, возможно, отмените исходные 3 поля).
Достижение этого вручную с помощью моего контроллера не является проблемой. Я могу просто захватить входные данные, соединить поля, разделенные символами, и отключить их. Затем я могу выполнить проверку вручную, прежде чем передавать команду на обработку.
Тем не менее, я бы предпочел использовать FormRequest
для проверки валидации и FormRequest
в мой метод контроллера. Поэтому мне нужен способ фактического изменения запроса формы до выполнения проверки.
Я нашел следующий вопрос, который аналогичен: Laravel 5 Запрос – изменение данных
Он предлагает переопределить 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
метода фактически не изменяет данные на объекте запроса формы. Поэтому, когда дело доходит до выполнения команды, запрос формы содержит исходные немодифицированные данные. Если я не использую теперь переопределенный метод, чтобы вытащить данные.
Я ищу более конкретный способ изменения данных в моем запросе формы, который не требует вызова определенного метода.
ура
в 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(); }
После некоторого беспорядка вокруг себя я придумал следующее:
приложение / HTTP / Запросы / 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
следующим образом:
приложение / HTTP / Запросы / 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; } }
Это, похоже, работает для моих нужд. Я не уверен в каких-либо недостатках в этом, поэтому я приветствую любые комментарии / критику.
Ответ, данный The Shift Exchange выше, также будет работать отлично.
Вы все же переопределите метод all()
но попробуйте его как это
public function all() { $input = $this->all(); $input['date_of_birth'] = $input['year'].'-'.$input['month'].'-'.$input['day']; $this->replace($input); return $this->all(); }
Тогда вы фактически не вызываете метод самостоятельно – он будет вызываться самим валидатором при выполнении правил.
Я применил аналогичный подход к Julia Logvina, но я думаю, что этот способ – несколько более элегантный способ добавления / изменения полей перед валидацией (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()
добавит новое поле в ваш запрос.
Я думаю, что это лучший подход для этого: Laravel 5.1 Изменить входные данные перед проверкой запроса формы
В Laravel 5.4+ существует специальный метод для подобных вещей, поэтому используйте его: prepareForValidation
Мне тоже нужен был быстрый и грязный способ сделать это. Я хотел использовать решение 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 другие нуждаются.