skip to Main Content

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?

2

Answers


  1. 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(IlluminateSupportCollection)#1029 (1) {
      ["items":protected]=>
      array(1) {
        [0]=>
        object(stdClass)#1030 (3) {
          ["id"]=>
          int(1)
          ["name"]=>
          string(3) "Age"
          ["tags"]=>
          object(IlluminateSupportCollection)#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)

    Login or Signup to reply.
  2. you can try this :

    $categoryTagsSorted = $categoryTags->each(
        function ($categoryTag) {
            $categoryTag = $categoryTag->tags->sortBy('name');
        }
    );
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search