How to prevent whereRaw from automatically sort my collection? - php

I have a list of ids which are id of a collection after sorted, e.g:
$orderedIds = "2,18,4,1,17,5,6,16,15,14,13,11,12,10,9,8,7,3"
and I want to pick them out with whereRaw like this:
$result = Collection::whereRaw("FIELD(id, ".$orderedIds." )");
but the result is automatically sorted by id, which means the collection output is literally the original collection:
[
{
"id": 1,
...
}, {
"id": 2,
...
}, {
"id": 3,
...
}
]
Any option with whereRaw, or any other way around for me to achieve the sorted collection?

Try this
Collection::whereIn('id',$orderedId)->orderByRaw(DB::raw("FIELD(id, $orderedId)"))->get();

Related

Retrieve array object in a table from another table data id using a where clue in laravel

Question: I have two tables how to fetch a customer's data using order's table user_id
"order": [
{
"id": 1,
"user_id": 4
},
{
"id": 2,
"user_id": 5
}
],
"customers": [
{
"id": 5,
"name": "Mohamed Raazi",
"phone": "777",
}
],
Following code will return only the last object of an array, i need to display all the objects from user table using a where condition in customers table
for ($x=0; $x<count($orders); $x++){
$customer = User::where('id',$orders[$x]->user_id)->get();
}
I would use the ::whereIn-method where you can provide an array of IDs to and get all the users with the provided IDs.
First you would have to reformat the $orders array that you have so that it contains only user IDs. I am guessing that you are using Eloquent to fetch the orders, then you can use the pluck-function in your Eloquent-statement:
$userIds = Order::where('statement', true)->pluck('user_id')->toArray();
Please note that the where-statement is not real, I just want to illustrate how you can call the pluck-method.
Another alternative is that you use the map function on the $orders-collection and return only user IDs:
$userIds = $orders->map(function ($order) {
return $order->user_id;
});
Once you have your user IDs in an array/collection you can use it in the whereIn-statement:
$users = Users::whereIn('id', $userIds)->get();
Then this would give you all the users that that are connected to the orders you have in your order-collection.

Laravel sortBy() includes keys in the output, but sortByDesc doesn't?

I'm fetching a collection with relationship and then I try to sort by a column in one of the relationships. The output for using sortBy() is like this:
{
"1": {
"id": 1,
},
"0": {
"id": 2,
}
}
However, when I use sortByDesc() it comes out like this:
[
{
"id": 2,
},
{
"id": 1,
}
]
Is there a reason for this? It doesn't present a problem if I use it inside a Controller or View, however it is used as output in an AJAX call and breaks everything. Is there a way to have consistent output? sortByDesc() output works best for me since I don't need keys.
sortBy() and sortByDesc() behave the same way, the difference is your data.
If the sorted result has consecutive integer keys (0, 1, 2), json_encode() will return an array (your second case). Otherwise, json_encode() will return an object (your first case).
you may use something like this
$collections->sortBy(function ($collection) {
return $collection->id;
})->values();

How to count relations in laravel

How can I count for example the number of roles for a user?
When I try this:
User::with('roles')->count();
it just counts the number of users.
What I need is to return the number of roles per user. For example:
[
{
"id": 2,
"name": "user",
"roles": 2
},
{
"id": 3,
"name": "user",
"roles": 1
}
]
Eloquent does not support this out-of-the-box.
You can read this great article on how to achieve this:
How to get hasMany relation count efficiently?
If you already have the $user object, you can do the following:
$rolecount = $user->roles()->count();
Or if you are using eager loading you can drop the ( & ) at roles
$rolecount = $user->roles->count();

Mongodb $in not return correct sequence

