laravel4 update additional columns in pivot table - laravel

I'm trying to update additional column data in a pivot table in a many to many relationship.
I have two tables - reservation and resource linked with a pivot table. I can attach and am working with the model. However I'm struggling to update one of the additional columns in the pivot table.
I have an object: '$reservation' From that object I created another object $resources using:
$resources = $reservation->resource()->get();
I'm then iterating through $resources using a foreach loop as follows
foreach($resources as $resource ) {...}
I then want to update a column called gcal_id and am using the following:
$resource->pivot->gcal_id = "TEST";
$resource->save();
If I var_dump the model I can see the property exists to the correct value but in the database itself the entry is not being updated - so the save is not working
I have the columns listed in both sides of the relationship with this:
->withPivot('start', 'end', 'quantity', 'product_id','gcal_id')
Given I have the resource object how can I update a column correctly in the pivot table and save to database?
Thanks

After that you set the attribute on the pivot:
$resource->pivot->gcal_id = "TEST";
You seem to save the resource and not the pivot:
$resource->save();
If you want the pivot to be saved, saving the resource is not enough. Call save on the pivot instead:
$resource->pivot->gcal_id = "TEST";
$resource->pivot->save();

An alternative instead of save method, is the method Illuminate\Database\Eloquent\Relations\BelongsToMany\updateExistingPivot()
$reservation->resource()->updateExistingPivot($resource_id, ['gcal_id' => 'TEST']);
Or
$reservation->resource()->updateExistingPivot([1, 4, 5, 6], ['gcal_id' => 'TEST']);
This work for me in Laravel 4.2

Related

How to get the list of inserted ids from the insert() method to use with the syncWithoutDetaching() method?

I have Files and Folders models that are related by a many-to-many relationship with a folder_file pivot table.
I want to insert files in bulk using the insert() method, then use the list of inserted ids with the syncWithoutDetaching() method to update the pivot table, | first create the $data_array in a foreach loop that does other things as well:
$data_array = [];
foreach (...) {
// ...
$data_array[] = $row;
}
then I want to insert the data and update the pivot table:
File::insert($data_array);
$folder->files()->syncWithoutDetaching($array_of_inserted_ids);
Is it possible to get the list of inserted ids from the insert() method?
Or maybe there is a more efficient way for better DB performance?
At first I just wanted to create the record and update the pivot table inside the foreach loop that creates the $data_array so that on every iteration it would create and update the tables, but that could be bad for performance with that many queries?
You could use the createMany() here. Instead of inserting the files then get the ids of inserted data. It will accept an array of data so that you could directly insert your array of files then connecting them to the folder.
$folder->files()->createMany($data_array);

The merge method doesn't work in voyager laravel

