merge values into one collection using laravel - php

I have a table only able to submit maximum two times on each qid.
first submit = 'submitted' on status column.
second submit = 'resubmitted' on status column.
id username qid amount status
1 john 2 150 submitted
2 john 2 120 resubmitted
3 david 2 100 submitted
4 david 2 80 resubmitted
I want to add the first amount on a collection like below so I can simply display both amounts on view.
"id" => 1
"username" => john
"amount" => "120.00"
**"first_amount" => "150.00"**
"status" => "resubmitted"
Blade:
#foreach($xxx as $x)
{{$x->amount}}
{{$x->first_amount}}
#endforeach
Is this possible?

You can load data once:
$collection = Model::get();
And then use the collection without executing any additional queries:
#foreach($collection->where('status', 'resubmitted') as $x)
{{ $x->amount }}
{{ $collection->where('status', 'submitted')->firstWhere('qid', $x->qid)->amount }}
#endforeach
Or you can rebuild the collection to add first_amount to it:
$collection = $a->where('status', 'resubmitted')->map(function($i) use($collection) {
$i['first_amount'] = $collection->where('status', 'submitted')->firstWhere('qid', $i['qid'])->amount;
return $i;
});

Add the "first_amount" column to the table with a default value of 0. Then it will be populated in the collection when you retrieve it. You can set the value of the "first_amount" when you insert the "resubmitted" rows.
It will also save you having to modify the collection to add a value into it.

You can do this in your query or transform the result (via collection).
One possible solution (via Collection) is:
$collection = (new Collection($data))->groupBy('username')->map(function($userItems, $username) {
$firstAmount = $userItems->where('status', 'submitted')->first();
return $userItems->map(function($data) use ($firstAmount) {
return array_replace_recursive($data, ['first_amount' => $firstAmount['amount']]);
});
})->flatten(1);
This will add the first amount to all results.
Another way is like Alexey posted. Basically you fetch the the "resubmitted" values and add the first_amount into it. But, this will be added only into "resubmitted" values (items with 'submitted' won't have the first_amount key).

Related

How can I retrieve 3 values ​with the every id in the foreach method?

#foreach ($options as $ozellik)
#if($ozellik->urun_kategori == $urunler->id )
<tr>
<td> <b> {!!$ozellik->ozellik!!}</b></td>
<td>{!!$ozellik->aciklama!!}</td>
</tr>
#endif
#endforeach
this is my blade
I want to retrieve 3 values for every id. How can i do that. It has to retrieve 3 values for each id.
My Table
For example i want to get 3 of the values for "urun_kategori" = 7
But there are 4 records for "urun_kategori" = 7
This is where is set $options
Without being able to test it since you did not provide a sample dataset. The solution to your problem should look something like this:
$options = $options->groupBy('urun_kategori')
->flatMap(function($group) {
return $group->take(3);
});
... place that inside your web.php after the line $options = App\Option::all();
Explanation:
groupBy as the name suggest groups the collection by the given attribute 'urun_kategori' into subcollections. In the flatMap we limit the the amount of items in each group to 3 - take(3), then flatten the array because we dont need the subcollections anymore.

Laravel - how to group data by key and save to array?

I have table attribute_values(id, value, attr_group_id).
I need to return the collection grouped by key attr_group_id.
in clear php using ORM RedBean i made:
$data = \DB::table('attribute_values')->get();
$attrs = [];
foreach ($data as $k => $v){
$attrs [$v['attr_group_id']][$k] = $v['value'];
}
return $attrs;
I need same using Laravel, after this one:
$data = \DB::table('attribute_values')->get();
My table
id value attr_group_id
1 one 1
2 two 1
3 three 2
4 four 2
5 five 3
6 six 3
And i need result
Array(
[1] => Array
(
[1] => one
[2] => two
)
[2] => Array
(
[3] => three
[4] => four
)
[3] => Array
(
[5] => five
[6] => six
)
)
Fetch all data, and map it with attribute id of every row will work,
$data = \DB::table('attribute_values')->get();
$attrs = [];
foreach ($data as $key => $value) {
// -> as it return std object
$attrs[$value->attr_group_id][] = $value->value;
}
dd($attrs);
You can use the groupBy() function of collection as:
$data = \DB::table('attribute_values')->get()->groupBy('attr_group_id');
It merges records with same attr_group_id under this field's value as making key of the collection.
Doing all this in raw SQL will be more efficient, SQL database are quite good at these operations. SQL has a group by function, since you are overwriting value, i just get it out with max() (this seems weird, that you overwrite the value, do you actually just want unique results?).
DB::table('attribute_values')
->select('attr_group_id', DB::raw('max(value)'))
->groupBy('attr_group_id')
->get();
EDIT
Since the scope has changed, you can utilize Laravels Collection methods, that is opreations on a Collection.
DB::table('attribute_values')
->get()
->groupBy('attr_group_id')
->toArray();
Friends, this is a ready task that I needed !
I did it myself and you helped me. If anyone interested can read.
I'll explain to you why I needed this particular method. I am doing an online store with a clock and now there was a task to make filters and attributes for filters.
So there are three tables
attribute_groups table
attribute_products table
attribute_values
I need to display the Laravel widget on my .blade.php like as
{{ Widget::run('filter', 'tpl' => 'widgets.filter', 'filter' => null,]) }}
When i creating a new product in the admin panel.
I must to save the product id and attribute_id in attribute_products, but there can be as many attributes as possible for one product. so, if I'll use this option
$data = \DB::table('attribute_values')
->get()
->groupBy('attr_group_id')
->toArray();
I got result:
But! each new array starts with index 0. But I need an index that means its id. attr_group_id from table attribute_value for saving into attribute_products.
And after I see only one method for me.
$data = \DB::table('attribute_values')->get();
$attrs = [];
foreach ($data as $key => $value) {
$attrs[$value->attr_group_id][$value->id] = $value->value;
}
return $attrs;
and the result I was looking for
now you can see what's the difference and what was needed. Array index starts 1,2,3,4,5 and this index = attr_group_id. Unfortunately I could not initially ask the right question. thanks to all.
Laravel Version 5.8
So You need to Group the id
if You need in the Model Way I have created the Model as AttributeValue
$modelWay = \App\AttributeValue::get()
->groupBy('attr_group_id');
if You need in the DBWay I have created the table as attribute_values
$dbWay = \DB::table('attribute_values')
->get()
->groupBy('attr_group_id');
Both Will give the Same Result

