Home > database >  how to sort nested array in laravel collection
how to sort nested array in laravel collection

Time:10-17

I'm trying to sort nested collection but i can't get correct results.

category tags collection

[
 {
        "id": 1,
        "name": "Age",
        "tags": [
            {
                "id": 1,
                "name": "18 "
            },
            {
                "id": 2,
                "name": "21 "
            },
            {
                "id": 3,
                "name": "25 "
            },
            {
                "id": 4,
                "name": "30 "
            },
            {
                "id": 5,
                "name": "17 "
            },
            {
                "id": 6,
                "name": "16 "
            },
            {
                "id": 7,
                "name": "26 "
            },
            {
                "id": 8,
                "name": "13 "
            },
            {
                "id": 9,
                "name": "24 "
            },
            {
                "id": 10,
                "name": "20 "
            },
            {
                "id": 11,
                "name": "19 "
            }
        ],
}
]

i'm trying to sort tags:

<?php

$categoryTagsSorted = $categoryTags->transform(
    function ($categoryTag) {
        $sortedTags = $categoryTag->tags->sortBy('name');

        // $sortedTags->values() return correct sorted array
        $categoryTag->tags = $sortedTags->values();// < - this not work
        return $categoryTag;
    }
);

$categoryTagsSorted returns untouched results, but when i assign $sortedTags to $categoryTag->newField = $sortedTags->values() i've got sorted tags in newField.

Question is how to return collection with sorted tags?

CodePudding user response:

you can try this :

$categoryTagsSorted = $categoryTags->each(
    function ($categoryTag) {
        $categoryTag = $categoryTag->tags->sortBy('name');
    }
);

CodePudding user response:

In your code I believe you have misunderstood the use of the transform() method. It is used to iterate over each item in the collection and replaces the item with the value you give it in the callback. In your code you have also simply returned the original value without applying any 'transformation' to it. If you wish to alter the value of tags on the object you could try reassigning the object property:

$categoryTags->tags = $categoryTags->tags->sortBy('name');

Read the docs on the transform method here: https://laravel.com/docs/9.x/collections#method-transform#

Update

I think you can simply use map and re-assign the tags property to accomplish the solution:

$categoryTags->map(function($categoryTag) {
    $categoryTag->tags = $categoryTag->tags->sortBy('name');
    return $categoryTag;
});

The following test code worked OK for me...

$categoryTags = collect([
    (object) [
        'id' => 1,
        'name' => 'Age',
        'tags' => collect([
            ['id' => 1, 'name' => '18 '],
            ['id' => 2, 'name' => '21 '],
            ['id' => 3, 'name' => "25 "],
            ['id' => 4, 'name' => "30 "],
            ['id' => 5, 'name' => "17 "]
        ])
    ]
]);

$categoryTags->map(function($categoryTag) {
    $categoryTag->tags = $categoryTag->tags->sortBy('name');
    return $categoryTag;
});

var_dump($categoryTags);

Output:

object(Illuminate\Support\Collection)#1029 (1) {
  ["items":protected]=>
  array(1) {
    [0]=>
    object(stdClass)#1030 (3) {
      ["id"]=>
      int(1)
      ["name"]=>
      string(3) "Age"
      ["tags"]=>
      object(Illuminate\Support\Collection)#1026 (1) {
        ["items":protected]=>
        array(5) {
          [4]=>
          array(2) {
            ["id"]=>
            int(5)
            ["name"]=>
            string(3) "17 "
          }
          [0]=>
          array(2) {
            ["id"]=>
            int(1)
            ["name"]=>
            string(3) "18 "
          }
          [1]=>
          array(2) {
            ["id"]=>
            int(2)
            ["name"]=>
            string(3) "21 "
          }
          [2]=>
          array(2) {
            ["id"]=>
            int(3)
            ["name"]=>
            string(3) "25 "
          }
          [3]=>
          array(2) {
            ["id"]=>
            int(4)
            ["name"]=>
            string(3) "30 "
          }
        }
      }
    }
  }
}
=> null

Try it out here: https://web.tinkerwell.app/#/snippets/e2c93c20-5706-4ffd-bcc0-601aae861c8b (takes a min to load)

  • Related