2

Filter tree structure based on children length | In below tree structure I want remove the array if the length of children of children is zero.Is there any way without using multiple loop and building new array?

    [{
    "id": 1,
    "name": "XYZ",
    "type": 1,
    "mapping_id": 1,
    "children": [
        {
            "id": 1,
            "name": "XYZ UAE",
            "brand_id": 1,
            "type": 2,
            "mapping_id": 2,
            "children": [
                {
                    "id": 1,
                    "name": "Dubai Airport Free Zone",
                    "country_id": 228,
                    "brand_region_id": 1,
                    "type": 3,
                    "mapping_id": 3
                }
            ]
        },
        {
            "id": 3,
            "name": "test",
            "brand_id": 1,
            "type": 2,
            "mapping_id": 0,
            "children": []
        }
    ]
},
{
    "id": 2,
    "name": "ABC",
    "type": 1,
    "mapping_id": 0,
    "children": [
        {
            "id": 2,
            "name": "ABC Restaurants UAE",
            "brand_id": 2,
            "type": 2,
            "mapping_id": 0,
            "children": []
        }
    ]}]

my code to pull data is

 $assets = $this->brand
        ->select('brands.id', 'brands.name', DB::raw('1 as type,IFNULL(supplier_asset_mappings.id,0) as mapping_id'))
        ->leftJoin('supplier_asset_mappings', function ($join) use ($supplierId) {
            $join->on('asset_id', '=', 'brands.id')
                ->where('supplier_asset_mappings.supplier_id', $supplierId)
                ->where('supplier_asset_mappings.asset_type', 1);
        })
        ->with(array('children' => function ($query) use ($supplierDeliveryCountries, $supplierId) {
            $query->select('brand_regions.id', 'brand_regions.name', 'brand_id', DB::raw('2 as type,IFNULL(supplier_asset_mappings.id,0) as mapping_id'))
                ->leftJoin('supplier_asset_mappings', function ($join) use ($supplierId) {
                    $join->on('asset_id', '=', 'brand_regions.id')
                        ->where('supplier_asset_mappings.supplier_id', $supplierId)
                        ->where('supplier_asset_mappings.asset_type', 2);
                })
                ->where('status', '=', BrandRegion::STATUS_ACTIVE);
        }, 'children.children' => function ($query) use ($supplierDeliveryCountries, $supplierId) {
            $query->select('branches.id', 'branches.name', 'country_id', 'brand_region_id', DB::raw('3 as type,IFNULL(supplier_asset_mappings.id,0) as mapping_id'))
                ->leftJoin('supplier_asset_mappings', function ($join) use ($supplierId) {
                    $join->on('asset_id', '=', 'branches.id')
                        ->where('supplier_asset_mappings.supplier_id', $supplierId)
                        ->where('supplier_asset_mappings.asset_type', 3);
                })
                ->where('branches.location_type', '=', 1)//location type is 1 for branch
                ->whereIn('country_id', $supplierDeliveryCountries)
                ->where('status', '=', Branch::STATUS_ACTIVE);
        }))
        ->where('brands.company_id', $companyId)
        ->where('brands.status', '=', Brand::STATUS_ACTIVE)
        ->get();

here I am using with function with array of relationship to get the tree structure.

3 Answers3

0

It looks like data from DB, so you just should use Eloquent has() method while getting data from DB. It will load model only if it has specified relation.

Alternatively, you could use filter() on Laravel collection or array_filter() on an array.

Alexey Mezenin
  • 158,981
  • 26
  • 290
  • 279
  • yes you are right .data is from DB. but I wonder how can I use has if my code is like this .I have updated my question please have a look .thanks – Suhail Pallimalil Oct 13 '17 at 06:21
  • @SuhailPallimalil you haven't shown any code, so I can't help. – Alexey Mezenin Oct 13 '17 at 06:24
  • @SuhailPallimalil can't help you with raw queries, sorry. But I'd really recommend you to learn Eloquent because you could get filtered data with just a few readable lines of code here instead of using huge QB/raw query and then trying to filter empty arrays. – Alexey Mezenin Oct 13 '17 at 06:28
0

Pure php alternative : you could take advantage of the function array_walk_recursive with a parameter passed by reference to inspect each node and filter out the empty leaves of your tree.

http://php.net/manual/en/function.array-walk-recursive.php

Calimero
  • 4,238
  • 1
  • 23
  • 34
0
/**
 * filter categories
 *
 * @param Builder $query
 * @param int $counter
 * @return Builder
 */
public function scopeFilter(Builder $query, $counter = 3)
{
    $label = request('label');
    $title = request('title');

    if (isset($label)) {
        $query->where('label', 'like', '%' . $label . '%');
    }

    if (isset($title)) {
        $query->where('title', 'like', '%' . $title . '%');
    }

    if ((isset($label) || isset($title)) && $counter > 0) {
        $counter -= 1;
        $query->orWhereHas('children', function (Builder $query) use ($counter) {
            return $query->filter($counter);
        });
    }

    return $query;
}
Serjikaa
  • 1
  • 1