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.
Related
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);
There are some duplicate rows in db table. When retrieving from db and setting for the drop box, it should display values uniquely. How should I perform that?
There I want to avoid duplicating 2 in the drop box
I you have an instance of Illuminate\Support\Collection than you could do something like this
$unique = $collection->unique(); // where $collection is of course the variable that holds your collection
$unique->values()->all(); // [1,2,3,4]
I have a product table which has column name unit_id, I have approximate 15 units data. And I stored a custom key of unit to the product as you can check in the screenshot.
And the Units data is stored in settings table, in a single row and meta_value holds all the units data in json format
Now the problem is I have to run two queries every time for products, need help to know more convenient.
// For Products
Product::where('id', 1)->first();
// For settings
Settings::where('meta_key', 'product_units')->first();
Is there any way so that I attach the Settings data in Product model, the problem we get for multiple products not single.
You can try to use a mutator inside the Products model https://laravel.com/docs/5.1/eloquent-mutators.
public function getProductUnitsAttribute() {
return Settings::where('meta_key', 'product_units')->first();
}
so you can do this to get the settings
$product = Product::where('id', 1)->first();
$product->product_units;
but i don't think that this is a good practice.
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
I have size of product (XS, XL, ...).
I want add column in cart table Size, where show sizes of products.
I added SKU in this table $_item->getSku(); This works.
But $_item->getSize(); not works. Please, help me.
try adding ->addFieldToSelect('*'), it'll add every attribute associated with your products in the returning data, you can replace the * with the attribute code of the attribute your trying to display
problem is, it'll return integers that are used in either eav_attribute_option or eav_attribute_option_value (not sure why there's 2 different tables, one has values and one has sort order, it's not like Magento even links a value to 2 options), however if you use the following code
$attributeInfo = Mage::getResourceModel('eav/entity_attribute_collection')->setCodeFilter('ATTRIBUTE_CODE')->getFirstItem();
$sizeValues = array();
// populates sizevalue array with data
foreach ($attributeOptions as $key => $value)
{
$sizeValues[$value['value']] = $value['label'];
}
you get an array of values with their index's being that of that it returned in your collection