Laravel unique identifiers for latest foreign key in collection - php

I have a Laravel collection with record IDs and foreign keys:
{id=1, foreign_id=1},
{id=2, foreign_id=1},
{id=3, foreign_id=2},
{id=4, foreign_id=3},
{id=5, foreign_id=2}
I expect:
{id=2, foreign_id=1},
{id=5, foreign_id=2},
{id=4, foreign_id=3}
I want to search Laravel query builder for unique values ​​for foreign_id if id in collection occurs more than 1 time.
I want then to give latest foreign_id.

Try $collection->unique('foreign_id');

Here I'm giving an example, You can check by yours,
$a = collect([
[
'id' => 1,
'foreign_id' => 2
],
[
'id' => 2,
'foreign_id' => 1
],
[
'id' => 3,
'foreign_id' => 2
],
[
'id' => 4,
'foreign_id' => 3
],
[
'id' => 5,
'foreign_id' => 2
],
]);
$a->unique('foreign_id');

The easiest way to do it is to sort collection by "id" in descending order and than use unique method by "foreign_id"
$myCollection->sortByDesc('id')->unique('foreign_id')

Related

array filter of PDO result

I get PDO rows array which contains the result:
parent_id , item_id
NULL 2
NULL 3
1 5
1 8
I want a new array where parent_id is not NULl
Means
new arr=[5,8]
You need to set new array from exits or to duplicate request with IS NULL condition. With array method, your code will show like this:
$arr = [
[
'parent_id' => null,
'item_id' => 2,
],
[
'parent_id' => null,
'item_id' => 4
],
[
'parent_id' => 2,
'item_id' => 20,
],
];
$new_arr = array_filter($arr,function ($item) {
return !$item['parent_id'];
});
print_r($new_arr);

How to get rows grouped by with total count (MySQL, Laravel)

Background
We have this table lead_activity in our mysql database, with following fields
1. id
2. lead_id
3. activity
example of rows:
id
lead_id
activity
1
5
Called
2
5
Selled
3
6
Contacted
4
9
Contacted
In Laravel, I have got following query:
$this->data['lead_activities'] = LeadActivity::select(DB::Raw('count(*) as total'), 'activity')->groupBy('activity')->get();
With this result:
[
0 => [
'total' => 1,
'activity' => 'Called'
],
1 => [
'total' => 1,
'activity' => 'Selled'
],
2 => [
'total' => 2,
'activity' => 'Contacted'
],
]
Request
How can I build this query (whether Eloquent or raw SQL) so have something similar to these results within just one Query, without any for each after:
[
0 => [
'total' => 1,
'activity' => 'Called',
'lead_ids' => [5]
],
1 => [
'total' => 1,
'activity' => 'Selled'
'lead_ids' => [5],
],
2 => [
'total' => 2,
'activity' => 'Contacted',
'lead_ids' => [6,9]
],
]
Have a look at the MySQL GROUP_CONCAT() function.
I think that should solve your problem. Its not returning you an array of lead_ids but a concatenation (string) of all lead_ids, you can work with (transform to array eventually) afterwards.
$list = LeadActivity::select(DB::Raw('count(*) as total'), 'activity','GROUP_CONCAT(lead_id) as lead_id_aggr')
->groupBy('activity')
->get();
reference: https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html#function_group-concat
You can try this:
LeadActivity::query()
->select(
'activity',
DB::raw('GROUP_CONCAT(lead_id) as leads'),
DB::raw('COUNT(*) as activities_count'),
)->groupBy('activity')
->get();
which would produce this result:
Illuminate\Database\Eloquent\Collection {#2057
all: [
App\Models\LeadActivity {#2059
activity: "Called",
leads: "5",
activities_count: 1,
},
App\Models\LeadActivity {#2060
activity: "Contacted",
leads: "6,9",
activities_count: 2,
},
App\Models\LeadActivity {#2061
activity: "Sold",
leads: "5",
activities_count: 1,
},
],
}

How can I manage some irregular array to regular array?

