I'm building a binary tree where I have two arrays. First array has empty tree structure and second array has actual values. Below are the structure of both arrays.
First Array
"157": {
"id": "157",
"username": "username",
"children": [
{
"id": "-1",
"parent_id": "0",
"username": "NULL",
"position": "",
"children": [
{
"id": "-1",
"parent_id": "0",
"username": "NULL",
"position": "",
"children": [
{
"id": "-1",
"parent_id": "0",
"username": "NULL",
"position": "",
"children": []
}
]
}
]
}
]
}
}
Second Array
"157": {
"id": "157",
"position": 1,
"username": "test1",
"parent_id": null,
"children": [
{
"id": "158",
"position": 1,
"parent_id": "157",
"username": "test1",
"children": [
{
"id": "159",
"position": 1,
"parent_id": "158",
"username": "test2",
"children": [
{
"id": "160",
"position": 1,
"parent_id": "159",
"username": "test3",
"children": []
}
]
}
]
}
]
}
}
I'm using array_replace_recursive function to replace empty values with actual value. It is working fine when both the arrays have same depth. For example if first array has 3 depth and second array also has 3 depth then it is working fine, but if second array has more values then first array then it is breaking array tree structure. So now I want to replace values upto depth of first array, no matter how big is second array, just replace values upto the depth first array.
Is this really possible?
Thank you!
Related
a have a comments table that has these fields: id, body, parent_id
each comment can have comments, that's why it has a parent_id column.
class Comment extends Model
{
public function comments()
{
return $this->HasMany($this, 'parent_id');
}
}
It can have child comments up to two levels only.
In my controller I retrieve the information this way:
return Comment::with('comments.comments')->get();
The resulting response is like this:
[
{
"id": 1,
"body": "test",
"parent_id": null,
"comments": [
{
"id": 2,
"body": "test",
"parent_id": 1,
"comments": [
{
"id": 3,
"body": "test",
"parent_id": 2
},
{
"id": 4,
"body": "test",
"parent_id": 2
}
]
},
{
"id": 5,
"body": "test",
"parent_id": 1,
"comments": []
}
]
},
{
"id": 2,
"body": "test",
"parent_id": 1,
"comments": [
{
"id": 3,
"body": "test",
"parent_id": 2,
"comments": []
},
{
"id": 4,
"body": "test",
"parent_id": 2,
"comments": []
}
]
},
{
"id": 3,
"body": "test",
"parent_id": 2,
"comments": []
},
{
"id": 4,
"body": "test",
"parent_id": 2,
"comments": []
},
{
"id": 5,
"body": "test",
"parent_id": 1,
"comments": []
},
{
"id": 6,
"body": "test",
"parent_id": null,
"comments": []
}
]
What I would to retrive is this:
[
{
"id": 1,
"body": "test",
"parent_id": null,
"comments": [
{
"id": 2,
"body": "test",
"parent_id": 1,
"comments": [
{
"id": 3,
"body": "test",
"parent_id": 2
},
{
"id": 4,
"body": "test",
"parent_id": 2
}
]
},
{
"id": 5,
"body": "test",
"parent_id": 1,
"comments": []
}
]
},
{
"id": 6,
"body": "test",
"parent_id": null,
"comments": []
}
]
I would like that the child comments don't repeat again at top level, what can I do?
thank you.
Add whereNull(‘parent_id’) to your top level query.
return Comment::whereNull('parent_id')->with('comments.comments')->get();
I'm struggling to remove item from recursive array if parent id don't match. All I want to display separate tree for each tree number. I didn't find any solution with SQL so now I am retrieving top nodes of that tree number and removing array those items don't have that top node ids. I already have tree structure, below I'm providing the structure of array.
{
"196": {
"id": "196",
"username": "test1",
"parent_id": null,
"children": [
{
"id": "197",
"parent_id": "196",
"flower_id": null,
"username": "test1",
"children": []
},
{
"id": "198",
"parent_id": "196",
"flower_id": "1690587",
"username": "test3",
"children": [
{
"id": "213",
"parent_id": "198",
"flower_id": "5197062",
"username": "test33",
"children": []
}
]
},
{
"id": "199",
"parent_id": "196",
"flower_id": "1690587",
"username": "test2",
"children": [
{
"id": "205",
"parent_id": "199",
"flower_id": null,
"username": null,
"children": [
{
"id": "207",
"parent_id": "205",
"flower_id": null,
"username": null,
"children": []
}
]
},
{
"id": "212",
"parent_id": "199",
"flower_id": "6794158",
"username": "gunu",
"children": []
}
]
}
]
}
}
Here is what I'm doing doing
function recursive_unset(&$array, $parentIds = array()) {
foreach ($array as $key => &$value) {
if(!in_array($value['parent_id'], $parentIds)) {
unset($array[$key]);
}
if (is_array($value['children'])) {
$this->recursive_unset($value, $parentIds);
}
}
}
This is how I'm calling this function $data = $this->recursive_unset($array, [198,199]);
Any help is appreciated.
Thanks in advance.
Im posting a multipart with text and files and trying to pass data to form, but these data are separated, so I want to combine them.
$request->request->all()
$request->files->all()
$form = $this->createForm(ParkingType::class, new Parking());
$form->submit($INeedToPassTheCombinedArray);
if ($form->isValid()) {
return $form->getData();
}
Both arrays have the same structure.
For example:
$request->request->all()
{
"name": "Test",
"taxId": "asd12",
"nationality": "england",
"parkings": [{
"total": 4,
"capacity": 928,
"places": [{
"total": 123,
"name": "test",
"address": "test"
},
{
"total": 123,
"name": "test",
"address": "test"
}
]
}]
}
$request->files->all()
{
"parkings": [{
"generalInfo": "File.pdf",
"places": [{
"logo": "File1.png"
},
{
"logo": "File2.png"
}
]
}]
}
I want to combine then in one single array, getting this:
{
"name": "Test",
"taxId": "asd12",
"nationality": "england",
"parkings": [{
"total": 4,
"capacity": 928,
"generalInfo": "File.pdf",
"places": [{
"total": 123,
"name": "test",
"address": "test",
"logo": "File1.png"
},
{
"total": 123,
"name": "test",
"address": "test",
"logo": "File2.png"
}
]
}]
}
I tried using array_merge, but the result is a single array which contain 2 arrays. It is not adding the data of one array in the respective position of the other array.
I want to know if there is some method for do this automatically and elegant.
Hope this will solve your problem
$data1 = json_decode($data,true);// first post array
$data2 = json_decode($file,true);//second file array
foreach($data1['parkings'] as $key=>&$val){ // Loop though one array
$val2 = $data2['parkings'][$key]; // Get the values from the other array
$val += $val2; // combine 'em
foreach($val['places'] as $k=>&$v){
$val3 = $val2['places'][$k]; // Get the values from the other array
$v += $val3; // combine 'em
}
}
echo json_encode($data1);
{
"name": "Test",
"taxId": "asd12",
"nationality": "england",
"parkings": [
{
"total": 4,
"capacity": 928,
"places": [
{
"total": 123,
"name": "test",
"address": "test",
"logo": "File1.png"
},
{
"total": 123,
"name": "test",
"address": "test",
"logo": "File2.png"
}
],
"generalInfo": "File.pdf"
}
]
}
Given an array, in which each index there are certain key value pairs, how do I select certain key value pairs and reject the others.
$channels = Channel::get()->toArray();
This will yield the following Array:
"channels": [
{
"id": 1,
"name": "Info Release",
"slug": "info-release",
"desc": "Contains blah blah.",
"access_level": "0",
"created_at": "2018-12-02 01:23:50",
"updated_at": "2018-12-05 07:54:41"
},
{
"id": 11,
"name": "Casual News",
"slug": "casual-news",
"desc": "Contains blah blah.",
"access_level": "0",
"created_at": "2018-12-05 05:34:50",
"updated_at": "2018-12-05 07:54:32"
},
{
"id": 12,
"name": "haha",
"slug": "haha",
"desc": "Contains blah blah.",
"access_level": "0",
"created_at": "2018-12-29 23:27:16",
"updated_at": "2018-12-29 23:27:16"
}
],
What is the best way to turn that array into this:
"channels": [
{
"id": 1,
"name": "Information Release",
"slug": "information-release",
},
{
"id": 11,
"name": "Casual News",
"slug": "casual-news",
},
{
"id": 12,
"name": "haha",
"slug": "haha",
}
],
So that if I write
$channels[0]->id
it will spit out 1
Can You try this
$viewFileds = ['id', 'name', 'slug'];
$channels = Channel::get()
->map(function ($each) use ($viewFileds) {
return Arr::only($each, $viewFileds);
});
It will return the new Collection by Only the field enabled in the $viewFileds
Hope it helps
I have a json tree with categories,
I would like to obtain the last level of elements for each different category.
For example on this json:
[
{
"category_id": "3",
"parent_id": "2",
"name": "Women",
"categories": [
{
"category_id": "11",
"parent_id": "3",
"name": "Clothing",
"categories": [
{
"category_id": "30",
"parent_id": "11",
"name": "T-shirts",
"categories": null
},
{
"category_id": "33",
"parent_id": "11",
"name": "jeans",
"categories": null
}
]
}
]
},
{
"category_id": "5",
"parent_id": "2",
"name": "Footwear ",
"categories": [
{
"category_id": "15",
"parent_id": "5",
"name": "Rings",
"categories": [
{
"category_id": "51",
"parent_id": "15",
"name": "Small Leathers",
"categories": null
}
]
},
{
"category_id": "16",
"parent_id": "5",
"name": "Bands",
"categories": [
{
"category_id": "41",
"parent_id": "16",
"name": "boots",
"categories": null
}
]
},
{
"category_id": "48",
"parent_id": "5",
"name": "Bracelets",
"categories": [
{
"category_id": "55",
"parent_id": "48",
"name": "Cocktail",
"categories": null
}
]
}
]
}
]
The result would be an array (T-shirts, Jeans, Small Leathers, boots, cocktail)
What I was thinking is to decode it on an array and search filter the array with all the categories that are null, but I'm not sure if it's the best option because the object have different levels.
(I'm sorry for the English)
Json string is not a valid. It can be made valid by enclosing the json string in {}.
$json = '{"categories": [
{
"category_id": "3",
"parent_id": "2",
"name": "Women",
"categories": [
{
"category_id": "11",
"parent_id": "3",
"name": "Clothing",
"categories": [
{
"category_id": "30",
"parent_id": "11",
"name": "T-shirts",
"categories": null
},
{
"category_id": "33",
"parent_id": "11",
"name": "jeans",
"categories": null
}
]
}
]
},
{
"category_id": "5",
"parent_id": "2",
"name": "Footwear ",
"categories": [
{
"category_id": "15",
"parent_id": "5",
"name": "Rings",
"categories": [
{
"category_id": "51",
"parent_id": "15",
"name": "Small Leathers",
"categories": null
}
]
},
{
"category_id": "16",
"parent_id": "5",
"name": "Bands",
"categories": [
{
"category_id": "41",
"parent_id": "16",
"name": "boots",
"categories": null
}
]
},
{
"category_id": "48",
"parent_id": "5",
"name": "Bracelets",
"categories": [
{
"category_id": "55",
"parent_id": "48",
"name": "Cocktail",
"categories": null
}
]
}
]
}
]}';
Decode the json string in to php opject
$json_object = json_decode($json);
Use this recursive function to fetch get all the last level categories in a array.
function getLastCategories($object){
$last_categories = array();
if(is_array($object->categories)){
foreach($object->categories as $categories){
$last_categories = array_merge( $last_categories, getLastCategories($categories));
}
}else{
$last_categories[]=$object->name;
}
return $last_categories;
}
print_r(getLastCategories($json_object));
Output:
Array
(
[0] => T-shirts
[1] => jeans
[2] => Small Leathers
[3] => boots
[4] => Cocktail
)
You can do this using recursive iterators.
$categories = json_decode($json);
// create the iterator
$iterator = new RecursiveIteratorIterator(new RecursiveArrayIterator($categories));
// iterate recursively
foreach ($iterator as $key => $subcategories) {
// if the 'categories' key is empty for the current level...
if ($key == 'categories' && !$subcategories) {
// then add the value of the 'name' key for the current level to your result array.
$result[] = $iterator->getSubIterator()->offsetGet('name');
}
}
This may not be the most efficient way to do it, but it makes the code pretty simple.