How to KeyBy where multiple items have the same key

I am using Laravel Collections methods and am trying to key my query results (which are a collection) by the id. The problem is I have multiple entries with the same id, but point to different countries and I want to have all of the values, not just the last one.
Here is my code that i am using so far:
$allCountries = new Collection($allCountries);
$offerCountries = $allCountries->keyBy('id');
dd($offerCountries);
foreach ($offer as $o) {
$o->countries = $allCountries->get($o->id);
}
To explain, my query puts the results in $allCountries which contains ids and countries and those results looks something like this
id=>225, country=>US
id=>225, country=>IT
id=>3304, country=>NZ
Just to give you a quick idea. I want to key this by the id which results in $offerCountries. I then loop thru a previous Collection that contains offers which have a certain ID that relates to the country result by id. So for the offer 225, the countries it contains are US and IT. I loop thru each offer and set the countries object equal to all the $allCountries id that it equals. The problem I have here is keyBy overwrites the value and only takes the last one. I am hoping to get some results like this:
[
225 => countries: {'id' => 225, 'country' => 'US'}, {'id' =>
'225', 'country' => 'IT'}
3304 => ['id' => 3304, 'country' => 'NZ'],
]
Is there a laravel method to do this, or do I need to write my own keyBy so it does not overwrite. If so, how can I get started to write this method?
Thanks
Instead of using keyBy, use groupBy:
$countriesById = collect($allCountries)->groupBy('id');
You could use filter and create a custom filter
$filtered = $allCountries->filter(function ($item) use ($id) {
return $item->id == $id;
});
$filtered->all();

How do you populate a dropdown box using data from another model so that all rows are taken as options in yii?

I'm using version 1.1.14 of yii.
My VIEW file has
<?php echo $form->dropDownList($model,'estado', CHtml::listData(Estado::model()->findAll(), 'id', 'estado')); ?>
I have a model called Estado which was generated from a table with only 2 fields ID as PK and estado where I have my data. Which has 3 rows Active, Inactive, Prospecting.
So far the code only shows the last row of that table, ignoring the first 2.
What am I doing wrong?
for the dropdown list you can pass a normal array :
$data = array(
'number1',
'number2',
'number3',
);
or an array with key => value
$data = array(
7 => 'number7',
2 =>'number2',
4 =>'number4',
);
Chtml::listData() will only help you make that array avalable for the function
however if you need to make a combination of models ( or arrays) you have to do that manually using array concatenation functions such as CMap::mergeArray()

Removing Records from an Associated Table PHP

I am working on a Many to Many table and I fixed an issue where I couldn't pull the records. Now I'm trying to delete records when that is needed.
I have a site where children can be associated to an event. In the event that a child was accidentally added I want to be able to remove the child. They are added via Checkbox as follows:
<input type="checkbox" name="eventChildren[]" id="childId_12" />
<input type="checkbox" name="eventChildren[]" id="childId_13" />
<input type="checkbox" name="eventChildren[]" id="childId_14" />
I have multiple checkboxes that are pre-checked if the child has already been added.
I have three tables (not sure if this is relevant):
DB:
- children
- events
- eventChildren
When I save the record I'm doing a check to make sure I don't add duplicates to my eventChildren table. I know if records are already in the database but not submitted from the form then the child is being removed from the list...and I can't figure out how to catch this subset.
Example code:
// $eventChildren comes from the form above name="eventChildren[]"
// $eventId is passed into the function
$currentChildren = $this->eventChildren->GetEventChildren(array('eventId' => $eventId));
// Loop through all submitted children
foreach ($eventChildren as $childId)
{
// Loop through all existing children
foreach ($currentChildren as $currChild)
{
// If the child ID's do not match then it's a new record
if ($currChild->childId != $childId)
{
$this->eventChildren->AddEventChildren(array(
'eventId' => $eventId,
'childId' => $childId
));
}
}
}
When the form is submitted I get a return that grabs all records from the eventChildren table where the eventId matches.
eventChildren (return)
- [0]
eventChildrenId => 1
childId => 12
eventId => 4
- [1]
eventChildrenId => 2
childId => 13
eventId => 4
- [2]
eventChildrenId => 3
childId => 14
eventId => 4
submittedChildren
- [0] => 12
- [1] => 13
How can I say, based on the submittedChildren array remove the record where eventChildrenId = 3?
I hope this makes sense. :)
There's many ways to approach this(better ways), but I'm just going to go with a straight forward answer I can give based on the info you presented.
$orphaned = array();
foreach ($currentChildren as $currChild) {
if (!in_array($currChild->childId, $submittedChildren)) {
$orphaned[] = $currChild->childId;
}
}
Just to be clear, you're deleting the relationship between the two items (i.e. deleting from the many-to-many table)?
Usually the event_id and the child_id fields would be the identifying (PRIMARY) key in the relationship. Therefore, if the user submits a child_id of 13, and you can contextually derive that the event_id is 4, then deleting from the eventChildren table where child_id = 13 and event_id = 4 should suffice. You shouldn't need to first gather information about the eventChildren object (you already have the identifying info).

Categories