Laravel updating multiple hasMany / belongsToMany relationships - php

I have inherited a project that has a a few CRUD forms ... On the create form we need to create entries for a hasMany and belongsToMany relationship. So basically what i have got is the following
$movie = Movie::create($request->validated());
// Then to save the belongsToMany
foreach ($request['actors'] as $actor) {
// do some data manipulation
$actor = Actor::where('code', $actor->code)->first();
$movie->actors()->attach($actor);
}
// Save the hasMany
foreach ($request['comments'] as $comment) {
// do some data manipulation
$movie->comments()->create([
'title' => $comment['title'],
'body' => $comment['body'],
]);
}
I'm not sure if this is the best way of doing this, but it seems to work.
The problem I am having is that in the edit form, these actors / comments can be edited, added to or deleted and i am unsure of how to go about updating them. Is it possible to update them, or would it be better to delete the existing relationship data and re-add them?
I have never updated relationships, only added them so i am unsure how to even start.
Any help would be greatly appreciated.

As laravel doc suggested you can use saveMany() method for storing relationship instances.
// Save the hasMany
foreach ($request['comments'] as $comment) {
$comments[] = [
new Comment([
'title' => $comment['title'],
'body' => $comment['body'],
]);
];
}
!empty($comments) && $movie->comments()->saveMany($comments);
For deletion and update you should define two routes, one for updating comment and one for deleting comment.
Route::patch('movie/{movie}/comment/{comment}',[MovieController::class,'updateComment']);
Route::delete('movie/{movie}/comment/{comment}',[MovieController::class,'deleteComment']);

Related

Multi selection bootstrap insert in database Laravel

I'm trying to create multi selection bootstrap output to save in database but I'm getting an array in my controller like ["6","7"]. How I can save this?
There is 2 selection that means 2 row must created.
The query I was trying:
$table = Pool_user::updateOrInsert(['pool_id' => [$string1], 'user_id' => $request['id']]);
Can anyone help me to solve this?
By responding directly to your question, you need to create an array of arrays with the values you want to enter.
Something like this:
$array = [];
foreach($request['pool_ids'] as $pool_id){ //$request['pool_ids'] -> ["6","7"]
array_push($array, [
'pool_id' => $pool_id,
'user_id' => $request['id']
]);
}
$table = Pool_user::insert($array);
However, considering that Pool_user is a Pivot table of a Many to Many relationship, there is a much better method of doing this.
Let's say in User Model, have a relationship called polls().
You can simply ask the Eloquent to synchronize the relationships:
$user = User::find($request['id']);
$user->polls()->sync($request['pool_ids']); //$request['pool_ids'] -> ["6","7"]
Hope this helps

Laravel attach object to many objects in many-to-many relationship without loop

I have a many-to-many relationship on a User model and Notification model.
To create a Notification and attach to many Users, I am currently doing:
$users = User::all();
$notification = new Notification(['title'=>'some title', 'body'=>'notification body']);
$notification->save();
foreach ($users as $user) {
$user->notifications()->attach([$notification->id]);
}
The foreach implementation won't be ideal if $users->count() becomes a very large number;
Please is there a better way to get this done without so many loops?
Thanks
See here: https://laravel.com/docs/5.4/eloquent-relationships#updating-many-to-many-relationships
You can pass an array of ids to the attach() method like so:
$user_ids = User::pluck('id');
$notification = new Notification(['title'=>'some title', 'body'=>'notification body']);
$notification->save();
$notification->users()->attach($user_ids);
Assuming your relationship on $notification is called users() of course
No there isn't, not using Eloquent.
There exists the ability to attach multiple records simultaneously, but this internally uses a loop itself, so you're not making any saving there.
$notification->users()->attach([
1 => [],
2 => [],
// ...
]);
When dealing with large result sets, Eloquent is not necessarily the ideal solution. You might consider using the Database query builder or even raw SQL to handle mass insert operations.
$users = User::all();
$notification = Notification::create([
'title'=>'some title',
'body'=>'notification body'
]);
$notification->user()->attach($users);

updating related tables from a controller laravel