I override the Laravel controller but now i don't what's the problem is coz it show me that (Field 'lab_price' doesn't have a default value) I used the merge method when I debugged its good and has a value.
$val = $this->validateBread($request->all(), $dataType->addRows)->validate();
$l_price = DB::table('labs')
->where('id', $request->lab_id)
->value('price');
$request->merge(['lab_price' => $l_price])
->all();
$data = $this->insertUpdateData($request, $slug, $dataType->addRows, new $dataType->model_name());
Actually i have lab_price column in child table and i want to get the (price) from the parent table and store in the child table whenever the lab_name is selected from the fronted.
Also if this method doesn't possible here, then is it possible through laravel observer?
I also go through it but i didn't find join in observer??

SOLVED: Looking for a smarter way to sync and order entries in Laravel/Eloquent pivot table

In my Laravel 5.1 app, I have classes Page (models a webpage) and Media (models an image). A Page contains a collection of Media objects and this relationship is maintained in a "media_page" pivot table. The pivot table has columns for page_id, media_id and sort_order.
A utility form on the site allows an Admin to manually associate one or more Media items to a Page and specify the order in which the Media items render in the view. When the form submits, the Controller receives a sorted list of media ids. The association is saved in the Controller store() and update() methods as follows:
[STORE] $page->media()->attach($mediaIds);
[UPDATE] $page->media()->sync($mediaIds);
This works fine but doesn't allow me to save the sort_order specified in the mediaIds request param. As such, Media items are always returned to the view in the order in which they appear in the database, regardless of how the Admin manually ordered them. I know how to attach extra data for the pivot table when saving a single record, but don't know how to do this (or if it's even possible) when passing an array to attach() or sync(), as shown above.
The only ways I can see to do it are:
loop over the array, calling attach() once for each entry and passing along the current counter index as sort_order.
first detach() all associations and then pass mediaIds array to attach() or sync(). A side benefit would be that it eliminates the need for a sort_order column at all.
I'm hoping there is an easier solution that requires fewer trips to the database. Or am I just overthinking it and, in reality, doing the loop myself is really no different than letting Laravel do it further down the line when it receives the array?
[SOLUTION] I got it working by reshaping the array as follows. It explodes the comma-delimited 'mediaIds' request param and loops over the resulting array, assigning each media id as the key in the $mediaIds array, setting the sort_order value equal to the key's position within the array.
$rawMediaIds = explode(',', request('mediaIds'));
foreach($rawMediaIds as $mediaId) {
$mediaIds[$mediaId] = ['sort_order' => array_search($mediaId, $rawMediaIds)];
}
And then sorted by sort_order when retrieving the Page's associated media:
public function media() {
return $this->belongsToMany(Media::class)->orderBy('sort_order', 'asc');
}
You can add data to the pivot table while attaching or syncing, like so:
$mediaIds = [
1 => ['sort_order' => 'order_for_1'],
3 => ['sort_order' => 'order_for_3']
];
//[STORE]
$page->media()->attach($mediaIds;
//[UPDATE]
$page->media()->sync($mediaIds);

Updating a pivot table in Eloquent

I've got a many to many relationship between a student and an institution_contact.
students should only ever have two institution_contacts and I have an attribute on the pivot table named type to be set as 1 or 2.
So, my pivot table looks like this:
institution_contact_student: id, institution_contact_id, student_id, type
I've run into difficulty in deciding how to approach the issue of adding/updating the pivot table. Let's say I have 100 students and I want to assign them a contact with the type of 1.
My current solution is to delete the contact then add it:
$students = Student::all(); // the 100 students
$contactId = InstitutionContact::first()->id; // the contact
foreach ($students as $student) {
// remove existing contact
$student
->institutionContacts()
->newPivotStatement()
->where('type', 1)
->delete();
// add new contact
$student
->institutionContacts()
->attach([$contactId => ['type' => 1]]);
}
However, I'm thinking that this is going to hit the database twice for each student, right? So would I be better off creating a model for the pivot table and removing all entries that matched the student id and the type then simply adding the new ones? Or would creating a model for the pivot table be considered bad practice and is there a better way of accomplishing this that I've missed?
Please note the reason I'm not using sync is because I'm relying on the type attribute to maintain only two contacts per student. I'm not aware of a way to modify an existing pivot without causing issues to my two contacts per student requirement.
Edit:
Instead of creating a model I could run the following code to perform the delete using DB.
DB::table('institution_contact_student') // the pivot table
->whereIn('student_id', $studentIds)
->where('type', 1)
->delete();
If I have understood your question correctly then you can use the updateExistingPivot method for updating your pivot table.But first of course you have to define the pivot in your relationship. For instance,
public function institutionContacts(){
return $this->belongsToMany('institutionContact')->withPivot('type');
}
after this, all you have to do is use the following code:
$student
->institutionContacts()
->updateExistingPivot($contactId, ["type" => 1]);
Hope this helps.

Laravel attach with extra field

I have 3 tables, products, images and product_image. The 3rd one is a pivoting table. Other than product_id and image_id in product_image table, I also have 2 extra fields in this pivoting table: position and type, now for an existing product model A, how do I attach an image to A and at the same time set up its position and type value in that pivoting record? Thanks.
You may try something like this:
$product = Product::find(1);
// if you need also to save the image
$image = new Image(array('foo' => 'bar'));
$product->images()->save($image,array('position'=>'foo', 'type'=>'bar' ));
// if you know image id
$product->images()->attach([$imageId => ['position'=>'foo', 'type'=>'bar']]);
You need just add a array to attach method as second parameter
//for example:
$product->images()->attach($newImage, ['foo'=>'bar']);
It is more eloquent solution.

Resources