Laravel make data unique but remove first duplicate - php

I got data from db:
$message = Message::where('user_id', $user->id)->get();
Result:
[
{
"id": 1,
"post_id": 3,
"agent_id": 1,
"user_id": 1,
"message": "hello",
"status": 0
},
{
"id": 2,
"post_id": 3,
"agent_id": 1,
"user_id": 1,
"sender_id": 1,
"message": "how are you?",
"status": 0
},
{
"id": 3,
"post_id": 3,
"agent_id": 1,
"user_id": 1,
"message": "Ill call you",
"status": 0
},
{
"id": 4,
"post_id": 5,
"agent_id": 1,
"user_id": 2,
"message": "hi hello",
"status": 0
}
]
Well, I able to make it unique and remove duplicate by user_id with:
$message->unique('user_id')
It return right result, but what I want is, remove first item not last, current result:
{
"0": {
"id": 1,
"post_id": 3,
"agent_id": 1,
"user_id": 1,
"message": "hello",
"status": 0
},
"3": {
"id": 4,
"post_id": 5,
"agent_id": 1,
"user_id": 2,
"message": "hi hello",
"status": 0
}
}
As you see, it keep first item and then removed next duplicate, in this case I want to keep id 3 and 4 also it made my object to array, I don't want this, how can I solve this?
But I want this result:
[
{
"id": 3,
"post_id": 3,
"agent_id": 1,
"user_id": 1,
"message": "Ill call you",
"status": 0
},
{
"id": 4,
"post_id": 5,
"agent_id": 1,
"user_id": 2,
"message": "hi hello",
"status": 0
}
]

To get the newest messages try sorting on id in a descending order
$messages = Message::where('user_id', $user->id)->orderBy('id', 'DESC')->get();
and you are receiving a Collection you call toArray on it to get back an array:
return $messages->unique('user_id')->toArray();

Use sorting before unique.
$message = Message::where('user_id', $user->id)->orderBy('id','desc')->get();
$message->unique('user_id');

Related

How to modify nested Laravel collection using group by

I want to modify nested collection using group by.
This is sample collection
"document": [
{
"id": 1,
"company_id": 4,
"client_id": 1,
"status": 1,
"client": {
"id": 1,
"company_id": 4,
"name": "1663159185735-client"
},
"document_items": [
{
"id": 1,
"master_id": 5,
"text_value": "piyo",
},
{
"id": 2,
"master_id": 5,
"text_value": "fuga",
},
{
"id": 3,
"master_id": 3,
"text_value": "hoge",
}
]
}
]
I want to change like this.
"document": [
{
"id": 1,
"company_id": 4,
"client_id": 1,
"status": 1,
"client": {
"id": 1,
"company_id": 4,
"name": "1663159185735-client"
},
"document_items": [
5: [{
"id": 1,
"master_id": 5,
"text_value": "piyo",
},
{
"id": 2,
"master_id": 5,
"text_value": "fuga",
}
],
3: [{
"id": 2,
"master_id": 5,
"text_value": "fuga",
       }
     ]
]
}
]
I try write below code;
$result->map(function ($v){
$v->documentItems = $v->documentItems->groupBy('master_id');
return $v;
});
but output key is documentItems not document_items
I changed to
$v->document_items = $v->documentItems->groupBy('master_id');
key is drawing_drawing_items but not groupby(simple array)
how to modify group by and preserve key case?
I changed to
$v->document_items = $v->documentItems->groupBy('master_id');
key is drawing_drawing_items but not groupby(simple array)
You should also change like this $v->document_items->groupBy('master_id')
The key is 'document_items' not 'documentItems'

Obtain KEY Value Array in variable PHP

