I have this request:
GET http://example.com/test?q[]=1&q[]=2&q[]=3
And I have this route:
Route::get('test', function(Request $req) {
$req->validate(['q' => 'array']);
});
How should I do to add other validation rules to each element of this array using Laravel validator? For example, I want to check that each q value has a minimum of 2.
Thank you for your help.
Take a look at the documentation about validating arrays.
$validator = Validator::make($request->all(), [
'person.*.email' => 'email|unique:users',
'person.*.first_name' => 'required_with:person.*.last_name',
]);
You can also do this in your controller using the Request object, documentation about validation logic.
public function store(Request $request)
{
$validatedData = $request->validate([
'title' => 'required|unique:posts|max:255',
'body' => 'required',
]);
// The blog post is valid...
}
There is a third option for when you have a lot of validation rules and want to separate the logic in your application. Take a look at Form Requests
1) Create a Form Request Class
php artisan make:request StoreBlogPost
2) Add Rules to the Class, created at the app/Http/Requestsdirectory.
public function rules()
{
return [
'title' => 'required|unique:posts|max:255',
'body' => 'required',
];
}
3) Retrieve the request in your controller, it's already validated.
public function store(StoreBlogPost $request)
{
// The incoming request is valid...
// Retrieve the validated input data...
$validated = $request->validated();
}
You can do:
Route::get('test', function(Request $req) {
$req->validate([
'q' => 'array',
'q.*' => 'min:2'
]);
});
For more information on validation of arrays, see => laravel.com/docs/5.6/validation#validating-arrays
Suppose I got an array of users
users: [
{
"id": 1,
"name": "Jack",
},
{
"id": 2,
"name": "Jon"
}
]
I would validate it like below :
$request->validate([
'users[*]'=> [
"id" => ["integer", "required"],
"name" => ["string", "required"]
]
]);
Here * acts as a placeholder
Related
I have created a route with Api prefix
$routes->scope('/api', function (RouteBuilder $routes) {
$routes->setExtensions(['json']);
$routes->post(
'/add-categories',
['controller' => 'Miles', 'action' => 'addCategories','prefix'=>'Api']
);
}
I have created a controller file in directory Controller/Api/MilesController.php
I have created a addCategory method like below
public function addCategories()
{
$categoriesTable = $this->fetchTable('Categories');
$categoryEnt = $categoriesTable->newEmptyEntity();
if ($this->request->is('post')) {
$category = $categoriesTable->patchEntity($categoryEnt, $this->request->getData());
if ($categoriesTable->save($category)) {
$responseBody = [
'status' => 201,
'data' => $category
];
}else{
$responseBody = [
'status' => 400,
'data' => $category->getErrors()
];
}
}
$this->set(compact('responseBody'));
$this->viewBuilder()->setOption('serialize', ['responseBody']);
}
In postman if I try to send a post request without any data , then I getting the response like below
{
"responseBody": {
"status": 201,
"data": {
"created": "2022-05-10T20:04:13+09:00",
"modified": "2022-05-10T20:04:13+09:00",
"id": 8
}
}
}
My Model/Table/CategoriesTable.php looks like
<?php
declare(strict_types=1);
namespace App\Model\Table;
use Cake\ORM\Query;
use Cake\ORM\RulesChecker;
use Cake\ORM\Table;
use Cake\Validation\Validator;
class CategoriesTable extends Table
{
public function initialize(array $config): void
{
parent::initialize($config);
$this->setTable('categories');
$this->setDisplayField('name');
$this->setPrimaryKey('id');
$this->addBehavior('Timestamp');
$this->hasMany('Products', [
'foreignKey' => 'category_id',
]);
}
public function validationDefault(Validator $validator): Validator
{
$validator
->allowEmptyString('id', null, 'create');
$validator
->scalar('title')
->notEmptyString('title');
$validator
->boolean('status')
->notEmptyString('status');
$validator
->scalar('imageUrl')
->allowEmptyFile('imageUrl');
return $validator;
}
}
Why my notEmptyString validation not working which I have written in CategoriesTable.php file ?
Note : This Api/MilesController.php has no self model. How can I apply CategoriesTable validation here ?
None of your fields are set as being required, ie they are all optional, and when an optional field is missing, no validation rules will be applied.
So for all fields that must be present, use requirePresence(), for example:
$validator
->requirePresence('title', 'create') // required on create, optional on update
->scalar('title')
->notEmptyString('title');
See also
Cookbook > Validation > Creating Validators > Requiring Field Presence
it's me again. I have a problem saving data to the database from the input form that I made.
Here is my web route:
Route::get('/admin/data-karyawan', [BasicKaryawanController::class, 'data_karyawan']);
Route::get('/admin/create', [BasicKaryawanController::class, 'index']);
Route::post('/admin/create', [BasicKaryawanController::class, 'simpan']);
Here is my controller:
class BasicKaryawanController extends Controller
{
public function data_karyawan()
{
return view('data-karyawan', [
"title" => "Data Karyawan",
"karyawan" => Karyawan::with(['role', 'user'])->search(request(['search']))->paginate(10)
]);
}
public function index()
{
return view('create', [
"title" => "Tambah Karyawan"
]);
}
public function simpan(Request $request)
{
$validatedData = $request->validate([
'nik' => 'required|max:7',
'nama' => 'required|max:255',
'jk' => 'required|max:1',
'tempat_lahir' => 'required|max:255',
'tanggal_lahir' => 'required|max:255',
'alamat' => 'required|max:255',
'agama' => 'required',
'jabatan' => 'required|max:255',
'id_jabatan' => 'required|max:1',
'divisi' => 'required',
'email' => 'required|email:dns|unique:karyawans',
'password' => 'required|min:5|max:255'
]);
$validatedData['password'] = bcrypt($validatedData['password']);
Karyawan::create($validatedData);
return view('data-karyawan', [
"title" => "Data Karyawan",
"karyawan" => Karyawan::with(['role', 'user'])->search(request(['search']))->paginate(10)
]);
}
and this is my form blade view:
https://codeshare.io/3AzKD1
The code is running well but the form is not saving the data I input from the form to the database. Did I miss something?
Thank you.
This is solved.
I need to fill all the field on the table so it can store to the database.
Yes right, if u r using eloquent create method which accepts an array of attributes, creates a model, and inserts it into the database. The difference between save and create is that save accepts a full Eloquent model instance while create accepts a plain PHP array.
U can take the reference from here
I have an array that makes in front end with js and pass that to my controller with ajax.
Ajax:
var values = [{FirstName: "fff"},{LastName: null}]
$.ajax({
method: "POST",
url: "/api/store-step",
data: { values: values, step: activePanelNum }
}).fail(function (jqXHR, textStatus, error,result) {
console.log(jqXHR.responseJSON.errors);
}).done(function( result ) {
console.log(result);
});
structure of array is this:
[{FirstName: "fff"},{LastName: null}]
Controller:
public function storeSteps(Request $request)
{
$validator = Validator::make($request->values, [
'FirstName' => 'required',
'LastName' => 'required',
]);
if ($validator->fails()) {
return response()->json(['success'=>false, 'errors' => $validator->getMessageBag()->toArray()],422);
}
}
I can't validate this array with request validation Laravel. Now I'm going to turn this array into a Larval request to apply the rules to it.
Can any one helps?
you can validate array element like this
$validator = Validator::make($request->all(), [
'values' => 'required',
'values.*.FirstName' => 'required',
'values.*.lastName' => 'required','
]);
by using . you can access an index in a array and * apples all indexes in the array.
I am validating an array in Laravel 5.7 but the validator passes when I expect it to fail.
$validator = Validator::make($request->all(), [
'user_reg_email' => 'required|max:255|email|exists:users,email',
'service_start_date' => 'required|before_or_equal:today',
'service_end_date' => 'nullable|after:service_start_date',
'role' => 'array|min:1|unique:provider_user,role,NULL,id,user_email,' . $request->user_reg_email . ',provider_domain,' . $request->prov,
]);
The payload is as below:
{
_token: "d5VYhirRAn3Zb9bCKHKQiuLNXkHfEP4hEs0bAZvj",
prov: "email.com",
user_reg_email: "john#email.com",
service_start_date: "2019-03-03",
service_end_date: null,
role: [
null
],
}
The role validation passes but I expect it to fail. How do I get the expected results?
'role' => 'array,...' will validate that the role field is an array, which it is.
To validate the items within the array, you also need to include this rule:
'role.*' => unique:provider_user,...
Take this request data:
HTTP PUT
[
'id' => 1,
'company' => 'Company Name',
'attributes' => [
[
'attribute' => 'url',
'value' => 'example1.com'
],
[
'attribute' => 'url',
'value' => 'example2.com'
],
]
]
I want to build a form that validates attributes using choice loaders:
public function buildForm(FormBuilderInterface $builder, array $options): void
{
parent::buildForm($builder, $options);
$builder->add(
$builder->create('attributes', FormType::class, [
'compound' => true
])
);
$builder->get('attributes')
->add('attribute', ChoiceType::class, [
'constraints' => [
new NotBlank([
'message' => 'attribute name cannot be blank.'
])
],
'choices' => [
'url',
'type',
'email',
'date',
],
])
->add('value', TextType::class)
;
}
However when i write my unit test for this:
public function testAttributesForm(array $data)
{
$form = $this->factory->create(AttributesType::class);
$form->submit($data);
if(!$form->isValid()) {
var_dump($form->getErrors()->current()->getMessage());
}
}
I get a failed validation:
string(42) "This form should not contain extra fields."
Which is because it finds a nested array instead of the actual fields.
How do I pass nested data in a way where I can fully use validation constraints?
In the past I used CollectionType::class with 'allow_add' => true but it doesn't allow for very detailed validation.
You should try use directive
'allow_extra_fields' => true
To be able to validate nested data without a data_class using Forms (as you may when writing an api) you need to add a form per collection dynamically, in this case:
The first form builder method would look like this:
class CompanyType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('id', IntegerType::class)
->add('company', TextType::class)
;
$builder->add(
$builder->create('companyAttributes', CollectionType::class, [
'allow_extra_fields' => true
])
);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'csrf_protection' => false,
]);
}
}
and the second would also be a standalone form:
class CompanyAttributeType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('value',TextType::class)
->add('attribute',TextType::class, [
'constraints' => [
new NotBlank([
'message' => 'Parameter name cannot be blank.'
])
],
])
;
}
}
When the request is sent, you would create the first and add the second form in a loop.
Notice the loop's $key is used for the form name so you can do $form->get(1) etc.
$form = $this->factory->create(CompanyType::class);
if(!empty($data['attributes'])) {
foreach ($data['attributes'] as $key => $parameters) {
$form->get('companyAttributes')->add($key, CompanyAttributeType::class);
}
}
$form->submit($data);
if($form->isSubmitted() && $form->isValid()) {
//2xx response
} else {
//4xx/5xx response
}
This setup will validate all forms when $form->submit($data) is called.