Laravel - Convert list object to key value - laravel

I have a list object like:
"my_list":
[
{
"id": 1,
"name": A
},
{
"id": 2,
"name": B
},
]
I want to convert to key - value like:
my_list = {
1: 'A',
2: 'B'
}
How can I do that? Does anyone have solution?
Please help, thanks!

Cast it to Laravel collection and use mapWithKeys()
$keyed = collect($my_list)->mapWithKeys(function ($item) {
return [$item['id'] => $item['name']];
});
If you need to convert it to object then:
$keyed = (object)$keyed->toArray();

You can use array helper methods combines with array_combine():
(object)array_combine(Arr::pluck($my_list, 'id'), Arr::pluck($my_list, 'name'));

Related

Laravel - Assert json array ids using wildcard

In my application I have a response like this:
{
"items": [
{
"id": 10,
"field": "foo"
},
{
"id": 20,
"field": "bar"
}
]
}
I need to test the content of items and validate each id.
I've tried many solutions but no one works, for example (this is just a kind of pseudo-code):
assertJson(fn (AssertableJson $json) =>
$json->where('items.*.id', [10, 20])
)
Is there a way to use a wildcard to pick every ID and validate using an array?
You can use array_filter:
$idArray = [10, 20];
$myObj = json_decode($json); // Turn JSON to obj
$items = $myObj["items"]; // Get items from object
// Filter the items for items that aren't in the ID list
$invalidItems = array_filter($items, function ($el) {
// If the item has an id which isn't in the array, return true
return !in_array($el["id"], $idArray);
});
// This returns true if we found 0 items with IDs not in the ID list
return $invalidItems == [];
You can similarly use array_map to simplify your array, then compare it to your ID array:
$myObj = json_decode($json); // Turn JSON to obj
$items = $myObj["items"]; // Get items from object
$outIdArray = array_map(function($el) {
return $el["id"];
}, $items);
// Compare $outIdArray to [10, 20]
Not tested yet but below should work.
We attach an each on each child element under items and add a callback to where on that id key of each child.
<?php
assertJson(fn (AssertableJson $json) =>
$json->each('items', fn (AssertableJson $childJson) =>
$childJson->where('id', fn($idVal) =>
in_array($idVal, [10,20])
)
)
)

jsonata filter by "outside" property

I need to filter values of list2 by property of list1 as such:
JSON:
{
"list1": [
{"b":1, "list2": [{"a":1},{"a":2},{"a":3}]},
{"b":2, "list2": [{"a":1},{"a":2},{"a":3}]},
{"b":3, "list2": [{"a":1},{"a":2},{"a":3}]}
]
}
JSONata:
{
"result": $$.list1.{
"v": list2[a=b].{
"v":a
}
}
}
The issue is - I don't know how to reference b property of list1 in filter list2[a=b]
https://try.jsonata.org/dxPC5s-zM
Expected result is:
{
"result": [
{"v":1},
{"v":2},
{"v":3}
]
}
I know example is "stupid" but it simply illustrate problem.
I was wondering if some temp variables could be used to solve it?
Thank you!
ok I found solution with temp. variables:
JSONata:
{
"result": $$.list1.(
$b := b; /* temp var. */
{
"v": list2[a=$b].{
"v":a
}
})
}
You can use the 'parent' operator to reference this 'outside' property. So if you are within the context of the list2 array, you can refer to the 'b' property of list1 using:
list1.list2[a = %.b]
See https://docs.jsonata.org/path-operators#-parent

How to find all documents that don't have an array or it is smaller than