Hi I have this array code and I need to get: user_id": 4
I just need to get the value 4 from user_id
I have this code but it doesn't work
$myvar = $request['order'][0]['user_id'];
{
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL3NpdGUudGVzdC9wdWJsaWMvYXBpL2xvZ2luIiwiaWF0IjoxNjIzODExMTE1LCJuYmYiOjE2MjM4MTExMTUsImp0aSI6Ind2bExlTlJHdkdpU2xmVUYiLCJzdWIiOjIsInBydiI6Ijg3ZTBhZjFlZjlmZDE1ODEyZmRlYzk3MTUzYTE0ZTBiMDQ3NTQ2YWEifQ.-Q56kEsHZgVEtaMzSS9Ub11imYjWjFbJMAug3Wx7WTg",
"user": {
"success": true,
"data": {
"id": 2,
"auth_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL3NpdGUudGVzdC9wdWJsaWMvYXBpL2xvZ2luIiwiaWF0IjoxNjIzODExMTE1LCJuYmYiOjE2MjM4MTExMTUsImp0aSI6Ind2bExlTlJHdkdpU2xmVUYiLCJzdWIiOjIsInBydiI6Ijg3ZTBhZjFlZjlmZDE1ODEyZmRlYzk3MTUzYTE0ZTBiMDQ3NTQ2YWEifQ.-Q56kEsHZgVEtaMzSS9Ub11imYjWjFbJMAug3Wx7WTg",
"name": "Leo",
"email": "ventas#nikostore.net",
"phone": "+51943363373",
"default_address_id": 3,
"default_address": {
"address": "mi dirección",
"house": null,
"latitude": "-1.327080900000001",
"longitude": "-10.6348053",
"tag": null
},
"delivery_pin": "51972",
"wallet_balance": 0,
"avatar": null,
"tax_number": null
},
"running_order": null,
"delivery_details": null
},
"order": [{
"selectedaddons": [{
"addon_category_name": "Comida Marina Ingredientes",
"addon_id": "2",
"addon_name": "Cangrejo Adicional",
"price": "32.00"
}],
"id": 5,
"restaurant_id": 12,
"item_category_id": 2,
"name": "Producto 1 Loquillo",
"price": "423.00",
"old_price": "0.00",
"image": "https://localhost/phpmyadmin/themes/pmahomme/img/logo_left.png",
"is_recommended": 1,
"is_popular": 1,
"is_new": 1,
"desc": "<p>321312</p>",
"placeholder_image": null,
"is_active": 1,
"is_veg": null,
"order_column": null,
"addon_categories": [{
"id": 2,
"name": "Comida Marina Ingredientes",
"type": "SINGLE",
"user_id": 4,
"created_at": "2021-06-10 20:18:37",
"updated_at": "2021-06-10 20:39:18",
"description": null,
"pivot": {
"item_id": 5,
"addon_category_id": 2
},
"addons": [{
"id": 2,
"name": "Cangrejo Adicional",
"price": "32.00",
"addon_category_id": 2,
"user_id": 4,
"created_at": "2021-06-10 20:20:30",
"updated_at": "2021-06-10 20:38:51",
"is_active": 1
}, {
"id": 3,
"name": "Pene",
"price": "95.00",
"addon_category_id": 2,
"user_id": 4,
"created_at": "2021-06-10 23:52:53",
"updated_at": "2021-06-10 23:52:53",
"is_active": 1
}]
}],
"quantity": 1
}],
"coupon": null,
"location": {
"lat": "-5.187080900000001",
"lng": "-80.6348053",
"address": "midreccion",
"house": null,
"tag": null
},
"order_comment": null,
"total": {
"productQuantity": 1,
"totalPrice": 455
},
"method": "COD",
"payment_token": "",
"delivery_type": 1,
"partial_wallet": false,
"dis": 0,
"pending_payment": false,
"tipAmount": null
}
Working from the JSON string you posted here, you need to decode it first with json_decode(). Assuming no flags are set, this will decode to a mix of objects and arrays as represented in the JSON string.
$str = '{"token": "ey...WTg",
"user": {
...
}
}'; //The JSON string you posted in the question
$request = json_decode($str);
From there the path to the user_id is:
$request->order[0]->addon_categories[0]->user_id // 4
Use foreach loop.
Assuming that you have stored array in variable $array.
Code :
foreach($array as $arr)
{
if($arr['user_id'] == 4)
{
$user = $arr;
}
}
You will get the entire object which has user_id 4, you can get related column by
$user_id = $user['user_id];
Hope this will be useful.

Laravel use toArray to add object to array and remove key [duplicate]

This question already has answers here:
How to remove index number from laravel eloquent unique
(2 answers)
Closed 3 years ago.
$message = Message::where('agent_id', $agent->id)->orderBy('id', 'DESC')->get();
I used unique() on collection and now I got this result:
{
"0": {
"id": 1,
"post_id": 3,
"agent_id": 1,
"user_id": 1,
"message": "hello",
"status": 0
},
"3": {
"id": 4,
"post_id": 5,
"agent_id": 1,
"user_id": 2,
"message": "hi hello",
"status": 0
}
}
But I want to remove key index, I mean 0 and 3, desire output is:
[
{
"id": 1,
"post_id": 3,
"agent_id": 1,
"user_id": 1,
"message": "hello",
"status": 0
},
{
"id": 4,
"post_id": 5,
"agent_id": 1,
"user_id": 2,
"message": "hi hello",
"status": 0
}
]
I tried:
$message->unique('user_id')->toArray();
But not working. any idea?
I using Laravel.
Use the values method of the Collection, similar to array_values:
$new = $message->values();
Assuming $message is the Collection holding the result of the unique call.
Laravel 6.x Docs - Collections - Available Methods - values
Try using group by groupBy('user_id')
$message = Message::where('agent_id', $agent->id)
->groupBy('user_id')
->orderBy('id', 'DESC')
->get();

How to calculate the total amount for similar keys in PHP using Laravel eloquent/collections

I currently have the below json response that the API is returning. I am able to return it using Laravel Eloquent. There are several users and each user has a several receipts. A receipt has types and status. I want to try to get the total sum amount for each receipt that is related to its type and status. I was able to return the below json response using
$this->user->with('receipts')->has('receipts')->get(['id', 'name']);
I have tried using multiple laravel collections methods https://laravel.com/docs/5.8/collections#available-methods
But I am still unable to get the desired response.
{
"id": 1,
"name": "kent",
"receipts": [
{
"id": 1,
"user_id": 1,
"type_id": 1,
"status": 0,
"amount": 100
},
{
"id": 2,
"user_id": 1,
"type_id": 1,
"status": 0,
"amount": 100
},
{
"id": 3,
"user_id": 1,
"type_id": 2,
"status": 1,
"amount": 50
},
{
"id": 4,
"user_id": 1,
"type_id": 2,
"status": 0,
"amount": 30
},
{
"id": 5,
"user_id": 1,
"type_id": 2,
"status": 0,
"amount": 30
},
{
"id": 6,
"user_id": 1,
"type_id": 1,
"status": 0,
"amount": 20
},
{
"id": 7,
"user_id": 1,
"type_id": 1,
"status": 1,
"amount": 10
}
]
},
{
"id": 2,
"name": "allison",
"receipts": [
{
"id": 9,
"user_id": 2,
"type_id": 1,
"status": 0,
"amount": 20
}
]
}
]
I expect to get the below
{
"id": 1,
"name": "kent",
"receipts": [
{
"performance and deleted": 220,
"performance and not deleted": 10,
"project and deleted": 60,
"project and deleted": 50
}
]
},
{
"id": 2,
"name": "allison",
"receipts": [
{
"performance and deleted": 20,
"performance and not deleted": 0,
"project and deleted": 0,
"project and not deleted": 0
}
]
}
]
You should be able to get the sum of amount with
$this->user->with(['receipts' => function($query) {
$query->selectRaw("SUM(amount) as amount, type_id, status, user_id")->groupBy('type_id', 'status', 'user_id');
}])->has('receipts')->get(['id', 'name']);
You can use collection methods to get the desired output
$this->user->with(['receipts' => function($query) {
$query->selectRaw("SUM(amount) as amount, type_id, status, user_id")->groupBy('type_id', 'status', 'user_id');
}])->has('receipts')->get(['id', 'name'])
->each(function ($user) {
$user->setRelation(
'receipts',
$user->receipts->mapWithKeys(function ($receipt) {
return [
$receipt->type_id . ' and ' . $receipt->status => $receipt->amount // format the key as you wish
];
})
);
})
You may use foreach and other loops to make the json you want!
use This function to convert your collection to the json you want :
public function convert(Collection $collection)
{
$result_collection = $collection;
$payment_collections = [];
foreach ($result_collection->receipts as $receipt)
{
$payment["type_id${receipt->type_id} and status${$receipt->status}"] = $receipt->amount;
}
$result_collection->receipts = $payment_collections;
return $result_collection;
}
And This is same way to get total amount. Just put an foreach and add each amount to a variable that initialized with 0;
and there is other ways like change toArray function in your Resource Collection.
I wrote the script assuming your data is a PHP array so you may change some part of my code.
For example you may change:
$row['receipts']
// To
$row->receipts
anyway
// The function in your controller
function index(){
$users=User::whereHas('receipts')->with('receipts')->get()->toArray();
return convert($users);
}
// The helper function
function convert($data){
$data=collect($data);
$allTypes=[];
$allStatuses=[];
return $data->each(function($row) use (&$allTypes,&$allStatuses){
$types=collect($row['receipts'])->pluck('type_id')->toArray();
$statuses=collect($row['receipts'])->pluck('status')->toArray();
$allTypes=array_unique(array_merge($allTypes,$types));
$allStatuses=array_unique(array_merge($allStatuses,$statuses));
})->map(function ($row,$index) use (&$allTypes,&$allStatuses){
$result=[];
$receipts=collect($row['receipts']);
foreach ($allTypes as $type){
foreach ($allStatuses as $status){
$result["type_id {$type} and status {$status}: "]=$receipts->where('type_id',$type)->where('status',$status)->sum('amount');
}
}
$row['receipts']=$result;
return $row;
});
}

