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

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

Related

query laravel not working if pass variable in Where NOT IN

I'm trying to filter items from a database table
what I do is get the ids that I want to exclude and then through -> whereNotIn in laravel, I pass the ids
$idcontracts=array();
$idbike=array();
$biciCorretta = array();
$findcontract=Contract::whereRaw('? between data_inizio and data_fine', [$datainizio])->whereRaw('? between data_inizio and data_fine', [$datafine])->get();
foreach ($findcontract as $key) {
if (!in_array($key->id,$idcontracts)) {
array_push($idcontracts,$key->id);
}
}
foreach ($idcontracts as $idcontract) {
$bike_contracts=DB::table('bike_contract')->where('contract_id',$idcontract)->get();
foreach ($bike_contracts as $bike_contract) {
if (!in_array($bike_contract->bike_id,$idbike)) {
array_push($idbike,$bike_contract->bike_id);
}
}
}
$notid=implode("', '",$idbike);
up to this point I have no problem.
the result of "implode" gives me the ids I want to remove
this is the result of $idbike and $notid:
this is the query I write to exclude the ids found:
$bikes = Bike::with('category')->whereNotIn('id', [$notid])->orderBy('category_id')->get();
the problem is that it doesn't exclude me the ids passed with $notid
but if I manually pass the ids, it removes them instead:
$bikes = Bike::with('category')->whereNotIn('id', [40,41,34,36,39])->orderBy('category_id')->get();
am I doing something wrong?
You shouldn't implode $notid, that makes it a string and Laravels whereNotIn() already does that for you.
->whereNotIn('id', $idbike)
And remove the $notid parameter, as it is not needed.
implode will return in string, and because of that it will not work correctly, you should pass it as array instead.
If you print data
$idbike =[40,41,34,36,39];
print_r($idbike);
Output will be Array
Array
(
[0] => 40
[1] => 41
[2] => 34
[3] => 36
[4] => 39
)
and if you print below code
$notid=[implode(",",$idbike)];
print_r($notid);
The output will be
Array
(
[0] => 40,41,34,36,39
)
So your query become
->whereNotIn('id', ["40,41,34,36,39"])
so laravel searching for id of "40,41,34,36,39". so its not returning result
So you can pass array directly to wherenotin
->whereNotIn('id', $idbike)
Laravel, whereNotIn method removes elements from the collection that have a specified item value that is contained within the given array. That means you have to pass an array
So, idbike is the array you mentioned
$bikes = Bike::with('category')->whereNotIn('id', idbike)->orderBy('category_id')->get();

Fill one array using two loop

I have an object where there are all my articles.
I'm currently looping my object to fill an array where I create an associative table for each article.
In my object I also have a Categories object and I would like to add the label of each category at the end of each associative array previously completed, but
I don't know how to do that.. In the Categories object there may be multiple labels.
My code :
$articles = $this->entityManager->getRepository('SGBundle:Article')->findBy([], ['id'=>'desc']);
$arrayCollection = [];
foreach($articles as $article) {
$arrayCollection[] = [
'id' => $article->getId(),
'date_publication' => $article->getDatePublication(),
...
];
foreach($article->getCategories() as $categorie) {
$arrayCollection[] = ['categorie' => $categorie->getLibelle()];
}
}
On my screenshot, for each article there is an array with 36 values ​​and an array with 1 value and I would like this table to be in the table where there are 36 values. It's possible ?
First gather categories, then add'em to article item:
foreach($articles as $article) {
$categories = [];
foreach($article->getCategories() as $categorie) {
$categories[] = $categorie->getLibelle();
}
$arrayCollection[] = [
'id' => $article->getId(),
'date_publication' => $article->getDatePublication(),
...
//
'categorie' => $categories,
];
}
If the article.categories field is marked as lazy, then it won't be hydrated by default and the $article->getCategories() will perform a new query on each loop round.
Instead of a simple findBy, you might want a custom DQL query in this case to optimize this and get the exact array you want in one single request.
Also note that your current query is fetching all articles of your database. While this is probably your purpose, keep in mind that this could get pretty heavy with the data growing. In most cases, this kind of query should be paginated.