I write code with some array that have different structure, but I must extract the data to do something else. How can I manager these array?
The array's structure are as follow:
$a = [
'pos1' => 'somedata',
'pos2' => ['data2', 'data3'],
'pos3' => '';
];
$b = [
[
'pos1' => ['data1', 'data2', ['nest1', 'nest2']],
'pos2' => ['data1', 'data2', 'data3'],
],
['data1', 'data2'],
'data4',
];
The array's Index can be a key or a position, and the value of the corresponding index may be a array with the same structure. More tough problem is that the subarray can be nesting, and the time of the nesting has different length.
Fortunately, every array has it's owe fixed structure.
I want to convert the these array to the format as follow. When the index is a value, change it to the keyword; and if the index is a keyword, nothing changed.
$a = [
'pos1' => 'somedata',
'pos2' => [
'pos2_1' => 'data2',
'pos2_2' => 'data3'
],
'pos3' => '';
];
$b = [
'pos1' => [
'pos1_1' => [
'pos1_1_1' => 'data1',
'pos1_1_2' => 'data2',
'pos1_1_3' => [
'pos1_1_3_1' => 'nest1',
'pos1_1_3_2' => 'nest2',
],
],
'pos1_2' => [
'pos1_2_1' => 'data1',
'pos1_2_2' => 'data2',
'pos1_2_3' => 'data3',
],
],
'pos2' => ['data1', 'data2'],
'pos3' => 'data4',
];
My first solution is for every array, write the function to convert the format(the keyword will specify in function). But it is a huge task and diffcult to manage.
The second solution is write a common function, with two argument: the source array and the configuration that specify the keyword to correspondent value index. For example:
$a = [0, ['pos10' => 1]];
$conf = [
// It means that when the value index is 0, it will change it into 'pos1'
'pos1' => 0,
'pos2' => 1,
];
The common funciton will generate the result of:
$result = [
'pos1' => 0,
'pos2' => ['pos10' => 1],
]
But this solution will lead to a problem: the config is diffcult to understand and design, and other people will spend a lot of time to understand the format after conversion.
Is there are some better solution to manage these array that other people can easy to use these array?
Thanks.

Best way to convert keys in PHP

Im retrieving data from a mysql database like following Array:
$data = [
0 => [
'id' => 1,
'Benutzer' => 'foo',
'Passwort' => '123456',
'Adresse' => [
'Strasse' => 'bla', 'Ort' => 'blubb'
],
'Kommentare' => [
0 => ['Titel' => 'bar', 'Text' => 'This is great dude!'],
1 => ['Titel' => 'baz', 'Text' => 'Wow, awesome!']
]
],
]
Data like this shall be stored in a mongo database and therefore i want to replace the keynames with translated strings that come from a config- or languagefile ('Benutzer' -> 'username').
Do i really have to iterate over the array and replace the keys or is the a better way to achieve that?
If you don't want to iterate over the array then you can change the column name in the query itself using select() function.
Considering your model name is Client then your query will be:
Client::select('Benutzer as username', '...') // you can use `trnas()` function here also
->get()

Laravel sync Relation with optional parameters

I use the sync function for syncing a belongsToMany Relation:
$model->products()->sync($productIds);
In the $productIds array there is flat array with some Id's -
something like this:
$productIds = [1,3,5,6];
What I want:
The pivot table has also additional columns like "created_by" and "updated_by".
But how can I add these fields to my array WITHOUT doing a foreach loop?
Is there a shorter way to do this?
I need an array like this:
$productIds = [1 => [
'created_by' => 1,
'updated_by' => 1
],3 => [
'created_by' => 1,
'updated_by' => 1
],5 => [
'created_by' => 1,
'updated_by' => 1
],6 => [
'created_by' => 1,
'updated_by' => 1
]];
Yes I know I can do it with foreach and add the columns while I loop through the array. But I want do it shorter.. is there a way to do it shorter (perhaps with laravel)?
It should be enough to pass what you have set in $productIds in your code example to sync().
This method works not only with array of integers. You can also pass an array where key is the synced ID and value is the array of pivot attributes that should be set for given ID.
This should do the trick:
$productIds = [
1 => [
'created_by' => 1,
'updated_by' => 1
]
//rest of array
];
$model->products()->sync($productIds);
Just make sure you have defined those fields as pivot fields in your relation definition.
In order to generate such table based on a list of IDs in $productIds you can do the following:
$productIds = array_fill_keys($productIds, array(
'created_by' => 1,
'updated_by' => 1,
));

Categories