Getting unique results with elasticsearch acorrding to field

I'm using FOSElasticaBundle with Symfony2 on my project and there are entry and user tables on MySQL database and each entry belongs to one user.
I want to get just one entry per a user among the whole entries from the database.
Entries Representation
[
{
"id": 1,
"name": "Hello world",
"user": {
"id": 17,
"username": "foo"
}
},
{
"id": 2,
"name": "Lorem ipsum",
"user": {
"id": 15,
"username": "bar"
}
},
{
"id": 3,
"name": "Dolar sit amet",
"user": {
"id": 17,
"username": "foo"
}
},
]
Expected result is:
[
{
"id": 1,
"name": "Hello world",
"user": {
"id": 17,
"username": "foo"
}
},
{
"id": 2,
"name": "Lorem ipsum",
"user": {
"id": 15,
"username": "bar"
}
}
]
But it returns all entries on table. I've tried to add an aggregation to my elasticsearch query and nothing changed.
$distinctAgg = new \Elastica\Aggregation\Terms("distinctAgg");
$distinctAgg->setField("user.id");
$distinctAgg->setSize(1);
$query->addAggregation($distinctAgg);
Is there any way to do this via term filter or anything else? Any help would be great. Thank you.
Aggregations are not easy to understand when you are used to MySQL group by.
The first thing, is that aggregations results are not returned in hits, but in aggregations. So when you get the result of your search, you have to get aggregations like that :
$results = $search->search();
$aggregationsResults = $results->getAggregations();
The second thing is that aggregations wont return you the source. With the aggregation of your example, you will only know that you have 1 user with ID 15, and 2 users with ID 15.
E.g. with this query :
{
"query": {
"match_all": {}
},
"aggs": {
"byUser": {
"terms": {
"field": "user.id"
}
}
}
}
Result:
{
"took": 1,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 3,
"max_score": 1,
"hits": [ ... ]
},
"aggregations": {
"byUser": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": 17,
"doc_count": 2
},
{
"key": 15,
"doc_count": 1
}
]
}
}
}
If you want to get results, the same way you would do with a GROUP BY in MySQL, you have to use a top_hits sub-aggregation:
{
"query": {
"match_all": {}
},
"aggs": {
"byUser": {
"terms": {
"field": "user.id"
},
"aggs": {
"results": {
"top_hits": {
"size": 1
}
}
}
}
}
}
Result:
{
"took": 3,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 3,
"max_score": 1,
"hits": [ ... ]
},
"aggregations": {
"byUser": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": 17,
"doc_count": 2,
"results": {
"hits": {
"total": 2,
"max_score": 1,
"hits": [
{
"_index": "test_stackoverflow",
"_type": "test1",
"_id": "1",
"_score": 1,
"_source": {
"id": 1,
"name": "Hello world",
"user": {
"id": 17,
"username": "foo"
}
}
}
]
}
}
},
{
"key": 15,
"doc_count": 1,
"results": {
"hits": {
"total": 1,
"max_score": 1,
"hits": [
{
"_index": "test_stackoverflow",
"_type": "test1",
"_id": "2",
"_score": 1,
"_source": {
"id": 2,
"name": "Lorem ipsum",
"user": {
"id": 15,
"username": "bar"
}
}
}
]
}
}
}
]
}
}
}
More informations on this page : https://www.elastic.co/blog/top-hits-aggregation

Categories