Hi I’ve a users and education table. A user can have multiple school or college. So its one to many relationship. education table has school, from_year, to_year and user_id (fk) I want to update the user table as well as education table from a PUT request to users/{id} with email,school, from_year, and to_year fields.
// UsersController.php
public function update(Request $request, $id)
{
$user = User::find($id);
if (!$user) {
return $this->respondNotFound('User not found');
}
$input = $request->all();
$input = array_filter($input, 'strlen');
//$user->update($input);
//Get array of school records
// $user->educatoion->push($records) // don't know what will come here to update the education table
// or may be $user->push(); // don't know
return $this->respond([
'data' => $user,
]);
}
Try to keep it as simple as possible.
If this is your first time updating multiple tables at once, draw up a diagram of the process. This way you can identify the correct order of updates.
Take care to note any formatting that has to done on each value.
Laravel has some great functionality in regards to binding input to a model using ->update($data)
However, when binding to multiple models, you might run into issues with duplicate field names.
Update:
To create a education row from the $user model:
$education = new Education(array('school' => 'Harward', 'from_year' => 1999, 'to_year' => 2016));
User::find($id)->education()->save($education);

Laravel Pivot Tables - accessing from inverse relation-table

UPDATE: Apparently $problem->userRatings()->count(); returns 1, so a record does exist, but the script still doesn't enter the foreach loop for some reason...
UPDATE 2/Solution: I feel incredibly foolish, but the reason it isn't working, is that I was calling foreach($problem->userRatings() as $rating){ when it should be foreach($problem->userRatings as $rating){ (dynamic property)
In my database I have problem_ratings, problems, and users. I have models for users and problems, and problems_ratings is a pivot table between problems and users with an extra 'content' column that stores the numeric rating value (1-5).
The many-to-many relation in my Problem model:
public function userRatings(){
return $this->belongsToMany('User', 'problem_ratings', 'author_id', 'problem_id')->withPivot('content');
}
The many-to-many relation in my User model:
public function problemRatings(){
return $this->belongsToMany('Problem', 'problem_ratings', 'author_id', 'problem_id')->withPivot('content');
}
When creating a problem_ratings element, I attach it to my user model like so:
$user->problemRatings()->attach($problem->id, array('content' => $val));
I can access the pivot table through the user, but when I try this:
foreach($problem->userRatings() as $rating){
echo "In average loop";
$newAverage = ($rating->pivot->content) + $newAverage;
}
it doesn't find any records, even though some exist in the database. Am I using these relations correctly?
Thanks in advance!
In the Problem model I think your relationship should looks something like :
public function userRatings(){
return $this->belongsToMany('User', 'problem_ratings', 'problem_id', 'author_id')->withPivot('content');
}
When using a foreach loop over something like this, you need to use dynamic properties (ie. without parentheses):
foreach($problem->userRatings as $rating){ instead of foreach($problem->userRatings() as $rating){

unable to fetch records from multiple tables using join

I am using Yii framework. i am wonder how i can get records from multiple tables i did research but couldn't find any usefull link i am using following code for this please let me know where i am missing
my model Task.php
public function relations()
{
// NOTE: you may need to adjust the relation name and the related
// class name for the relations automatically generated below.
return array(
'prj_user' => array(self::BELONGS_TO, 'User', 'id'),
);
}
model User.php
public function relations()
{
// NOTE: you may need to adjust the relation name and the related
// class name for the relations automatically generated below.
return array(
array('task', self::HAS_MANY, 'Task','project_id')
);
}
and this is my main controller
$criteria = new CDbCriteria;
$criteria->compare('t.id', 1);
$criteria->with = array( 'prj_user' => array('select' => 'username,title,roles', 'joinType'=>'inner join'));
$rows = Task::model()->findAll( $criteria );
but still i am getting columns only from task table but i need more three columns from users table please help me
Let Yii worry about joining your tables. Your relations looks fine so you should be able to access them directly
For example, what does this return?
foreach ($rows as $task)
{
if ( isset($task->prj_user) )
echo $task->prj_user->username . "<br>";
}
Or this?
this->widget('zii.widgets.grid.CGridView', array(
'dataProvider'=>new CActiveDataProvider('Task'),
'columns'=>array(
'id',
'prj_user.username',
'prj_user.title',
'prj_user.roles',
)
));
->with() is used for eager loading, so at this point you probably don't need it. In fact, unless I misread you completely, you can remove your criteria all together.

Categories