3

I am using etrepat baum laravel module to store and generate hierarchy. Also using eloquent api resource to customize the json data returned.

Currently empty children are returned if no children available. Is it possible to have children only if available?

Current Result

[{
    "id": "1",
    "text": "Vegetables",
    "children": [{
        "id": "2",
        "text": "Onion",
        "children": []
    }, {
        "id": "3",
        "text": "Tomato",
        "children": []
    }, {
        "id": "4",
        "text": "Chilli",
        "children": []
    }, {
        "id": "5",
        "text": "Potato",
        "children": []
    }]
}, {
    "id": "6",
    "text": "Fruits",
    "children": [{
        "id": "7",
        "text": "Apple",
        "children": [{
            "id": "12",
            "text": "Red Apple",
            "children": []
        }, {
            "id": "13",
            "text": "Green Apple",
            "children": []
        }]
    }, {
        "id": "8",
        "text": "Banana",
        "children": [{
            "id": "14",
            "text": "Red Banana",
            "children": []
        }, {
            "id": "15",
            "text": "Yellow Banana",
            "children": []
        }]
    }, {
        "id": "9",
        "text": "Orange",
        "children": []
    }, {
        "id": "10",
        "text": "Papaya",
        "children": []
    }, {
        "id": "11",
        "text": "Guava",
        "children": []
    }]
}]

Expected Result

[{
    "id": "1",
    "text": "Vegetables",
    "children": [{
        "id": "2",
        "text": "Onion"
    }, {
        "id": "3",
        "text": "Tomato"
    }, {
        "id": "4",
        "text": "Chilli"
    }, {
        "id": "5",
        "text": "Potato"
    }]
}, {
    "id": "6",
    "text": "Fruits",
    "children": [{
        "id": "7",
        "text": "Apple",
        "children": [{
            "id": "12",
            "text": "Red Apple"
        }, {
            "id": "13",
            "text": "Green Apple"
        }]
    }, {
        "id": "8",
        "text": "Banana",
        "children": [{
            "id": "14",
            "text": "Red Banana"
        }, {
            "id": "15",
            "text": "Yellow Banana"
        }]
    }, {
        "id": "9",
        "text": "Orange"
    }, {
        "id": "10",
        "text": "Papaya"
    }, {
        "id": "11",
        "text": "Guava"
    }]
}]

CategoryResource.php

public function toArray($request) {
    return [
        'id' => (string) $this->id,
        'text' => (string) $this->name,
        'children' => CategoryResource::collection($this->children)
    ];
}

CategoryController.php

public function index()
{
        CategoryResource::withoutWrapping();
        $categories = Category::all()->toHierarchy()->values();
        return new CategoryResourceCollection($categories);
}

4 Answers 4

3

You can check before adding it to the array and if it's empty don't add it to the returned array :

public function toArray($request) {
    $result =  [
            'id' => (string) $this->id,
            'text' => (string) $this->name
        ];

    $child = CategoryResource::collection($this->children);
    if (!$child->isEmpty()) {
       $result['children'] = $child;
    }

    return $result;
}
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks a lot. Slightly modified the empty check to "if (!$child->isEmpty())" and it worked.
It's ok i thought that it return an array not a collection :p
1

In Laravel 5.7, you could use:

public function toArray($request) {
    return [
        'id' => (string) $this->id,
        'text' => (string) $this->name,
        'children' => CategoryResource::collection($this->whenLoaded('children'))
    ];
}

1 Comment

It is correct "this->whenLoaded" (so I voted up) but it will still not work because it's "loaded" but empty.
0

Correct answer for Laravel 5.7

public function toArray($request) {
    return [
        'id' => (string) $this->id,
        'text' => (string) $this->name,
        'children' => CategoryResource::collection($this->when(!$this->children->isEmpty()))
    ];
}

In this example, if the children is empty, the children key will be removed from the resource response entirely before it is sent to the client.

Comments

0

If you also need this to work correctly with Conditional Relationships (i.e. not trigger loading of each relationship just to check whether it's empty), this is the best way I could figure out (based partly on the other answers here, plus some trial and error)

public function toArray($request)
{
    $children = $this->whenLoaded('children');
    return [
        'id' => $this->id,
        'text' => $this->text,
        'children' => $this->when(method_exists($children, 'isEmpty') && !$children->isEmpty(), CategoryResource::collection($children))
    ];
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.