Update order in pivot table when using sync in Laravel - php

In Laravel 4.2, I have the following code:
$thingIds = [];
foreach ($this->things as $thing) {
$thingIds[] = $thing->id;
}
$thong->things()->sync($thingIds);
$thong->save();
Which seems to work for me, however in my pivot table I have an order column that isnt being updated/synced correctly. The order is set to 1 for each item in the pivot table, however I want the order to be representative of the order of the ids in $thingIds.
Is this possible?
Is it possible to update an additional column in the pivot table using ->sync()?
After the suggestion in the comments, I have also tried the following code:
$thingIds = [];
foreach ($this->things as $index => $thing) {
$thingIds[$thing->id] = ['order' => $index];
}
$thong->things()->sync($thingIds);
$thong->save();
And I have tried
$thingIds = [];
$order = [];
foreach ($this->things as $index => $thing) {
$thingIds[] = $thing->id;
$order[] = ['order' => $index];
}
$thong->things()->sync(array_combine($thingIds, $order));
$thong->save();
But neither of these is working (the order is still 1 for each item in the pivot table). Can anyone explain what I am doing wrong?
If I do the attaching one at a time, like so:
foreach ($this->things as $index => $thing) {
$thong->things()->attach($thing, ['order' => $index]);
}
The order comes out correctly in the pivot table. How can I get the same effect but whilst still using ->sync()?

Related

Why the name of trucks are same in 2nd and 3rd record of company data retrieval?

My data in database:
My objective is to retrieve all data of company collection (MongoDB) data from the database. The company collection holds one or many trucks. I have implemented one-to-many reference between company and trucks collection. That is working fine.
I am using query builder to get all the data. But, my code is not giving me all the Trucks of the specific company. It is retrieving only one truck name for specific documents.
My API code is checking the length of the truck's array and storing the name for the truck on ta[] array. Code is not written nicely as I have tried so many methods and I am frustrated now.
How can I retrieve my data?
My API:
/**
* #Route("/koco/get/company/query", name="queryToGetCompany")
* #Template()
*/
public function queryForCompanyAction()
{
$checkarray = array();
$dm = $this->get('doctrine_mongodb')->getManager();
$qb = $dm->createQueryBuilder(Company::class);
$qb->find(Company::class);
$query = $qb->getQuery();
$comapnies = $query->execute();
foreach ($comapnies as $company)
{
$objectId = $company->getId();
$objectName = $company->getName();
$objectAddress = $company->getAddress();
// for length
$len = count($company->getTrucks());
echo $len;
// For trucks
$Trucks = $company->getTrucks();
foreach ($Trucks as $truckname)
{
$ta = array();
for($i=0;$i< $len;$i++){
$object = new Truck();
$object = $truckname->getName();
$ta[] = $object;
}
}
$checkarray[] = array(
'Id' => $objectId,
'Name' =>$objectName,
'Address' =>$objectAddress,
'Trucks' => $ta,
);
}
$data = [
'Comapnies' => $checkarray,
];
return new JsonResponse($data);
}
My results from the API:
The 2nd and third companies are giving me the same records for the name of trucks, but in my database the truck names are different.
Your foreach and your for loop are colliding, in conjunction with your array being emptied inside the foreach loop. If you reset your array before the foreach loop, not inside, and also just use a foreach without the for, I think this is what you want.
What is happening in your code as presented in the question is that the array is wiped out between trucks, so you only get the last truck. Additionally, because of the manually counted for loop, the number of copies of the last truck is equal to the total number of trucks associated with each company.
This is my suggestion based on what you have shown, replacing the entire foreach loop with this code.
$ta = array();
foreach ($Trucks as $truckname)
{
$object = new Truck();
$object = $truckname->getName();
$ta[] = $object;
}

How to find and merge two rows into one

I am new to Laravel so I am confused how to do this
I have a table called groups where I forget to use unique in validation . After Long time I found out there are multiple datas with same name for ex :
I have two datas with same name called Feminism but with different id
The group table have only name and description columns , but it has relation with products many to many I have other datas too which has same name I want to merge those datas into one . along with the relation to the product . Is is possible ?
Shall I have to check all the names manually like
Item::where('name','Feminism')->get();
and then merge those datas or we have some other relavant methods
You can refactor this code for your models and relations
foreach ($groups as $group) {
$duplicates = Group::where('name', $group->name)->where('id', '<>', $group->id)->get();
foreach ($duplicates as $duplicate) {
$mustBeUpdatedRelation = $duplicate->products;
$anotherRelation = $duplicate->anotherRelation;
foreach ($mustBeUpdatedRelation as $product) {
$product->categories()->detach($duplicate->id); // if product has pivot data you must get these and assign to new relation
//new relation
$product->categories()->attach($group->id);
}
$anotherRelation = $duplicate->anotherRelation;
foreach ($anotherRelation as $item) {
// like above
// detach duplicated
// attach unique
}
//finally you can delete or .... duplicated group
$duplicate->update([
'name' => "duplicated_$duplicate->name"
]);
}
}
You may use the following
$items = App\Item::with('products')->get();
$tempArr = [];
foreach ($items as $key => $item) {
if(isset($tempArr[$item->name])) {
$merged = $tempArr[$item->name]['products']->merge($item->products);
unset($tempArr[$item->name]['products']);
$tempArr[$item->name]['products'] = $merged;
} else {
$tempArr[$item->name] = $item;
}
}
foreach ($tempArr as $item) {
$item->products()->sync($item->products->pluck('id'));
}
$idsToKeep = array_column($tempArr, 'id');
App\Item::whereNotIn('id', $idsToKeep )->delete();
Use onDelete cascade when defining your pivot table migration.
This takes care of deleting the model’s relations for you:
e.g.
$table->foreign(’item_id’)
->references(’id’)->on(’items’)
->onDelete(’cascade’);

