Merge two json array into one - php

Tried merging two JSON responses into a single one but the problem is the data is displayed in two arrays and I want it in a single array. How do I achieve it in Lumen/Laravel
Tried contatinating two arrays or responses
public function index(Request $request)
{
$post = Post::orderBy('id', 'DESC')->get();
$post_images = PostImage::orderBy('id', 'DESC')->get();
return $this->successResponse($posts.$post_image );
}
Expected:-
{
"post": {
"id": 14,
"post_id": 798965728,
"user_id": 1,
"location": "first",
"title": "un8852",
"cooked_time": "1554329910",
"dispose_time": "1554373110",
"food_type": "nv",
"description": "asdfg",
"serve_quantity": 23,
"lat": 19.08,
"lon": 73,
"id": 10,
"post_id": 798965728,
"image_name1": null,
"image_name2": null,
"image_name3": null,
"image_name4": null,
"image_name5": null,
},
"st": "1",
"msg": "success"
}
Got:-
{
"post":"{\"id\":14,\"post_id\":798965728,\"user_id\":1,\"location\":\"first\",\"title\":\"un8852\",\"cooked_time\":\"1554329910\",\"dispose_time\":\"1554373110\",\"food_type\":\"nv\",\"description\":\"asdfg\",\"serve_quantity\":23,\"lat\":19.08,\"lon\":73,\"created_at\":\"2019-04-04 10:20:18\",\"updated_at\":\"2019-04-04 10:20:18\"}{\"id\":10,\"post_id\":798965728,\"image_name1\":null,\"image_name2\":null,\"image_name3\":null,\"image_name4\":null,\"image_name5\":null,\"created_at\":\"2019-04-04 10:20:18\",\"updated_at\":\"2019-04-04 10:20:18\"}",
"st":"1",
"msg":"success"
}

There are some missing pieces there, but I think I see what's happening.
Based on the result you're getting, it looks like $posts and $post_image in this code are eloquent models.
return $this->successResponse($posts.$post_image );
When you concatenate them, their __toString() methods convert them to strings, which is done using the toJson() method. So basically you have two JSON objects stuck together, which isn't valid JSON, and then the successResponse() method encodes them again.
To merge them, you can convert them to arrays, merge those, then pass the result to successResponse().
$merged = array_merge($posts->toArray(), $post_image->toArray());
return $this->successResponse($merged);
The result you want is impossible, though. The "post" object has two different values of "id". You'll only be able to get one. If you use
$merged = array_merge($posts->toArray(), $post_image->toArray());
Then the id value of the second object will replace the first one. If you want to keep the first id value, you need to use union instead of array_merge.
$merged = $a->toArray() + $b->toArray();

You can definitely concatenate two JSON arrays, You have to parse the objects and concatenate them and re stringify.
This question might be answered here also. https://stackoverflow.com/a/10384890/1684254

I think you can't concatenate 2 JSON objects as strings.
The proper way would be to:
Get the Post and the PostImage objects
$post = Post::orderBy('id', 'DESC')->get();
$post_images = PostImage::orderBy('id', 'DESC')->get();
Serialize the Post object
https://laravel.com/docs/5.8/eloquent-serialization
Use the method described below to add each field of the PostImage object (image_name1 .. image_name5) to the JSON
How to add attribute in JSON in PHP?
Return the JSON
Update:
Post::orderBy('id','DESC')->get()-> first() returns one object.
Post::orderBy('id','DESC')->get() returns a collection of objects and it would require a different approach.
Try this:
$post = Post::orderBy('id', 'DESC')->get();
$post->map(function ($item, $key) {
$post_images = PostImage::where('post_id', $item->id)->get()->first();
$item->setAttribute('image_name1',$post_images->image_name1);
$item->setAttribute('image_name2',$post_images->image_name2);
$item->setAttribute('image_name3',$post_images->image_name3);
$item->setAttribute('image_name4',$post_images->image_name4);
$item->setAttribute('image_name5',$post_images->image_name5);
return $item;
});
return $this->successResponse($posts);

Related

Search in Json column with Laravel

