I have set of input fields to be validated. I have removed commas (since user enters comma as thousand separator) before validation takes place. But it still complains that the number is not numeric.
class UpdateFamilyExpense extends FormRequest
{
public function authorize()
{
return true;
}
public function sanitize()
{
$attributes = $this->all();
for ($i=1; $i<=15; $i++)
{
$attributes['e'.$i] = str_replace(',', '', $attributes['e'.$i]);
}
$this->replace($attributes);
}
public function rules()
{
$this->sanitize();
return [
'e1' => 'required|numeric',
];
}
public function messages()
{
return [
'e1.required' => 'required',
'e1.numeric' => 'must be a numeric',
];
}
}
I cannot figure out where I am wrong. Can someone help me figure out what I am missing here?
Override prepareForValidation as:
protected function prepareForValidation()
{
$this->sanitize();
}
Related
I've a simple code (more o less) like this.
Routes:
Route::post('car', 'CarController#store')->name('insert_car.store');
Route::post('car-italian', 'CarItalianController#store')->name('insert_car-italian.store');
Controllers:
class CarController extends Controller
{
public function store(StoreCarRequest $request)
{
return Car::create($request->validated()) // Calling 'car-italian' route, the code fails here!
}
}
class CarItalianController extends Controller
{
public function store(StoreCarItalianRequest $request)
{
$input_parameters = $request->validated();
$t = [
'model' => $input_parameters['modello'],
'door' => $input_parameters['porte'],
];
return (new CarController)->store(new StoreCarRequest($t));
}
}
Forms Request:
class StoreCarRequest extends FormRequest
{
public function rules()
{
return [
'model' => 'string',
'door' => 'integer'
];
}
}
class StoreCarItalianRequest extends FormRequest
{
public function rules()
{
return [
'modello' => 'string',
'porte' => 'integer'
];
}
}
When I call the route car-italian, It fails with message:
Call to a member function validated() on null
Can someone help me? I spent one full day on it :-/
Thank you
Ok, I've found a solution updating the Controller CarItalianController:
class CarController extends Controller
{
public function store(StoreCarRequest $request)
{
return Car::create($request->validated())
}
}
class CarItalianController extends Controller
{
public function store(StoreCarItalianRequest $request)
{
$input_parameters = $request->validated();
$t = [
'model' => $input_parameters['modello'],
'door' => $input_parameters['porte'],
];
$insertRequest = new StoreCarRequest();
$insertRequest->setValidator(Validator::make($t, $insertRequest->rules()));
return (new CarController)->store($insertRequest);
}
}
Client sends something like this:
foo.1.bar=hello
in my FormRequest class I have tried:
public function rules()
{
return [
'foo.1.bar' => 'string|nullable' // does not work
'foo' => 'array|nullable' // does not work
'foo' => [ // does not work
'1' => [
'bar' => 'string|nullable'
]
]
Any idea how to handle this?
Try getting the value of the parameter manually and then validating it:
class YourRequest extends FormRequest
{
public function rules(): array
{
return [...];
}
public function withValidator(Validator $validator): void
{
$value = $this->get('foo.1.bar') ?: $this->get('foo_1_bar');
$validator->after(function (Validator $validator) use ($value) {
if ($value == null) {
$validator->errors()->add('foo.1.bar', 'Error Message.');
$validator->errors()->add('foo_1_bar', 'Error Message.');
}
});
}
}
Can I set a default value to a not-existing field in a FormRequest in Laravel?
For example, if a field called "timezone" does not exist in the incoming request, it get set to "America/Toronto".
Well I wrote a trait for this, which checks a function called 'defaults' exist in the form request it will replace the default values
trait RequestDefaultValuesTrait {
protected function prepareForValidation(){
// add default values
if( method_exists( $this, 'defaults' ) ) {
foreach ($this->defaults() as $key => $defaultValue) {
if (!$this->has($key)) $this->merge([$key => $defaultValue]);
}
}
}
}
the thing that you need to do is adding this trait to FormRequest class and then add a function like this:
protected function defaults()
{
return [
'country' => 'US',
'language' => 'en',
'timezone' => 'America/Toronto',
];
}
Being honest I don't link this method, but It works.
Try this
if(!$request->has('timezone') {
$request->merge(['timezone' =>'America/Toronto']);
}
I'm not so sure if you need to do it in this way, but if you want to:
class CreateUpdateDataFormRequest extends Request
{
public function authorize()
{
return true;
}
public function rules()
{
return [];
}
protected function getValidatorInstance()
{
$data = $this->all();
if(!isset($data['timezone'])) {
$data['timezone'] = 'America/Toronto';
$this->getInputSource()->replace($data);
}
// modify data before sending to validator
return parent::getValidatorInstance();
}
in request class add
public function prepareForValidation()
{
$this->mergeIfMissing([
'timezone' => 'America/Toronto'
]);
}
i have a field that required, and can be 2 value type : String (path) and Image file
how can write validation rule for this ?
if value is string check file_exist and if is file must be image
thanks
Maybe there's an easier way to do this. However, I think a custom rule as such should work.
$validator = Validator::make($request->all(), [
'image' => [
'required',
function ($attribute, $value, $fail) {
if(is_file($value)) {
if (true !== mb_strpos($value->getMimeType(), "image")) {
return $fail($attribute.' is invalid.');
}
}
if (is_string($value)) {
if(! file_exists($value)) {
return $fail($attribute.' is invalid.');
}
}
},
],
]);
i found my answer with FormRequest
MyTestFormRequest
<?php
use Illuminate\Foundation\Http\FormRequest;
use Symfony\Component\HttpFoundation\File\UploadedFile;
class MyTestFormRequest extends FormRequest
{
public function rules()
{
$rules = [
"image" => ['required']
];
if(is_string($this->image)) {
$rules['image'][] = new FileExistsRule;
} else if($this->image instanceof UploadedFile) {
$rules['image'][] = 'image';
$rules['image'][] = 'dimensions:ratio=1/1';
}
return $rules;
}
}
FileExistsRule
<?php
use Illuminate\Contracts\Validation\Rule;
class FileExistsRule implements Rule
{
public function passes($attribute, $value)
{
return file_exists(public_path($value));
}
public function message()
{
return 'The file not exists';
}
}
i've question about adding some data outside form and send it with form data. Look! I have 3 fields ActiveForm:
name (text)
email (email)
course (hidden)
Ok, but i need to add one more named "status". I do not want to add hidden fields, just want to add inside controller or model.
How?
Controller:
public function actionFree()
{
$model = new SubscribeForm();
$this->view->title = "ШКОЛА ПИСАТЕЛЬСКОГО МАСТЕРСТВА: Новичок курс";
if ($post = $model->load(Yii::$app->request->post())) {
if ($model->save()) {
Yii::$app->session->setFlash('success', 'Данные приняты');
return $this->refresh();
}
else {
Yii::$app->session->setFlash('error', 'Ошибка');
}
}
else {
// страница отображается первый раз
return $this->render('free-course', ['model' => $model, 'course_id' => 1]);
}
}
Model:
class SubscribeForm extends ActiveRecord
{
public $fio;
public $email;
public $course;
public $status;
public static function tableName()
{
return 'users';
}
public function rules()
{
return [
// username and password are both required
[['fio', 'email'], 'required'],
[['email'], 'unique'],
['email', 'email'],
['email', 'safe']
];
}
}
You could just set the value in your controller, like this:
public function actionFree()
{
$model = new SubscribeForm();
$model->status = 'your-status-value';
// ... the rest of your code
Or you could add a default value in your model. This way you can still overrule the value from the controller or a form field, but will get this value when nothing else is supplied.
public function rules()
{
return [
['status', 'default', 'value' => 'your-default-status-value'],
// .. other rules
];
}