I have query
$cursor = $collection->find(array('id' =>array('$in'=>array(4,3,2,1))), array('name'));
foreach($cursor as $fild)
{
echo $fild['name'].'<br>';
}
return
Need for speed: Most Wanted
Pro Evolution Soccer 2014
Fifa 2014
Star Craft 2
If I change order in array like (3,2,4,1).
Return
Need for speed: Most Wanted
Pro Evolution Soccer 2014
Fifa 2014
Star Craft 2
must return
Fifa 2014
Pro Evolution Soccer 2014
Star Craft 2
Need for speed: Most Wanted
What I'm doing wrong?
Essentially this is not how the $in operator works, for MongoDB or in really any equivalent form in any database. So the order you put the arguments in is not maintained in your results as you seem to be expecting them to.
There are however a couple of approaches you can take in order to achieve this. The first is by some creative use of the aggregation pipeline:
var selections = [ 4, 2, 3, 1 ];
db.collection.aggregate([
// $match is like a standard "find" query
{ "$match": {
"id": { "$in": selections }
}},
// Project your field(s) and a sorting field
{ "$project": {
"_id": 0,
"name": 1,
"order": { "$cond": [
{ "$eq": [ "$id", 4 ] },
1,
{ "$cond": [
{ "$eq": [ "$id", 2 ] },
2,
{ "$cond": [
{ "$eq": [ "$id", 3 ] },
3,
4
]}
]}
]}
}},
// Sort on the generated field
{ "$sort": { "order": } }
])
So by using the $cond operator, which is a ternary operator, you are evaluating the current value of id in order to determine which sort order to assign. Of course you would actually generate the pipeline contents for this condition in code, using a method similar to what is shown here.
Of course if that seems all a little too complex, even though you would be best off doing it that way, then you can approach the problem is a similar way using mapReduce. But as this uses JavaScript code in an interpreter and does not use native code like aggregate does, then this will run slower:
var selections = [ 4, 2, 3, 1 ];
db.collection.mapReduce(
function() {
emit(
selections.indexOf( this.id ),
this.name
);
},
function(){},
{
"query": { "id": { "$in": selections } },
"scope": { "selections": selections },
"out": { "inline": 1 }
}
)
And this way takes advantage of how mapReduce sorts the emitted key values from the mapper, so by positioning by the index value in the array you maintain the sort order.
So that gives you a couple of approaches you can use to generate a sort order "on the fly" from something like the order of arguments in an array.

Comparing JSON arrays by a specific key in PHP

I want to use the data from array A (below), but only when the item ID from array A does NOT match an ID from items in array B (also, below). How would I go about comparing these two JSON array's by the key of ID (from items) via PHP? I imagine I first need to convert them with json_decode, but I'm not sure where to go after that?
Please note that array B has more nests ("items", "something", & "posts"), unlike array A. I want to compare the ID from items, not posts.
Array A:
{
"data": [{
"category": "Games",
"id": "45345"
},
{
"category": "Music",
"id": "345345345"
},
{
"category": "Food",
"id": "1"
},
{
"category": "Pets",
"id": "13245345"
}]
}
Array B:
{
"data": {
"something": "blah",
"posts": [{
"id": "34241",
"title": "orange"
}],
"items": [{
"id": "1",
"name": "orange"
},
{
"id": "2",
"name": "dog"
},
{
"id": "3",
"name": "cat"
},
{
"id": "4",
"name": "apple"
}]
}
}
With the case above, it would run through array A and output everything from array A except for the third item, since the id of that item (1) matches one of the id's in array B items.
Based on my understanding, you need a two step process. The first is extracting the ids from the first JSON blob, and the second is filtering the second JSON blob. So basically, we have map and filter. And it just so happens we can use PHP's inbuilt functions for this:
$ids = array_map(
function($value) {
return $value['id'];
},
$array2['data']['items']
);
First, we flatten the second array's items element into the individual ids. We "map" over the data.items array, and return the $id attribute of each array. Now, we have an array of ids...
$new = array_filter(
$array1['data'],
function($var) use ($ids) {
return !in_array($var['id'], $ids);
}
);
Now, we use that to filter the first blobs array to determine if an element is new or not. So we use array filter to handle it for us. All we need to do is check the $ids array to see if the current data's id is there (and if it is, throw it away). So we want to filter the array to be only variables that are not in array of $ids (hence !in_array($var['id'], $ids)...)
Decode the items into PHP arrays. Use a SPL like array_diff() to get the results of a diff comparison.
Referances to get you started:
http://www.php.net/manual/en/function.array-diff.php
http://php.net/manual/en/function.array-diff-key.php
http://www.php.net/manual/en/function.json-decode.php
Should be about what your looking for

Categories