In my emails table, I have a column named To with column-type Json. This is how values are stored:
[
{
"emailAddress": {
"name": "Test",
"address": "test#example.com"
}
},
{
"emailAddress": {
"name": "Test 2",
"address": "test2#example.com"
}
}
]
Now I want a collection of all emails sent to "test#example.com". I tried:
DB::table('emails')->whereJsonContains('to->emailAddress->address', 'test#example.com')->get();
(see https://laravel.com/docs/5.7/queries#json-where-clauses)
but I do not get a match. Is there a better way to search using Laravel (Eloquent)?
In the debugbar, I can see that this query is "translated" as:
select * from `emails` where json_contains(`to`->'$."emailAddress"."address"', '\"test#example.com\"'))
The arrow operator doesn't work in arrays. Use this instead:
DB::table('emails')
->whereJsonContains('to', [['emailAddress' => ['address' => 'test#example.com']]])
->get()
I haven't used the json column but as the documentation refers, the below code should work fine.
DB::table('emails')
->where('to->emailAddresss->address','test#example.com')
->get();
In case to store array in json format. And just have an array list of IDs, I did this.
items is the column name and $item_id is the term I search for
// $item_id = 2
// items = '["2","7","14","1"]'
$menus = Menu::whereJsonContains('items', $item_id)->get();
Checkout the Laravel API docs for the whereJsonContains method
https://laravel.com/api/8.x/Illuminate/Database/Query/Builder.html#method_whereJsonContains
Using Eloquent => Email::where('to->emailAddress->address','test#example.com')->get();
You can use where clause with like condition
DB::table('emails')->where('To','like','%test#example.com%')->get();
Alternatively, if you have Model mapped to emails table names as Email using Eloquent
Email::where('To','like','%test#example.com%')->get();

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 get the specific json object from laravel blade?

I am trying to get specific object from the array which is call previous_position_1_name,right now in my blade
{{$jobseeker - > jobseeker['Myprevious_position_1']}}
it output the json array like:
{
"id": 3,
"previous_position_1_name": "QC",
"created_at": null,
"updated_at": null
}
I just only want to get the previous_position_1_name column which is QC.
Please guide me.
You can use json_decode and then fetch the certain object u want in this case it's previous_position_1_name.
//Decode the json so you can access the objects.. (array)
$json = json_decode($jobseeker,true);
//Access the object you want
$previous_position_1_name = $json['previous_position_1_name'];

Search an array nested in a laravel collection

I have a api call that returns a set of data something like this:
{
"id": 97423,
"visitor_id": 231505,
"domain_sessionidx": 1,
"session_start": "2017-06-01 04:40:07",
"session_end": "2017-06-01 05:22:45",
"session_length": 2558,
"count_pages": 11,
"count_pings": 7,
"created_at": null,
"updated_at": "2017-06-12 18:59:51",
"pages": [
1829,
1811,
1829,
1501,
1829,
1889,
1762,
1686,
1825,
1825,
1825
] },....
I have put this into a variable and made a collection out of it:
$new_var = collect($result);
I am having a problem because I would like to access only the records in the data where pages contains the id 1762. I have been trying with:
$new_var->whereIn('pages',[1762])->pluck('pages')
but I am always getting an empty result. Any help is greatly appreciated.
I feel like you need to filter your $new_var collection and return true if it's pages attribute contains the page you are looking for. For example:
$page = 1762;
$inPages = $new_var->filter(function($collection) use($page){
return in_array($page, $collection->pages);
});
$inPages should now be a subset of $new_var with entries that contain 1762 in their pages array, otherwise it will be an empty Collection. Check here for more information: https://laravel.com/docs/5.4/collections

Join table fields as a single JSON object

I am building API. I ran into issue when building responses such as this one:
{
"id": 1,
"name": "Some name",
"my_joined_table": {
"joined_table_id": "10",
"some_joined_table_field": "some value"
}
},
Joining tables as described in https://laravel.com/docs/5.2/queries would yield result such as:
{
"id": 1,
"name": "Some name",
"joined_table_id": "10",
"some_joined_table_field": "some value"
},
Instead of using join I could just run two queries, one for main table, second one for secondary and then just append second array to first one and spit JSON response, but it's a lot of queries and appending if list is big!
Example code which yields second result in pseudo-code:
$data = Model::select('id', 'name', 'my_joined_table.id as joined_table_id', 'my_joined_table.some_value some_value')
->leftJoin('my_joined_table', function($join) { //conditions_callback
})->get();
return response()->json($data);
Please advice.
EDIT2:
It seems that I can use with as follows:
$data = Model::with('my_second_table')->first();
return response()->json($data);
It does what I want, only the problem, that I cannot specify fields for both first and second tables using ->first($fields) and->with(['my_second_table' => function ($query) { $query->select('id', 'some_value'); }]) unless I specify primary key of second table in ->first($fields). How do I work around this?
TL;DR; Issue: http://laravel.io/bin/YyVjd
You can probably use Laravel Eloquent relationship to achieve it.
https://laravel.com/docs/5.2/eloquent-relationships#one-to-many
Or you can remap the returned data to a new response object using $appends.
Try something here,
http://laraveldaily.com/why-use-appends-with-accessors-in-eloquent/
This is just some clues and there is a lots work to do.
FYI, you can set $visible in your model to specify which attributes is visible.

Categories