Associative array from a database with codeigniter

On my models I try to write a php model that will get me a associative array from a database. But I don't quite know how to approach this.
So after I execute this SQL query:
SELECT balance_events.weight,balance_events.added_date,
balance_entries.mid FROM balance_events, balance_entries
WHERE balance_entries.added_date BETWEEN '2016-08-02' AND '2016-08-03'
AND balance_entries.ptid =12
AND balance_entries.beid = balance_events.id
I will get this table:
And from that table I want to extract a asociative array that it will look like this:
count = ['13'=>1, '6'=>4, '16'=>3, '4'=>3]
where 'mid'=>number of how many times that mid can be found in the table.
ex. mid '13'=>1 cause you can found it only once.
I think that I will have to use SQL COUNT function, but how I can aggregate all of this in a PHP model in codeigniter? I know how to configure controller and view, but I don't know how to actually do the actual php model that will get me the desired array.
Try this query may help you ,
$result = $this->db->select('balance_events.weight,balance_events.added_date,COUNT(balance_entries.mid) as mid_count')
->from('balance_events, balance_entries')
->where('balance_entries.added_date BETWEEN "2016-08-02" AND "2016-08-03" ')
->where('balance_entries.ptid','12')
->where('balance_entries.beid','balance_events.id')
->group_by('balance_entries.mid')
->get();
return $result->result_array();
I'm not sure how you would create this in SQL but since you tagged php, I wrote a function that would do just this.
<?php
$query = array(array("mid"=>13), array("mid"=>2), array("mid"=>13), array("mid" =>6), array("mid" => 13), array("mid" => 6));
function createMidArray($queryResult){
$returnArray = array();
foreach ($queryResult as $qr){
$returnArray[$qr['mid']]++;
}
return $returnArray;
}
print_r(createMidArray($query));
?>
The output of this was Array ( [13] => 3 [2] => 1 [6] => 2 ) which matches up to my inputted $query (which is a 2D array). I'm expecting the output of your query is stored in a similar array, but with more data and keys

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();

Multiple foreach to process nested arrays -- PHP CodeIgniter

I would first like to thank you for taking the time to look at my question--I am quite novice at PHP/CodeIgniter programming, however, I enjoy it very much.
What I am trying to do:
1) Retrieve each CompanyId associated with the company when the user is logged in. I achieve this by passing the $CompanyId (in my controller) from the session as a parameter to a query in my model. I have this working well as such:
// Assign query result to array to be used in view
$data['campaigns'] = $this->model_record->retrieve_campaign($CompanyId);
2) The return value is an array nested as such:
Array (
[campaigns] => Array (
[0] => Array (
[CampaignId] => 1
[DID] => 2394434444
[FWDDID] => 3214822821
[ProductId] => 1
[CampaignName] => Fort Myers Bus #1
[ProductName] => CallTrack - Sharktek
[Active] => 1
[CompanyId] => 1 )
)
3) Once this is processed, I am trying to create a for each loop that queries each CampaignId through another query in my model. Due to the MVC pattern I am implementing, I have to pass the results of this query to my $data array to send to the view.
foreach($data['campaigns'] as $campaign) {
$ids[] = $campaign['CampaignId'];
}
foreach ($ids as $row) {
$data['ids'] = $this->model_record->week_data(0,$row, $StartDate);
}
4) I am then trying to test view all the results of my queries in my view, however, I am only receiving one value, but when I echo the results of the foreach of the CampaignIds, it they all show up. Does anyone have any suggestions?
<?php
foreach($ids as $row):
echo $ids['MyCount'];
endforeach
?>
5 Extra) I have not begun to approach this yet, but once I get this working, I would like to run the query week_data 7 times as it is returning the data for each day of the week. My assumption is that I would place a for loop until it hits 7, is this correct?
Thank you again, for attempting to help me--I greatly appreciate the work many of you put into this community.
This line:
$data['ids'] = $this->model_record->week_data(0,$row, $StartDate);
Should look like:
$data['ids'][] = $this->model_record->week_data(0,$row, $StartDate);
As it is, the first line overwrites $data['ids'] until all you're left with is the last one. You need to add them to an array to collect all of them.

Categories