Laravel 5.5 validating hasMany relationship - php

How can I create a validation on a hasMany relationship
That is my Product model
public function produtoAtributos(){
return $this->hasMany("App\ProdutoAtributo", "produto_id", 'id')->latest();
}
and in Controller I fill the inputs than save it
$produtoatributos = $model->produtoAtributos()->getModel();
$produtoatributos->tipo = $produtoAtributo['tipo'];
$model->produtoAtributos()->save($produtoatributos);
The form input looks like this
<input name="ProdutoAtributos[0]['tipo']" />
How can add a validation for the relationship?

Laravel provide a nice way to validate arrays inpputs.
Here is an example
$validator = Validator::make($request->all(), [
'ProdutoAtributos.*.tipo' => 'required',
]);
You can read more about it here
https://laravel.com/docs/5.6/validation#validating-arrays

Related

How to add pivot table when inserting data to database in Laravel 8

maybe someone know how to insert pivot table in Laravel 8 automatically every i insert counselings table?
I have Model Counseling n to n Problem,
Input form
counselings table
problems table
Counselings Model
Problem Model
Controller
public function create()
{
return view('admin.counseling.create', [
'title' => 'Tambah Bimbingan dan Konseling',
'students' => Student::all(),
'problems' => Problem::all()
]);
}
public function find_nis(Request $request)
{
$student = Student::with('student_class', 'counselings')->findOrFail($request->id);
return response()->json($student);
}
public function store(Request $request)
{ dd($request->all());
$counseling = new Counseling();
$counseling->student_id = $request->student_id;
$counseling->user_id = Auth::user()->id;
$counseling->save();
if ($counseling->save()) {
$problem = new Problem();
$problem->id = $request->has('problem_id');
$problem->save();
}
}
You can insert into a pivot table in a few different ways. I would refer you to the documentation here.
Attaching
You may use the attach method to attach a role to a user by inserting
a record in the relationship's intermediate table:
Example:
$problem->counselings()->attach($counseling->id);
Sync
You may also use the sync method to construct many-to-many
associations. The sync method accepts an array of IDs to place on the
intermediate table. Any IDs that are not in the given array will be
removed from the intermediate table.
Example:
$problem->counselings()->sync($counselingsToSync);
Toggle
The many-to-many relationship also provides a toggle method which
"toggles" the attachment status of the given related model IDs. If the
given ID is currently attached, it will be detached. Likewise, if it
is currently detached, it will be attached:
Example:
$problem->counselings()->toggle($counselingsToToggle);
I would change your store() method to something like this :
public function store(Request $request)
{
$counseling = Counseling::create([
'student_id' => $request->student_id,
'user_id' => Auth::user()->id
]);
if($request->has('problem_id'){
$counseling->problems()->attach($request->problem_id);
//return something if problem id is in request
}
//return something if problem id is not there
}

Create and Insert Many-to-Many Relationships in Laravel

First of all, i'm a beginner and trying to learn all i can. So if i have mistakes please correct me.
So, i am working on a laravel project. I've got two models; drugs and interactions. What i am struggling is, I want to add two drugs and one interaction in one form. But also, i want to check if the drug has inserted already to avoid duplicate data.
Here are my models:
class Drug extends Model
{
//Table Name
protected $table = 'drugs';
//Primary Key
public $primaryKey = 'id';
//Timestamps
public $timestamps = true;
//relationship
public function interactions()
{
return $this->belongsToMany('App\Interaction', 'drug_interaction', 'interaction_id', 'drug_id');
}
}
class Interaction extends Model
{
//Table Name
protected $table = 'interactions';
//Primary Key
public $primaryKey = 'id';
//Timestamps
public $timestamps = true;
//Relationship
public function drugs()
{
return $this->belongsToMany('App\Drug', 'drug_interaction', 'drug_id', 'interaction_id');
}
}
And this is simply the store function in my DrugsController
public function store(Request $request)
{
$this->validate($request, [
'name'=> 'required',
'info'=> 'nullable'
]);
//create drug
$drug = new Drug;
$drug->name = $request->input('name');
$drug->info = $request->input('info');
$drug->save();
return redirect('/drugs')->with('success', 'İlaç Eklendi');
}
And this is my InterationsController's store function.
public function store(Request $request)
{
$this->validate($request, [
'name'=> 'required',
'description'=> 'required',
'category'=> 'nullable'
]);
//create interaction
$interaction = new Interaction;
$interaction->name = $request->input('name');
$interaction->description = $request->input('description');
$interaction->category = $request->input('category');
$interaction->save();
I can attach relationships via artisan tinker so i think relationship works. But i stuck when it comes to multiple input forms goes to different controllers. But using static id's. I need to make it variables. But two drugs should be attached to one interaction. So i couldn't succeed pasing two variables from form at the same time.
In dumb words, what i am trying to achieve is;
request drug_name_one from form's first textbox. Check db for that drug name, if exists; get its id. If it doesn't then create one and get id.
request drug_name_two from form's second textbox. Do the same as step one.
create an interaction as typed in form's third text box.
attach them.
PS: after this attach() work done, i also couldn't find a way to search for two drugs if they have a common interaction. If you can also mention a few tips to achieve that i'll be grateful.
All help and further reading advices appreciated. Thanks All !
Edit:
This is the create_interactions migration.
Schema::create('interactions', function (Blueprint $table) {
$table->BigIncrements('id');
$table->string('name');
$table->string('description');
$table->string('category');
$table->timestamps();
});
}
This is the input for 'category' field:
<div class="form-group">
{{Form::label('category', 'Kategori')}}
{{Form::text('category', '', ['class' => 'form-control', 'placeholder' => 'Etkileşim Kategorisi'])}}
</div>
I couldn't make the structure of a form as i desired btw. It's just the form for creating interactions by itself without relationship.
Here is the solution. It is working well now.
First of all i was trying to assign 2 drugs to one interaction. So i've imported select2 and used this "select" form to list the drugs and chose multiple from them:
<div class="form-group">
{!! Form::label('İlaçları Seçin') !!}
{!! Form::select('drugs[]', $drugs, null, ['multiple' => 'multiple', 'class' => 'form-control drugs']) !!}
</div>
On the InteractionsController:
$interaction = new Interaction;
$interaction->name = $request->input('name');
$interaction->description = $request->input('description');
$interaction->category = $request->input('category');
$interaction->save();
$interaction->drugs()->sync($request->drugs, false);
But i also wanted to show and edit those drugs assigned to the specific interaction. So on the edit.blade.php form there is this script:
<script type="text/javascript">
$('.drugs').select2().val({!! json_encode($interaction->drugs()->allRelatedIds()) !!}).trigger('change');
</script>
This script, calls the related drugs to the selected interaction in the same form as i used in create.blade.

how to save extra not required field in laravel default auth registration form

I am trying to customize the laravel auth registration. And I have added father name field in table and form. But father name field is not required.
I added this field in registercontroller.php and in User model also.
And then, if submit the form with all fields then data inserts successfully, But if I submit the form without father name field (which is not required), then error comes: f_name filed can not be null.
If I remove f_name from fillable then f_name is not saving.
Method in RegisterController.php is:
protected function create(array $data)
{
return User::create([
'name' => $data['name'],
'email' => $data['email'],
'f_name' => $data['f_name'],
'password' => bcrypt($data['password']),
]);
}
User.php is:
protected $fillable = [
'name', 'email', 'f_name' , 'password',
];
This is because you did not make it nullable in the database.
The other thing is that you should not code like that. You should create a Request class (where you validate request) for users with php artisan make:request UserRequest in command line or terminal. See the following.
protected function create(UserRequest $userRequest)
{
$user = new User($userRequest->all());
$user->password => bcrypt($userRequest['password']);
$user->save();
// your rest of the code.
}
Case 1: You might have set field default value to not-NULL in DB. Check your migrations it shpuld be something like $table->string('f_name')->nullable(); or Check in DB/phpmuadmin and set to NULL by default.
Case 2: Check your validator function, can set it to sometimes.

How to update an user using Route Model Binding in Laravel 5.6

I have a profile view where i would like to update users profile.
my Controller:
public function update(Request $request, User $user)
{
$validatedData = $request->validate([
'name' => 'required',
'email' =>'required|email',
'key' => 'required'
]);
// dd($user);
$user->update($validatedData);
// User::whereId($user->id)->update($validatedData);
return back()->with('flash', 'Successfully updated profile.');
}
I'm injecting a model's instance into my route. When i dd($user) i get the current user instance.
Now i would like to update the user with the validatedData. But unfortunately this $user->update($validatedData); is not working. I don't understand why...
This User::whereId($user->id)->update($validatedData); is working but it feels very strange to call on user the user->id.
It's important to understand the difference between the two similar calls.
whereId() returns an instance of the query builder so you're no longer calling methods on the model. So update() is a query builder call, not a model call.
find() (or route model binding) would returning an instance of the Model. Therefore, you'd be calling update() from the Model itself.
Eloquent models have mass assignment protection built in. My assumption is one or more of your columns are not in the $fillable array in your model. Either explicitly add every column into the $fillable array or remove the $fillable array and explicitly add every column that should not be mass assigned to the $guarded array.
https://laravel.com/docs/5.6/eloquent#mass-assignment
If you try update remenber declare fields into $fillable property on model.
protected $fillable = ['name','email','key'];
After that you can update the model using Route Model Binding
I ran into this yesterday. I was using model route binding for a delete action. So, I passed the ONLY the user ID to the DELETE route and hinted {user} in the route like this:
Route::middleware(['auth:sanctum', 'verified'])
->delete('/users/delete/{user}', [UserController::class, 'delete'])
->name('users.delete')
->where('id', '[0-9]+');
And the controller worked so simply like this:
public function delete(User $user) {
$user->delete();
return Redirect::route('users')
->with('success', "User $user->id $user->name was deleted successfully");
}
I was glad to have the user object available for the flash message.
Using the same process, I wanted to add a user update action. So, I did the same thing, I sent only the user ID to the PUT route and hinted user again:
Route::middleware(['auth:sanctum', 'verified'])
->put('/users/edit/{user}', [UserController::class, 'edit'])
->name('users.edit')
->where('id', '[0-9]+');
I got to the controller and could dump the user object. So, I tried a simple update something like this:
public function edit(User $user)
{
$user->update(
[
'name' => user->name,
'email' => user->email,
]
);
}
I received no errors and the update returned true.
But my data did not reflect the intended changes...
Then, in the car a while later, I realized, with model route binding, the route is querying the existing user in the database. So, if I assign the values from that user object in the controller, there will be no change!
::facepalm::
So, it makes sense that the delete action would work fine, but for an update action, you must assign the changed values from the request during the update. Because the values in the request would likely be different than the existing user objects values:
public function edit(Request $request, User $user)
{
$user->update(
$request->validate([
'name' => 'required|string',
'email' => 'required|email',
])
);
return Redirect::route('users')
->with('success', "User $user->id $user->name was updated successfully");
}

Validating Multiselect CakePHP 3 belongsToMany Entites

I'm want to ensure that a multi-select field (belongsToMany) has at least one item checked/selected. I have two entities:
Listings and PaymentTypes - belongsToMany.
My field is created with the helper:
echo $this->Form->input('payment_types._ids', ['options' => $paymentTypes, 'multiple' => 'checkbox']);
In my ListingsModel.php file I have my validator setup as follows:
public function validationDefault(Validator $validator) {
$validator = new Validator();
$validator->requirePresence('payment_types._ids');
return $validator;
}
This prevent the save from happening but I don't see any validation error message. Why doesn't the HTML5 form validation work as it does on other fields which are of type text?
I managed it with this custom rule:
->add('delivery_types', [
'multiple'=>[
'rule'=>['multiple', ['min'=>1]],
'message'=>'Select at least one method of delivery method'
]
])
This isn't especially well documented in the book so hopefully it iwll be of some help to others starting with Cake v.3
You should be able to accomplish this with nested validators - http://book.cakephp.org/3.0/en/core-libraries/validation.html#nesting-validators.
As an example:
public function validationDefault(Validator $validator) {
$paymentTypesValidator = new Validator();
$paymentTypesValidator->requirePresence('_ids');
$validator-> addNested('payment_types', $paymentTypesValidator);
return $validator;
}
You could then decorate the $paymentTypesValidator object with any other rules you require.

Categories