I'm trying to find all documents, which either don't have an array tags or the size of the array is smaller than 2. How do I do this? I'm trying this, but doesn't work:
db.collection.find({
'text' => { '$exists' => true }, # I need this one too
'tags' => {
'$or' => [
{ '$exists' => false },
{ '$lt' => ['$size', 2] }
]
}
})
It's Ruby, btw. MongoDB version is 4.
I'm getting:
unknown operator: $or
You can use below query
db.collection.find({
text: { $exists: true },
$or: [{
tags: { $exists: false }
}, {
$expr: { $lt: [{ $size: '$tags' }, 2] }
}]
})
To slightly modify MauriRamone's answer to a smaller version:
db.getCollection('test').find({
$and:[
{"text":{$exists:true} },
{$where: "!this.tags || this.tags.length < 2"}
]
})
However, $where is slow, and other options (such as Anthony's) should be preferred.
Your original query wasn't working because $or only works in expressions, not in fields, and you need an $expr operator for the size.
try using $were in your query, like this:
db.getCollection('test').find({
$and:[
{"text":{$exists:true} },
{
$or:[
{"tags":{$exists:false}},
{$where: "this.tags.length < 2"}
]
}
]
})
I am using Robomongo to test, you should format the query to Ruby.
regards.

Change Laravel Relationship Output Structure

I'm using Laravel 5.2 and I have Role and Permission models with
Role.php
public function permissions()
{
return $this->hasMany('App\Permissions');
}
And if I call
return Role::with('permissions')->get()
it will return
[{
"id": 2,
"name": "training_vendor",
"display_name": "Training Vendor",
"description": "Role for vendor",
"created_at": "2016-06-23 08:05:47",
"updated_at": "2016-06-23 08:05:47",
"permissions": [
{
"permission_id": 1,
"role_id": 2
},
{
"permission_id": 2,
"role_id": 2
},
{
"permission_id": 3,
"role_id": 2
},
{
"permission_id": 4,
"role_id": 2
},
{
"permission_id": 5,
"role_id": 2
}
}]
Is it possible to change the "permissions" structure to something like these?
[{
"id": 2,
"name": "training_vendor",
"display_name": "Training Vendor",
"description": "Role for vendor",
"created_at": "2016-06-23 08:05:47",
"updated_at": "2016-06-23 08:05:47",
"permissions": [1,2,3,4,5]
}]
If you want to get an array (as title says), use toArray() method:
return Role::with('permissions')->get()->toArray();
It will convert the collection to an array.
If you need to get custom formatted JSON (as your example shows), use toArray(), then rebuild this array with using foreach or array_map()/array_filter() methods and encode result into JSON with json_encode().
I would recommend you to send data as is (without rebuilding it's structure) to frontend or whatever and work with it there.
I order to extract a Collection of permission IDs you can use the pluck() function:
$permissionIds = $role->permissions->pluck('permission_id');
You can also write a getter function in your Role model:
public function getPermissionIds()
{
return $this->permissions->pluck('permission_id');
}
and use it like:
$permissionIds = $role->getPermissionIds();
You can even override the magic __get() function:
public function __get($attr)
{
if ($attr === 'permissionIds') {
return $this->getPermissionIds();
} else {
return parent::__get($attr);
}
}
and access the permission IDs like an attribute:
$permissionIds = $role->permissionIds;
In Laravel 5.2 the returned value of models is a Collection instance which can be used to transform the result
$roles = Role::with('permissions')->get();
$roles->transform(function($role){
$role['permissions'] = $role['permissions']->pluck('permission_id')->toArray();
return $role;
});
return $roles;
This code will provide the desirable result.
Note: You can even chain the transform function after the get function.
I hope this answer will help to you,
$role = Role::all();
foreach ($role as $index){
$permissions= $index->permissions;
foreach ($permissions as $permission){
$permissionId[] = $permission->permission_id;
}
unset($index->permissions);
$index['all_permissions']= $permissionId;
}
return response()->json($role, 200);
This is work for me. So check for your code.

Iterate and search a JSON array for the element in the array

I have a JSON array that looks like this:
response = {
"items"=>[
{
"tags"=>[
"random"
],
"timestamp"=>12345,
"storage"=>{
"url"=>"https://example.com/example",
"key"=>"mykeys"
},
"envelope"=>{
},
"log-level"=>"info",
"id"=>"random_id_test_1",
"campaigns"=>[
],
"user-variables"=>{
},
"flags"=>{
"is-test-mode"=>false
},
"message"=>{
"headers"=>{
"to"=>"random#example.com",
"message-id"=>"foobar#example.com",
"from"=>"noreply#example.com",
"subject"=>"new subject"
},
"attachments"=>[
],
"recipients"=>[
"result#example.com"
],
"size"=>4444
},
"event"=>"stored"
},
{
"tags"=>[
"flowerPower"
],
"timestamp"=>567890,
"storage"=>{
"url"=>"https://yahoo.com",
"key"=>"some_really_cool_keys_go_here"
},
"envelope"=>{
},
"log-level"=>"info",
"id"=>"some_really_cool_ids_go_here",
"campaigns"=>[
],
"user-variables"=>{
},
"flags"=>{
"is-test-mode"=>false
},
"message"=>{
"headers"=>{
"to"=>"another_great#example.com",
"message-id"=>"email_id#example.com",
"from"=>"from#example.com",
"subject"=>"email_looks_good"
},
"attachments"=>[
],
"recipients"=>[
"example#example.com"
],
"size"=>2222
},
"event"=>"stored"
}]
}
I am trying to obtain the "storage" "url" based on the "to" email.
How do I iterate through this array where x is just the element in the array
response['items'][x]["message"]["headers"]["to"]
Once I find the specific email that I need, it will stop and return the value of x which is the element number.
I was going to use that value for x and call response['items'][x]['storage']['url']
which will return the string for the URL.
I thought about doing this but there's gotta be a better way:
x = 0
user_email = another_great#example.com
while user_email != response['items'][x]["message"]["headers"]["to"] do
x+=1
value = x
puts value
end
target =
response['items'].detect do |i|
i['message']['headers']['to'] == 'another_great#example.com'
end
then
target['storage']['url']
This is another option by creating Hash with key of to's email. And on basis of it fetch required information like this:
email_hash = Hash.new
response["items"].each do |i|
email_hash[i["message"]["headers"]["to"]] = i
end
Now if you want to fetch "storage" "url" then simply do:
user_email = "another_great#example.com"
puts email_hash[user_email]["storage"]["url"] if email_hash[user_email]
#=> "https://yahoo.com"
You can use it as #Satoru suggested. As a suggestion, if you use case involves complex queries on json data (more complex than this), then you can store your data in mongodb, and can elegantly query anything.

Resources