Laravel Eloquent update multiple rows with same value but different ID

I'm using Laravel 6 and Eloquent. I'm looking for a way to update a set of rows with a set value, each identified with a unique ID.
This is what I'm doing right now:
$ids = [3948, 1984, 7849, 4456, 394];
$value = false;
foreach ($ids as $id)
{
User::where("id", $id)->update(["status" => $value]);
}
Is there a way to accomplish the same with only 1 query instead of 5?
You can use whereIn, like:
$ids = [3948, 1984, 7849, 4456, 394];
$value = false;
User::whereIn("id", $ids)->update(["status" => $value]);

How to updated multiple records with Laravel and Eloquent?

I have a project written using PHP on the top of Laravel 5.7. I am using Eloquent ORM to interact with the database.
I need to be able to update lots of records after pulling them from the database.
Here is how I am trying to do it.
$records = Record::where('Key','Test')->get();
$values = collecT([
['Id' => 1, 'Col' => 100],
['Id' => 2, 'Col' => 200],
['Id' => 3, 'Col' => 500],
....
]);
foreach($records as $record) {
$newValue = $values->where('Id', $record->id)->first();
if(is_null($newValue)){
continue;
}
$record->ColName = $newValue['Col'];
$record->save();
}
The above code does not write the updated value to the database. However, if I do the following it gets updated
foreach($values as $value) {
$record = Record::where('Key','Test')->where('id', $value['Id'])->first();
if(is_null($record)){
continue;
}
$record->ColName = $value['Col'];
$record->save();
}
Although the above code works, I have to make 1 select + 1 update statement for every record in the $values array. If the size of $values array is 1000. That's going to generate up to 2000 queries which are insane!
How can I correctly update multiple records in the database without doing range-update.
If all the rows you are trying to update would get the same value it is an easy problem. The problem becomes a bit more tricky because all your rows need to be updated with different values. This comment on a github issue of laravel has a solution that will do it with a single query, allowing him in that case with a 13x performance boost for 1000 rows to be updated compared to updating them one by one:
public static function updateValues(array $values)
{
$table = MyModel::getModel()->getTable();
$cases = [];
$ids = [];
$params = [];
foreach ($values as $id => $value) {
$id = (int) $id;
$cases[] = "WHEN {$id} then ?";
$params[] = $value;
$ids[] = $id;
}
$ids = implode(',', $ids);
$cases = implode(' ', $cases);
$params[] = Carbon::now();
return \DB::update("UPDATE `{$table}` SET `value` = CASE `id` {$cases} END, `updated_at` = ? WHERE `id` in ({$ids})", $params);
}
You can also try https://github.com/mavinoo/laravelBatch which does something similar.

push data in to a multidimensional array in laravel php

I want to create a multidimensional array to save the data according the date and a category as follow. Then i need to display this data in my blade view?what can i do to achieve this.
'2012-05-05' => array(
'suspension' => 52,
'transmission' => '58'
),
'2012-05-05' => array(
'suspension' => 44,
'transmission' => 21
I have done the following in my controller i want a $reportData variable to load the data.
public function loadReports(Request $request)
{
$data = ['2012-05-05','2012-05-06'];
$salesItems = array();
$orderItems = OrderItem::with('spare', 'order')->get();
foreach ($orderItems as $key => $orderItem) {
if ($orderItem->spare->retailer_id == Auth::user()->id) {
array_push($salesItems, $orderItem);
}
}
$categories = App\Categories::all();
foreach ($data as $date) {
foreach ($categories as $category) {
$categoryValue = 0;
foreach ($salesItems as $salesItem) {
if ($date == $salesItem->order->orderDate) {
$categoryValue += $categoryValue + $salesItem->subTotal;
}
}
//error appears as illegal offset type
$reportData[$date][$category]=$categoryValue;
}
}
return View::make('Retailer/reports')->with('categories', $categories)->with('reportData', $reportData);
}
I haven't tested it but looking at your code it seems that you're passing an object as array index key as 2nd level array index:
$reportData[$date][$category] = $categoryValue;
^^^^^^^^^ this is an object
Dump your $category in the foreach loop & check if that is the case: dd($category)
If you're using Eloquent & your Categories Model has a name property, you'll probably want to take each category name as index value:
$reportData[$date][$category->name] = $categoryValue;
The error is occurring due to the fact that you are trying to use an Object as the array's index.
As per the laravel documentation (https://laravel.com/api/4.2/Illuminate/Database/Eloquent/Model.html#method_all) the all method you called here '$categories = App\Category::all();' would have returned an Eloquent Collection.
So when you iterated over the $categories array and referenced $category, you were referencing an object. In PHP an array can only be indexed by either an integer or a string. So you need to change the line of code where the error is to this
$reportData[$date][$category->someVar] = $categoryValue;
Where someVar is the name of a variable on the Eloquent model Category that references its name, such as 'suspension' etc.
While it doesn't answer your question you could use the Eloquent engine to make your life easier:
$orderItems = OrderItem::with('spare', 'order')->get();
foreach ($orderItems as $key => $orderItem) {
if ($orderItem->spare->retailer_id == Auth::user()->id) {
array_push($salesItems, $orderItem);
}
}
can be simplified (and made more efficient) with:
// Store the uid to save the call.
$user_id = Auth::user()->id;
// Apply the condition to the Eloquent query.
$orderItems = OrderItem::with(['spare' => function($query) use ($user_id) {
return $query->where('retailer_id', '=', $user_id);
}, 'order'])->get();
The other answers are correct, but you probably also want to initialise the $reportData array as before you start working with it.

Categories